數據填充規則之PKCS7
安全芯片本身支持各種標準的加密算法,用戶(hù)可以使用相應的算法完成數據的加解密、簽名驗簽等功能來(lái)完善自己產(chǎn)品的安全性。在數據加解密應用中,數據填充又是其中重要的組成部分。數據填充通常有兩個(gè)作用一是按要求將數據補足到要就的塊長(cháng)度來(lái)滿(mǎn)足加密算法的應用需求;二是通過(guò)增加填充數據來(lái)進(jìn)一步提高密文的安全性。本次主要介紹分組對稱(chēng)算法中常用的PKCS7。
PKCS7是當下各大加密算法都遵循的填充算法,且 OpenSSL 加密算法默認填充算法就是 PKCS7。PKCS7Padding的填充方式為當數據長(cháng)度不足數據塊長(cháng)度時(shí),缺幾位補幾個(gè)幾,eg.對于A(yíng)ES128算法其數據塊為16Byte(數據長(cháng)度需要為16Byte的倍數),如果數據為”00112233445566778899AA”一共11個(gè)Byte,缺了5位,采用PKCS7Padding方式填充之后的數據為“00112233445566778899AA0505050505”。
特別注意的一點(diǎn)是如果是數據剛好滿(mǎn)足數據塊長(cháng)度也要在元數據后在按PKCS7規則填充一個(gè)數據塊數據,這樣做的目的是為了區分有效數據和補齊數據。仍以AES128為例:如果數據為”00112233445566778899AABBCCDDEEFF”一共16個(gè)符合數據塊規則采用PKCS7Padding方式填充之后的數據為
“00112233445566778899AABBCCDDEEFF10101010101010101010101010101010”
PKCS7是當下各大加密算法都遵循的數據填充算法,且 OpenSSL 加密算法簇的默認填充算法就是 PKCS7。
AES-128, AES-192, AES-256 的數據塊長(cháng)度分別為 128/8=16bytes, 192/8=24bytes, 256/8=32bytes。
其實(shí)PKCS7理解起來(lái)非常簡(jiǎn)單,使用需填充長(cháng)度的數值 paddingSize 所表示的ASCII碼 paddingChar = chr(paddingSize)對數據進(jìn)行冗余填充。
比如 AES-128的數據塊長(cháng)度是 16bytes,使用PKCS7進(jìn)行填充時(shí),填充的長(cháng)度范圍是 1 ~ 16。注意,當待加密數據長(cháng)度為 16 的整數倍時(shí),填充的長(cháng)度反而是最大的,要填充 16 字節,為什么呢?因為 "PKCS7" 拆包時(shí)會(huì )按協(xié)議取最后一個(gè)字節所表征的數值長(cháng)度作為數據填充長(cháng)度,如果因真實(shí)數據長(cháng)度恰好為 16 的整數倍而不進(jìn)行填充,則拆包時(shí)會(huì )導致真實(shí)數據丟失。
為什么是冗余填充呢?因為即便你的數據長(cháng)度符合blockSize的整數倍時(shí),也需要填充,填充的長(cháng)度反而是最大的,要填充blockSize個(gè)char(blockSize)字符在數據尾部,這樣犧牲了數據長(cháng)度的做法是為了更為靈活透明的去解包數據,發(fā)送端和接收端不需要約定好blockSize,接收端總能通過(guò)數據包的最后一個(gè)字符得到填充的數據長(cháng)度。
當我們拿到一串PKCS7填充的數據時(shí),取其最后一個(gè)字符paddingChar,此字符的ASCII碼的十進(jìn)制ord(paddingChar)即為填充的數據長(cháng)度paddingSize,讀取真實(shí)數據時(shí)去掉填充長(cháng)度即可substr(content, 0, -paddingSize)。
填充示例,比如數據塊blockSize為 8
h<0x07><0x07><0x07><0x07><0x07><0x07><0x07> 7 he<0x06><0x06><0x06><0x06><0x06><0x06> 6 hel<0x05><0x05><0x05><0x05><0x05> 5 hell<0x04><0x04><0x04><0x04> 4 hello<0x03><0x03><0x03> 3 hello <0x02><0x02> 2 hello w<0x01> 1 hello wo<0x08><0x08><0x08><0x08><0x08><0x08><0x08><0x08> 8 // 數據塊 hello wor<0x07><0x07><0x07><0x07><0x07><0x07><0x07> 7 hello word<0x06><0x06><0x06><0x06><0x06><0x06> 6
實(shí)現:
/** * PKCS7填充 * @param string $content 待填充內容 * @param int $block_size 待填充內容數據塊長(cháng)度 */ function pkcs7_padding($content, $block_size) { if (255 < $block_size || 0 >= $block_size) { throw new \Exception("the block size pkcs7 can padding is (0 ~ 255] "); } // 待填充的長(cháng)度 $padding_size = $block_size - (strlen($content) % $block_size); // 待填充的字符 $padding_char = chr($padding_size); $content .= str_repeat($padding_char, $padding_size); return $content; } /** * 移除PKCS7 * @param string $content * @return string */ function pkcs7_strip($content) { $padding_char = substr($content, -1); $padding_size = ord($padding_char); $content = substr($content, 0, -$padding_size); return $content; } $content = pkcs7_padding("hello", $block_size); echo pkcs7_strip($content);PKCS5
pkcs5作為pkcs7的子集算法,概念上沒(méi)有什么區別,只是在blockSize上固定為 8 bytes,即數據始終會(huì )被切割成 8 個(gè)字節的數據塊,然后計算需要填充的長(cháng)度。pkcs7的填充長(cháng)度blockSize是 1~255 bytes。
*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。