摘要:填充算法与基本上是可以通用的。年,高级加密标准已然成为对称密钥加密中最流行的算法之一。常用库介绍是一个功能强大的加密算法扩展库。为提供了各种各样的加密算法。目前已支持的算法包括是使用编写的加密工具包。
本文示例代码详见:https://github.com/52fhy/cryp...
DESDES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。
DES使用简介使用DES需要设置加密内容、加密key、加密混淆向量iv、分组密码模式、填充模式。
加密内容:
给定的加密的数据。如果数据长度不是 n*分组大小,则在其后使用 "0" 补齐。
加密Key:
加密密钥。 如果密钥长度不是该算法所能够支持的有效长度,需要填充。如果密钥长度过长,需要截取。
加密iv:
用于CBC, CFB, OFB模式,在ECB模式里不是必须的。
分组密码模式:
常见的分组密码模式有:CBC, OFB,CFB 和 ECB。
填充模式:
Pkcs5、Pkcs7。
PKCS5Padding与PKCS7Padding基本上是可以通用的。在PKCS5Padding中,明确定义Block的大小是8位,而在PKCS7Padding定义中,对于块的大小是不确定的,可以在1-255之间(块长度超出255的尚待研究),填充值的算法都是一样的:
pad = k - (l mod k) //k=块大小,l=数据长度,如果k=8, l=9,则需要填充额外的7个byte的7
可以得出:Pkcs5是Pkcs7的特例(Block的大小始终是8位)。当Block的大小始终是8位的时候,Pkcs5和Pkcs7是一样的。(参考)
填充算法实现:
PHP
function pkcs5_pad($text) { $pad = 8 - (strlen($text) % 8); //$pad = 8 - (strlen($text) & 7); //也可以使用这种方法 return $text . str_repeat(chr($pad), $pad); } function pkcs7_pad ($text, $blocksize) { $pad = $blocksize - (strlen($text) % $blocksize); return $text . str_repeat(chr($pad), $pad); }
反填充(去掉填充的字符)只需要根据解密后内容最后一个字符,就知道填充了什么、填充了几个,然后截取掉即可:
function _unpad($text){ $pad = ord(substr($text, -1));//取最后一个字符的ASCII 码值 if ($pad < 1 || $pad > strlen($text)) { $pad = 0; } return substr($text, 0, (strlen($text) - $pad)); }
Python
from Crypto.Cipher import AES def pkcs7_pad(str): x = AES.block_size - (len(str) % AES.block_size) if x != 0: str = str + chr(x)*x return str def _unpad(msg): paddingLen = ord(msg[len(msg)-1]) return msg[0:-paddingLen]加密解密步骤
加密步骤(以PHP的扩展mcrypt为例):
1、获得加密算法的分组大小(mcrypt_get_block_size);
2、被加密的明文使用Pkcs5或Pkcs7填充;
3、加密密钥key截取或填充至8位;
4、加密向量iv设置;
5、打开指定算法和模式对应的模块,返回加密描述符td(mcrypt_module_open);
6、使用td、key、iv初始化加密所需的缓冲区 (mcrypt_generic_init);
7、加密数据(mcrypt_generic);
8、清理的加密描述符td的缓冲区(mcrypt_generic_deinit);
9、释放加密描述符td(mcrypt_module_close);
10、返回base64_encode的加密结果,可选。
解密步骤(以PHP的扩展mcrypt为例):
1、base64_decode解码,如果加密使用了base64_encode;
2、加密密钥key截取或填充至8位;
3、加密向量iv设置;
4、打开指定算法和模式对应的模块,返回加密描述符td(mcrypt_module_open);
5、使用td、key、iv初始化加密所需的缓冲区 (mcrypt_generic_init);
6、解密数据(mdecrypt_generic);
7、清理的加密描述符td的缓冲区(mcrypt_generic_deinit);
8、释放加密描述符td(mcrypt_module_close);
9、使用Pkcs5去掉填充的内容,返回解密后的结果。
使用DES需要注意下面几点:
1) 确保都使用DES + ECB;
2) 确保明文填充都使用的是Pkcs5或者Pkcs7,此时两者效果一致;
3) 加密key在DES长度必须是8字节(bytes);如果不够长必须填充,过长必须截取;
4) 加密向量iv与加密key有同样的约定;
5) 注意加密结果建议都使用base64编码。
只有以上都保持一样,各个语言里最终加密的密文才能保持一致,否则会出现:
1) 每次加密的密文不一样,但是能解密;(iv随机生成导致的)
2) 不同语言加密出来的密文不一致。
示例:
Crypt_DES.php
setKey("pwd"); //$des->setIV(" ");//默认填0,注意是双引号 $encode = base64_encode($des->encrypt($plaintext)); echo $encode. PHP_EOL; echo $des->decrypt(base64_decode($encode));
注意:Crypt_DES类里默认是MCRYPT_MODE_CBC模式,且默认会把加密向量截取或填充至8位:
str_pad(substr($key, 0, 8), 8, chr(0))
也就是如果加密向量大于8位,只会截取前8位;少于则补0。
另外加密向量iv会被设置成