摘要:填充算法與基本上是可以通用的。年,高級(jí)加密標(biāo)準(zhǔn)已然成為對(duì)稱(chēng)密鑰加密中最流行的算法之一。常用庫(kù)介紹是一個(gè)功能強(qiáng)大的加密算法擴(kuò)展庫(kù)。為提供了各種各樣的加密算法。目前已支持的算法包括是使用編寫(xiě)的加密工具包。
本文示例代碼詳見(jiàn):https://github.com/52fhy/cryp...
DESDES全稱(chēng)為Data Encryption Standard,即數(shù)據(jù)加密標(biāo)準(zhǔn),是一種使用密鑰加密的塊算法,1977年被美國(guó)聯(lián)邦政府的國(guó)家標(biāo)準(zhǔn)局確定為聯(lián)邦資料處理標(biāo)準(zhǔn)(FIPS),并授權(quán)在非密級(jí)政府通信中使用,隨后該算法在國(guó)際上廣泛流傳開(kāi)來(lái)。
DES使用簡(jiǎn)介使用DES需要設(shè)置加密內(nèi)容、加密key、加密混淆向量iv、分組密碼模式、填充模式。
加密內(nèi)容:
給定的加密的數(shù)據(jù)。如果數(shù)據(jù)長(zhǎng)度不是 n*分組大小,則在其后使用 "0" 補(bǔ)齊。
加密Key:
加密密鑰。 如果密鑰長(zhǎng)度不是該算法所能夠支持的有效長(zhǎng)度,需要填充。如果密鑰長(zhǎng)度過(guò)長(zhǎng),需要截取。
加密iv:
用于CBC, CFB, OFB模式,在ECB模式里不是必須的。
分組密碼模式:
常見(jiàn)的分組密碼模式有:CBC, OFB,CFB 和 ECB。
填充模式:
Pkcs5、Pkcs7。
PKCS5Padding與PKCS7Padding基本上是可以通用的。在PKCS5Padding中,明確定義Block的大小是8位,而在PKCS7Padding定義中,對(duì)于塊的大小是不確定的,可以在1-255之間(塊長(zhǎng)度超出255的尚待研究),填充值的算法都是一樣的:
pad = k - (l mod k) //k=塊大小,l=數(shù)據(jù)長(zhǎng)度,如果k=8, l=9,則需要填充額外的7個(gè)byte的7
可以得出:Pkcs5是Pkcs7的特例(Block的大小始終是8位)。當(dāng)Block的大小始終是8位的時(shí)候,Pkcs5和Pkcs7是一樣的。(參考)
填充算法實(shí)現(xiàn):
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); }
反填充(去掉填充的字符)只需要根據(jù)解密后內(nèi)容最后一個(gè)字符,就知道填充了什么、填充了幾個(gè),然后截取掉即可:
function _unpad($text){ $pad = ord(substr($text, -1));//取最后一個(gè)字符的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的擴(kuò)展mcrypt為例):
1、獲得加密算法的分組大小(mcrypt_get_block_size);
2、被加密的明文使用Pkcs5或Pkcs7填充;
3、加密密鑰key截取或填充至8位;
4、加密向量iv設(shè)置;
5、打開(kāi)指定算法和模式對(duì)應(yīng)的模塊,返回加密描述符td(mcrypt_module_open);
6、使用td、key、iv初始化加密所需的緩沖區(qū) (mcrypt_generic_init);
7、加密數(shù)據(jù)(mcrypt_generic);
8、清理的加密描述符td的緩沖區(qū)(mcrypt_generic_deinit);
9、釋放加密描述符td(mcrypt_module_close);
10、返回base64_encode的加密結(jié)果,可選。
解密步驟(以PHP的擴(kuò)展mcrypt為例):
1、base64_decode解碼,如果加密使用了base64_encode;
2、加密密鑰key截取或填充至8位;
3、加密向量iv設(shè)置;
4、打開(kāi)指定算法和模式對(duì)應(yīng)的模塊,返回加密描述符td(mcrypt_module_open);
5、使用td、key、iv初始化加密所需的緩沖區(qū) (mcrypt_generic_init);
6、解密數(shù)據(jù)(mdecrypt_generic);
7、清理的加密描述符td的緩沖區(qū)(mcrypt_generic_deinit);
8、釋放加密描述符td(mcrypt_module_close);
9、使用Pkcs5去掉填充的內(nèi)容,返回解密后的結(jié)果。
使用DES需要注意下面幾點(diǎn):
1) 確保都使用DES + ECB;
2) 確保明文填充都使用的是Pkcs5或者Pkcs7,此時(shí)兩者效果一致;
3) 加密key在DES長(zhǎng)度必須是8字節(jié)(bytes);如果不夠長(zhǎng)必須填充,過(guò)長(zhǎng)必須截??;
4) 加密向量iv與加密key有同樣的約定;
5) 注意加密結(jié)果建議都使用base64編碼。
只有以上都保持一樣,各個(gè)語(yǔ)言里最終加密的密文才能保持一致,否則會(huì)出現(xiàn):
1) 每次加密的密文不一樣,但是能解密;(iv隨機(jī)生成導(dǎo)致的)
2) 不同語(yǔ)言加密出來(lái)的密文不一致。
示例:
Crypt_DES.php
setKey("pwd"); //$des->setIV("