微信公众号原文

密码学里有一个经典的问题,就是如何在不安全的信道中安全可靠地传输数据。避免自己的聊天与通信遭到偷窥,监控与河蟹。只要你手头有电脑,就可以轻易做到这一点。

问题1

现假设有两个用户翠花(Alice)与老王(Bob),正在使用偷窥狂马大帅(Oscar)家的垄断聊天软件宏信(MarcoMessage)讨论私密的事情。譬如:

老王  ------->   约吗  --------->  翠花
老王  <-------   约!<---------  翠花

消息被马大帅偷看去了,很不好,所以两人事先约定好一个秘密暗号: mimi

于是,翠花在发送消息前,使用OpenSSL对消息进行了加密处理:

echo '约吗' | openssl enc -des3 -k 'mimi'  | openssl enc -A -base64

加密结果为:

U2FsdGVkX19oIKhDajSdxib3KuoWR2Fh

翠花把这条消息贴到宏信里发给老王,老王收到这条乱码后,使用约定好的那个密码解密:

echo 'U2FsdGVkX19oIKhDajSdxib3KuoWR2Fh' | openssl enc -A -base64 -d | openssl enc -des3 -d -k 'mimi'

1.png

这里,你只需要把要加密的内容和密码替换成为你想要的东西就可以。

问题2

这次,翠花要发的秘密是一张私密的照片。假设名为 秘密.png

翠花依然使用密码mimi对这张图片进行奇妙处理:

openssl enc -des3 -k 'mimi' -in 秘密.png  | openssl enc -A -base64 > 秘密.txt

于是,照片秘密.png就变成了一堆乱码表示的秘密.txt。翠花把秘密.txt通过宏信文件发送给老王,老王心领神会,使出如下技法,秘密.txt 又变成了 解密.png,成为重新可以打开的图片了。

openssl enc -A -base64 -d -in 秘密.txt | openssl enc -des3 -d -k 'mimi' > 解密.png

2.png

这里,只要把文件名换成你想加解密的文件名就可以。

问题3

翠花与老王的密码实在太好猜了,马大帅一下就猜中了两人约定的密码。于是两人遇到了一个新的难题,如何协商出一个新的密码来。不幸的是,两人手头只有宏信可以用,总不能直接把密码发过去吧?

好在非对称加密可以解决这个问题。加解密使用同一个密钥的加密方式称为对称加密,例如上面无论是加密和解密都是用的同一个密码。还有一种神奇的加密方式,称为非对称加密。这种加密方式的原理非常简单:加密用的密钥和解密用的密钥不一样。加解密时会用到这两个不同的密码,分别称为私钥和公钥。两把钥匙都可以用来上锁,用任意一把钥匙加的锁,只能用另一把钥匙都打开:比如,用公钥上的锁,只有私钥可以打开;私钥上的锁,只有公钥可以打开。知道私钥就可以推断出公钥,但是知道公钥没办法推断出私钥。

所以基于这种特性,两个密码中的公钥可以大大方方地公开,任何人都可以使用这个公开的密码加锁,但只有私钥的持有人才能解开密文。这里,如果老王想通过不安全的聊天软件向翠花发送一条秘密信息,那么需要翠花的配合。翠花需要生成一对公私钥

# 生成私钥文件: 私钥
openssl genrsa -out 私钥 2048
# 从私钥计算生成对应的公钥文件 公钥
openssl rsa -in 私钥 -pubout -out 公钥

然后,翠花将自己的公钥通过随便什么方式发送给老王。别人拿到了也没用,因为公钥只能用来解开私钥上锁的信息,而只有公钥是无法推断出私钥的。

老王收到翠花的公钥后,把要发给翠花的秘密信息用这个公钥加密:

echo -n '有内鬼,中止交易' | openssl rsautl -encrypt -oaep -pubin -inkey 公钥 | openssl enc -A -base64

得到了一串加密后的密文,然后老王将这串乱码发送回给翠花。

ZrmUyA8zGWgEr/dPLX7QbfoZ1mUwvim0yau7LrnMFRUGh0KtxvinBBQuUpvzGr+1MAccd6hFDQPJ/CwHnlM3Kk2Da8g1SCR+CU8EReQ+CBLdbfvFXw4pjScMKsuubgY77jTKpkZQXcLnIM7DOZueEevASTX/+/J++W5IPgUhVIEiqX1tn63bVD6Jv3b7knWovv+mT97liqx8dV+JLgNvpm8/F05SGCInKZ9m7bXga3bxg/SfcI38VNKVpJnBph2gTgv0ZlFHKDxR2tFMfCfQgD2lrWaxlTdAx1QDtn1ter2whDXmazm/rUR07YvpQjBbboB2+fq5Kp44/buvj16Ksw==

翠花收到密文后,使用自己的私钥解密:

echo ZrmUyA8zGWgEr/dPLX7QbfoZ1mUwvim0yau7LrnMFRUGh0KtxvinBBQuUpvzGr+1MAccd6hFDQPJ/CwHnlM3Kk2Da8g1SCR+CU8EReQ+CBLd|bfvFXw4pjScMKsuubgY77jTKpkZQXcLnIM7DOZueEevASTX/+/J++W5IPgUhVIEiX1tn63bVD6Jv3b7knWovv+mT97liqx8dV+JLgNvpm8/F05SGCInKZ9m7bXga3bxg/SfcI38VNKVpJnBph2gTgv0ZlFHKDxR2tFMfCfQgD2lrWaxlTdAx|1QDtn1ter2whDXmazm/rUR07YvpQjBbboB2+fq5Kp44/buvj16Ksw== | openssl enc -A -base64 -d | openssl rsautl -decrypt -oaep -inkey 私钥
有内鬼,中止交易

就看到了秘密的信息:

3.jpeg

偷窥者马大帅能够看到这串密文,也能看到翠花的密钥。但他没法解密,因为非对称加密的特点就是。一把钥匙加的锁只能用另一把打开,而只知道公开的密码是没法推断出另一个私下的密码的。

4.jpeg

同理,翠花想要向老王发送秘密的时候,只需要反过来即可,老王生成公私钥对,将自己的公钥发给翠花。翠花使用老王的密钥加密后将密文发送给老王,只有老王能用自己的私钥解开来看。

就是这么简单

问题4

OpenSSL怎么安装?

Well,这个软件实在是太常见了,以至于很多操作系统都自带了它。如果你用的是Mac或者Linux,只需要打开终端/Terminal,敲openssl就可以了。如果是Windows,则需要单独下载,可以参考一些文章,譬如“windows 安装openssl”就有大把图文翔实际的教程文章,在此不再赘述。

我知道不少读者甚至都不知道怎样打开终端或者命令行,真的很想补充一篇图文并茂的教程。在Mac和Linux上你需要找到一个叫Terminal的系统自带的App打开就可以,在Windows下你可以在开始菜单搜索cmd.exe,然后按照随便哪一篇安装教程走过场即可。因为懒病和时间关系,也只能这样了。

命令小结


# 加密信息
echo '约吗' | openssl enc -des3 -k 'mimi'  | openssl enc -A -base64
echo 'U2FsdGVkX19oIKhDajSdxib3KuoWR2Fh' | openssl enc -A -base64 -d | openssl enc -des3 -d -k 'mimi'

# 加密文件
openssl enc -des3 -k 'mimi' -in 秘密.png  | openssl enc -A -base64 > 秘密.txt
openssl enc -A -base64 -d -in 秘密.txt | openssl enc -des3 -d -k 'mimi' > 解密.png

# 交换密码
# 翠花生成公私钥对,公钥发送给老王
openssl genrsa -out 私钥 2048
openssl rsa -in 私钥 -pubout -out 公钥

# 老王用公钥加密,翠花用私钥解密
echo -n '有内鬼,中止交易' | openssl rsautl -encrypt -oaep -pubin -inkey 公钥 | openssl enc -A -base64
echo '<用公钥加密的字符串>' | openssl enc -A -base64 -d | openssl rsautl -decrypt -oaep -inkey 私钥

小结

学会了上面三招(加密信息,加密文件,交换密码)之后,你就可以用任何公开的信道和任何人秘密地交换信息了。

你可以理直气壮地使用它,根据《中华人民共和国宪法》第四十条规定:中华人民共和国公民的通信自由和通信秘密受法律的保护。除因国家安全或者追查刑事犯罪的需要,由公安机关或者检察机关依照法律规定的程序对通信进行检查外,任何组织或者个人不得以任何理由侵犯公民的通信自由和通信秘密。

但一定要遵守相关法律法规,根据《中华人民共和国密码法》第三十二条规定:

第三十二条 违反本法第十二条规定,窃取他人加密保护的信息,非法侵入他人的密码保障系统,或者利用密码从事危害国家安全、社会公共利益、他人合法权益等违法活动的,由有关部门依照《中华人民共和国网络安全法》和其他有关法律、行政法规的规定追究法律责任。