工作中,我們常常會遇到跨語言平台的加密解密算法的交互使用,特別是一些標准的加解密算法,都設計到數據塊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. |
簡單對比之下發現,通用的有None,ISO10126兩種填充法,實際上PKCS5Padding與PKCS7Padding基本上也是可以通用的。
通過研讀參考資料下面的參考資料可以發現兩者定義的區別:
- [Def] PKCS #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 - [Inf] PKCS #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示例
-
123456789
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示例\
-
1234567891011
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