PKCS5Padding與PKCS7Padding的區別


工作中,我們常常會遇到跨語言平台的加密解密算法的交互使用,特別是一些標准的加解密算法,都設計到數據塊Block與填充算法的
問題,例如C#與JAVA中的常見的填充算法如下:

.Net中的填充算法:

成員名稱 說明
ANSIX923 ANSIX923 填充字符串由一個字節序列組成,此字節序列的最后一個字節填充字節序列的長度,其余字節均填充數字零。 

下面的示例演示此模式的工作原理。假定塊長度為

 8,數據長度為 9,則填充用八位字節數等於 7,數據等於 FF FF FF FF FF FF FF FF FF:

數據: FF FF FF FF FF FF FF FF FF

X923 填充: FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 07

ISO10126 ISO10126 填充字符串由一個字節序列組成,此字節序列的最后一個字節填充字節序列的長度,其余字節填充隨機數據。 

下面的示例演示此模式的工作原理。假定塊長度為 8,數據長度為 9,則填充用八位字節數等於 7,數據等於 FF FF FF FF FF FF FF FF FF:

數據: FF FF FF FF FF FF FF FF FF

ISO10126 填充: FF FF FF FF FF FF FF FF FF 7D 2A 75 EF F8 EF 07

None 不填充。 
PKCS7 PKCS #7 填充字符串由一個字節序列組成,每個字節填充該字節序列的長度。  

下面的示例演示這些模式的工作原理。假定塊長度為 8,數據長度為 9,則填充用八位字節數等於 7,數據等於 FF FF FF FF FF FF FF FF FF:

數據: FF FF FF FF FF FF FF FF FF

PKCS7 填充: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07

Zeros 填充字符串由設置為零的字節組成。 

JAVA中支持的填充算法(Cipher)有

Alg. Name Description
NoPadding No padding.
ISO10126Padding This padding for block ciphers is described in 5.2 Block Encryption Algorithms in the W3C's "XML Encryption Syntax and Processing" document.
OAEPPadding, OAEPWith<digest>And<mgf>Padding Optimal Asymmetric Encryption Padding scheme defined in PKCS1, where <digest> should be replaced by the message digest and <mgf> by the mask generation function. Examples: OAEPWithMD5AndMGF1Padding and OAEPWithSHA-512AndMGF1Padding

If OAEPPadding is used, Cipher objects are initialized with a javax.crypto.spec.OAEPParameterSpec object to suppply values needed for OAEPPadding.
PKCS1Padding The padding scheme described in PKCS1, used with the RSA algorithm.
PKCS5Padding The padding scheme described in RSA Laboratories, "PKCS5: Password-Based Encryption Standard," version 1.5, November 1993.
SSL3Padding The padding scheme defined in the SSL Protocol Version 3.0, November 18, 1996, section 5.2.3.2 (CBC block cipher):
    block-ciphered struct {
	opaque content[SSLCompressed.length];
	opaque MAC[CipherSpec.hash_size];
	uint8 padding[
	    GenericBlockCipher.padding_length];
	uint8 padding_length;
    } GenericBlockCipher;
The size of an instance of a GenericBlockCipher must be a multiple of the block cipher's block length. 

The padding length, which is always present, contributes to the padding, which implies that if:
    sizeof(content) + sizeof(MAC) % block_length = 0, 
padding has to be (block_length - 1) bytes long, because of the existence of padding_length

This make the padding scheme similar (but not quite) to PKCS5Padding, where the padding length is encoded in the padding (and ranges from 1 to block_length). With the SSL scheme, the sizeof(padding) is encoded in the always present padding_length and therefore ranges from 0 to block_length-1.

簡單對比之下發現,通用的有NoneISO10126兩種填充法,實際上PKCS5Padding與PKCS7Padding基本上也是可以通用的。

通過研讀參考資料下面的參考資料可以發現兩者定義的區別:

      • [DefPKCS #7: Cryptographic Message Syntax Standard,
        An RSA Laboratories Technical Note, Version 1.5. Revised November 1, 1993. http://www.cnblogs.com/midea0978/admin/ftp://ftp.rsa.com/pub/pkcs/ascii/pkcs-7.asc
      • [InfPKCS #5: Password-Based Encryption Standard,
        An RSA Laboratories Technical Note, Version 1.5. Revised November 1, 1993. http://www.cnblogs.com/midea0978/admin/ftp://ftp.rsa.com/pub/pkcs/ascii/pkcs-5.asc

        在PKCS5Padding中,明確定義Block的大小是8位,而在PKCS7Padding定義中,對於塊的大小是不確定的,可以在1-255之間(塊長度超出255的尚待研究),填充值的算法都是一樣的:

        value=k - (l mod k)  ,K=塊大小,l=數據長度,如果l=8, 則需要填充額外的8個byte的8

        在.net中,例如TripleDESCryptoServiceProvider ,默認BlockSize=64bits=8bytes,所以在這種情況下在PKCS5Padding=PKCS7Padding。

        如果在C#中自己定義了一個不是64bits的加密塊大小,同時使用PKCS7Padding,那么在java中使用JDK標准的PKCS5Padding就不能解密了。

        JAVA Code示例

      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        try  {
             byte [] KEY_DATA = { 1 , 8 ,- 49 ,- 31 , 77 , 90 , 10 , 121 ,- 14 , 109 , 107 , 38 , 29 , 68 , 59 , 5 , 82 , 49 , 31 , 42 ,- 25 , 67 , 96 , 15 };
             Cipher cipher = Cipher.getInstance( "DESede/ECB/PKCS5Padding" );
             SecretKeySpec key =  new  SecretKeySpec(KEY_DATA,  "DESede" ); //生成加密解密需要的Key
             cipher.init(Cipher.ENCRYPT_MODE, key);
             byte [] res = cipher.doFinal(data.getBytes());
        catch  (Exception e) {
             e.printStackTrace();
        }

          

      •  

        C# Code示例\

      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        TripleDESCryptoServiceProvider des =  new  TripleDESCryptoServiceProvider();
        des.Mode=CipherMode.ECB;
        des.Padding=PaddingMode.PKCS7;
        byte [] buffer =Encoding.Default.GetBytes( "明文" );
        MemoryStream stream =  new  MemoryStream();
        byte [] key=Convert.FromBase64String( "AQjP4U1aCnnybWsmHUQ7BVIxHyrnQ2AP" );
        CryptoStream encStream =  new  CryptoStream(stream, des.CreateEncryptor(key,  null ), CryptoStreamMode.Write);
        encStream.Write(buffer, 0, buffer.Length);
        encStream.FlushFinalBlock();
        byte [] res=stream.ToArray();
        Console.WriteLine( "result:" +Convert.ToBase64String(res));

         

      • 參考http://www.users.zetnet.co.uk/hopwood/crypto/scan/cs.html#pad_PKCSPadding

         http://www.cnblogs.com/midea0978/articles/1437257.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM