关于PKCS5Padding与PKCS7Padding的区别
knowledge
2016-07-10

区别

关于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 FFX923 填充: 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 FFPKCS7 填充: 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, OAEPWithAndPadding Optimal Asymmetric Encryption Padding scheme defined in PKCS1, where should be replaced by the message digest and by the mask generation function. Examples:OAEPWithMD5AndMGF1Padding and OAEPWithSHA-512AndMGF1Padding.If OAEPPadding is used, Cipher objects are initialized with ajavax.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示例
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示例
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));


其它文章