关于加密程序员应该了解的那点事(1) - 对称加密与非对称加密

Posted by 云谷计算 on February 13, 2018

对称加密

  • 原文 & 密码 -> 密文

对称加密双向可逆:即知道原文和密码就可以获得密文;获得密文和密码也可以获得原文。所以对于对称加密,密码必须严格控制,不能公开。设想下有一个1000个人的部门需要信息加密,那么所有1000人都必须要保存密码,只要其中有一个人不小心泄露了密码,整个加密机制就崩溃了。

OpenSSL采用AES256对称加解密test.cpp的示例:

# 加密
openssl enc -e -aes256 -in test.cpp -out test.cpp.enc

# 解密
openssl enc -d -aes256 -in test.cpp.enc -out test.cpp

非对称加密

  • 原文 & 私钥 -> 密文
  • 密文 & 公钥 -> 原文

非对称加密的密钥采用配对方式,采用公钥加密的密文,只有使用与这个公钥配对的私钥才能解开。这样,加密者可以保留私钥,把公钥开放给公众,任何人都可以采用这个公钥加密信息,而只有保存对应私钥的人才能解开这些信息。相比对称加密,非对称加密最大的优势在于解决了密钥传播的问题。

一个比较简单获得密钥对的命令是ssh-keygen, 比如以下命令会生产mykey密钥对,私钥是mykey,公钥是mykey.pub。

$ ssh-keygen -f ~/mykey
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/mykey.
Your public key has been saved in /root/mykey.pub.
The key fingerprint is:
SHA256:tTInYoRAlxD5K6xQpfud6atKRPm8bcUeKWTK+V/6pOA root@ecs-blog2.novalocal
The key's randomart image is:
+---[RSA 2048]----+
| .=+..           |
|  .+o.           |
|  o+. +   .      |
| .o+.* . o .     |
| o..*.+ S o      |
|..+ .= = *       |
|...o..=o. o      |
|..  .o+o =       |
|  ...oE.+..      |
+----[SHA256]-----+

OpenSSL采用非对称方式加密文件的示例:

# 加密
openssl rsautl -encrypt -inkey public_key.pem -pubin -in test.txt -out test.txt.enc

# 解密
openssl rsautl -decrypt -inkey private_key.pem -in test.txt.enc -out test.txt

值得注意的是,如果要加密的文件太大,上面的命令可能会抛出类似以下的错误:

RSA operation error
140735276269648:error:0406D06E:rsa routines:RSA_padding_add_PKCS1_type_2:data too large for key size:rsa_pk1.c:151:

这个时候,我们可以采用稍微变通的思路:

# 1. 生成一个稍微复杂的乱序密码
openssl rand -base64 64 > key.bin

# 2. 将原文用这个乱序密码进行对称加密
openssl enc -aes-256-cbc -salt -in test.txt -out test.txt.enc -pass file:key.bin

# 3. 将乱序密码进行非对称加密
openssl rsautl -encrypt -inkey public_key.pem -pubin -in key.bin -out key.bin.enc

# 4. 解密時首先使用私钥解密出乱序密码
openssl rsautl -decrypt -inkey private_key.pem -in key.bin.enc -out key.bin

# 5. 最后用乱序密码解出原文
openssl enc -d -aes-256-cbc -in test.txt.enc -out test.txt -pass file:key.bin