关于openssl的使用,在网上的例子都比较简单,有一些很难理解,由于我做的项目中有使用,所以将一些心得展开给大家。
在进行文件加密时,如果没有特别的要求,推荐使用对称加密方法(aes-128-cbc),详细使用如下:
1. 首先我们需要准备被加密的文件和数据。
echo "AABBCCDDEEFFGGHHMMNNOOPPQQ" > input.bin
2. 因为我们要使用aes-128-cbc算法,那么我们需要准备key值和iv值。
Key值:0123456789ABCDEF0123456789ABCDEF(最大长度32,可以使用下面命令随机生成,或者自己定义。)
iv值:FEDCBA9876543210FEDCBA9876543210(最大长度32,可以使用下面命令随机生成,或者自己定义。)
<生成随机Key值,推荐长度为32。>
cat /dev/urandom | head -n 1 | md5sum | head -c 32
第一次运行输出:c28540d871bd8ea669098540be58fef5(作为本例子Key值。)
第二层运行输出:857d3a5fca54219a068a5c4dd9615afb(作为本例子iv值。)
3. 这一步,我们使用Key值和iv值对input.bin进行加密,输出encrypt.bin。
>openssl enc -e -aes-128-cbc -in input.bin -out encrypt.bin -K c28540d871bd8ea669098540be58fef5 -iv 857d3a5fca54219a068a5c4dd9615afb -p
salt=0100000000000000
key=C28540D871BD8EA669098540BE58FEF5
iv =857D3A5FCA54219A068A5C4DD9615AFB
输出如下:
salt=0100000000000000 (自动插入的随机数作为文件内容填充使用,默认。可以使用-nosalt关闭。)
key=C28540D871BD8EA669098540BE58FEF5
iv =857D3A5FCA54219A068A5C4DD9615AFB
4. 让我们读取一下加密前和加密后的数据进行对比(16进制)。
加密前:
>xxd input.bin
00000000: 4141 4242 4343 4444 4545 4646 4747 4848 AABBCCDDEEFFGGHH
00000010: 4d4d 4e4e 4f4f 5050 5151 0a MMNNOOPPQQ.
加密后
>xxd encrypt.bin
00000000: 5ddc 8732 b01a 82b4 a704 82a6 91ee 8e19 ]..2............
00000010: bc4a 7d9f f8be 985b b10b a299 c8ad 5f59 .J}....[......_Y
这里大家应该发现点问题,加密后数据size变大了,稍后说明(备注一)。
5. 数据加密完成,那么解密看看数据是否和被加密数据一致。
>openssl aes-128-cbc -d -in encrypt.bin -out decode.bin -K c28540d871bd8ea669098540be58fef5 -iv 857d3a5fca54219a068a5c4dd9615afb -p
salt=0100000000000000
key=C28540D871BD8EA669098540BE58FEF5
iv =857D3A5FCA54219A068A5C4DD9615AFB
解密后
>xxd decode.bin
00000000: 4141 4242 4343 4444 4545 4646 4747 4848 AABBCCDDEEFFGGHH
00000010: 4d4d 4e4e 4f4f 5050 5151 0a MMNNOOPPQQ.
和加密前数据完全一样,说明是使用方法没问题,可以量产了。
6. 假设Key值错误,是否可以解密呢?我们来试试……
将Key值第一位的c改成a,测试结果如下:
>openssl aes-128-cbc -d -in encrypt.bin -out decode.bin -K a28540d871bd8ea669098540be58eef5 -iv 857d3a5fca54219a068a5c4dd9615afb -p
salt=0100000000000000
key=A28540D871BD8EA669098540BE58EEF5
iv =857D3A5FCA54219A068A5C4DD9615AFB
bad decrypt
139907769849496:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529:
最后无法输出解密结果,显示解密失败。
7. 那么假设iv值错误,是否可以解密呢?我们再来试试……
将iv值的第一位8改成9,测试结果如下:
>openssl aes-128-cbc -d -in encrypt.bin -out decode.bin -K c28540d871bd8ea669098540be58fef5 -iv 957d3a5fca54219a068a5c4dd9615afb -p
salt=0000000000000000
key=C28540D871BD8EA669098540BE58FEF5
iv =957D3A5FCA54219A068A5C4DD9615AFB
解密成功了,让我们看看解密后的文件数据。
>xxd decode.bin
00000000: 5141 4242 4343 4444 4545 4646 4747 4848 QABBCCDDEEFFGGHH
00000010: 4d4d 4e4e 4f4f 5050 5151 0a MMNNOOPPQQ.
数据错误了,第一位的A变成Q了。
综上,Key值是整个加密的关键,Key值正确才能保证解密成功,到Key值不正确,无法正常解密完成。
iv值作为打乱数据使用,虽然对加密很重要,但是iv值错误不会导致无法解密。但是数据会错误。
备注一:上面留了一个问题,加密后的数据size会增加,在项目应用中,有时候希望size保持一致。
数据增加是按照16字节补齐,我们可以使用-nopad参数,让加密后的数据不进行补齐,但是原始数据必须按照16位补齐。
你可能会说,原始数据补齐了,加密后数据也就一致了,还要-nopad参数做什么?
那你想错了,不使用-nopad的参数的情况下,即使原始数据16位补齐,加密后的数据还是会多16位。哈哈哈!
加密:openssl enc -e -aes-128-cbc -in input.bin -out encrypt.bin -K c28540d871bd8ea669098540be58fef5 -iv 857d3a5fca54219a068a5c4dd9615afb -p -nopad
解密:openssl aes-128-cbc -d -in encrypt.bin -out decode.bin -K c28540d871bd8ea669098540be58fef5 -iv 857d3a5fca54219a068a5c4dd9615afb -p -nopad
没了!!!!!