使用bouncycastle java和rsaes oaep进行加密/解密

smtd7mpg  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(1159)

我不是一个加密Maven,但我正在尝试创建一个 CMSEnvelopedDataGenerator 使用bouncycastle 1.67,其中会话密钥使用rsaes oaep加密(1.2.840.113549.1.1.7)
目前,我的代码如下所示:

CMSEnvelopedDataGenerator envelopedGenerator = new CMSEnvelopedDataGenerator();

 JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
 OAEPParameterSpec oaepSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT);

 AlgorithmIdentifier algorithmIdentifier;    
 algorithmIdentifier = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepSpec);
 JceKeyTransRecipientInfoGenerator recipent = new JceKeyTransRecipientInfoGenerator(receiverCert, algorithmIdentifier).setProvider("BC");    

 # encrypt
 CMSEnvelopedData envelopedData;
 envelopedData = envelopedGenerator.generate(
     new CMSProcessableByteArray(encodedSignedData),  
     new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC).setProvider("BC").build()
 )

但当我通过 openssl asn1parse ,我明白了

115:d=6  hl=2 l=   9 prim: OBJECT            :rsaesOaep
126:d=6  hl=2 l=  47 cons: SEQUENCE
128:d=7  hl=2 l=  15 cons: cont [ 0 ]
130:d=8  hl=2 l=  13 cons: SEQUENCE
132:d=9  hl=2 l=   9 prim: OBJECT            :sha256
143:d=9  hl=2 l=   0 prim: NULL
145:d=7  hl=2 l=  28 cons: cont [ 1 ]
147:d=8  hl=2 l=  26 cons: SEQUENCE
149:d=9  hl=2 l=   9 prim: OBJECT            :mgf1
160:d=9  hl=2 l=  13 cons: SEQUENCE
162:d=10 hl=2 l=   9 prim: OBJECT            :sha256

然后是十六进制转储。在我的参考文件中是这样的:

115:d=6  hl=2 l=   9 prim: OBJECT            :rsaesOaep
126:d=6  hl=2 l=  43 cons: SEQUENCE
128:d=7  hl=2 l=  13 cons: cont [ 0 ]
130:d=8  hl=2 l=  11 cons: SEQUENCE
132:d=9  hl=2 l=   9 prim: OBJECT            :sha256
143:d=7  hl=2 l=  26 cons: cont [ 1 ]
145:d=8  hl=2 l=  24 cons: SEQUENCE
147:d=9  hl=2 l=   9 prim: OBJECT            :mgf1
158:d=9  hl=2 l=  11 cons: SEQUENCE
160:d=10 hl=2 l=   9 prim: OBJECT            :sha256

在我档案的第143行

143:d=9  hl=2 l=   0 prim: NULL

我不知道那是从哪里来的。
当我使用对引用文件有效的解密代码时,会出现以下异常

exception unwrapping key: bad padding: unable to decrypt block

Caused by: org.bouncycastle.cms.CMSException: exception unwrapping key: bad padding: unable to decrypt block
 at org.bouncycastle.cms.jcajce.JceKeyTransRecipient.extractSecretKey(Unknown Source)
 at org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient.getRecipientOperator(Unknown Source)
 at org.bouncycastle.cms.KeyTransRecipientInformation.getRecipientOperator(Unknown Source)
 at org.bouncycastle.cms.RecipientInformation.getContentStream(Unknown Source)

Caused by: org.bouncycastle.operator.OperatorException: bad padding: unable to decrypt block
at org.bouncycastle.operator.jcajce.JceAsymmetricKeyUnwrapper.generateUnwrappedKey(Unknown Source)

Caused by: org.bouncycastle.jcajce.provider.util.BadBlockException: unable to decrypt block
at org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.getOutput(Unknown Source)
at org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(Unknown Source)
at javax.crypto.Cipher.doFinal(Cipher.java:2168)

Caused by: org.bouncycastle.crypto.InvalidCipherTextException: data wrong
at org.bouncycastle.crypto.encodings.OAEPEncoding.decodeBlock(Unknown Source)
at org.bouncycastle.crypto.encodings.OAEPEncoding.processBlock(Unknown Source)

我希望它不多,那是失踪。
编辑:
我的错误生成的文件 recipient.getKeyEncryptionAlgorithm().getParameters() 结果

[[0][2.16.840.1.101.3.4.2.1, NULL], [1][1.2.840.113549.1.1.8, [2.16.840.1.101.3.4.2.1, NULL]]]

中的正确文件

[[0][2.16.840.1.101.3.4.2.1], [1][1.2.840.113549.1.1.8, [2.16.840.1.101.3.4.2.1]]]

这些错在哪里 NULL 对于即将到来的sha-256值。

ccrfmcuu

ccrfmcuu1#

在bc创建的消息中,您只提到了一个'extra'null,但实际上有两个,第二个在您发布的数据中排除的第一行。文章中的(不同)长度字段,以及 getParameters() ,清楚地表明这一点。
那些空值没有错。
这些空值是oaep参数结构中散列算法的参数,是标准所要求的。rfc 3447=pkcs1v2.1是第一个在a.2.1中包含sha-2的版本(2003年,紧随2002年fips 186-2之后):

The parameters field ... shall have a value of type RSAES-OAEP-params:

      RSAES-OAEP-params ::= SEQUENCE {
          hashAlgorithm     [0] HashAlgorithm    DEFAULT sha1,
          maskGenAlgorithm  [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
          pSourceAlgorithm  [2] PSourceAlgorithm DEFAULT pSpecifiedEmpty
      }
...
         HashAlgorithm ::= AlgorithmIdentifier {
            {OAEP-PSSDigestAlgorithms}
         }

         OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
             { OID id-sha1 PARAMETERS NULL   }|
             { OID id-sha256 PARAMETERS NULL }|
             { OID id-sha384 PARAMETERS NULL }|
             { OID id-sha512 PARAMETERS NULL },
             ...  -- Allows for future expansion --
         }
...
         MaskGenAlgorithm ::= AlgorithmIdentifier {
            {PKCS1MGFAlgorithms}
         }
         PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
             { OID id-mgf1 PARAMETERS HashAlgorithm },
             ...  -- Allows for future expansion --
         }

请注意,这两个哈希规范(标签的外部哈希和mgf1参数中的内部哈希)都是由infoset定义的 HashAlgorithm 并且该集合中所有定义的值(包括sha-256)的参数都显式为null,而不是在通用x.509asn.1允许的情况下忽略(比较rfc5280 4.1.1.2,它使用旧的pre-infoset表示法)。
注:a.2.3中的pss也是如此,a.2.4中的rsassa-pkcs1-v15中的digestinfo有一组稍大的哈希算法。这和v2.0中的同等规定(不包括2.0中没有的pss,并且符号略有不同)可能是对pkcs1v1.5在10.1.2中仅使signature digestinfo参数成为“应该”的React(即使在2119之后也是小写,可能是因为这是rsalabs文本而不是ietf),这导致了实现上的变化,导致了有时实际上是正确的签名无法验证,这被认为是一件需要修复的坏事。
因此,您的“参考”文件在技术上违反了标准。然而,由于这些散列算法实际上不使用参数——这就是为什么它们用null编码的原因——bouncycastle可以很容易地容忍并接受省略的大小写。我用一个其他有效的结构进行了测试,它确实是双向的(如果它能处理一些不合适的值(比如插入的八位字节字符串),我也不会感到惊讶,但我没有测试它。)
即使参数编码错误,也不会导致出现异常——它可能是一个显式解码/解析错误(如“缺少必需字段”),或者是一个示例化错误(如“算法x的参数无效”)。在没有bug的情况下,“错误填充”是由损坏、篡改或其他错误的数据(在cms环境中这是非常不可能的)或不匹配的密钥引起的。
检查是否使用匹配的密钥。

相关问题