【问题标题】:Bouncycastle and PKCS #1 v2.1, Signing with RSASSA-PSS & Encrypting with AES CBC with RSAES-OAEPBouncycastle 和 PKCS #1 v2.1,使用 RSASSA-PSS 签名并使用 AES CBC 和 RSAES-OAEP 加密
【发布时间】:2017-04-04 10:54:23
【问题描述】:

在这个库上花费了无数个小时之后,我仍然无法让它工作。

我想用充气城堡库发送 smime 消息,用 RSASSA-PSS 签名,用 AES 加密,其中密钥传输应该是 RSAES-OAEP,所有 P1#v2.1

Signer first,它是这样创建的:

SMIMESignedGenerator gen = new SMIMESignedGenerator();
            SignerInfoGenerator signer
            = new JcaSimpleSignerInfoGeneratorBuilder()
            .setProvider("BC")
            .build("SHA256withRSAAndMGF1", pk.getPrivateKey(), pk.getCertificate()
            );
gen.addSignerInfoGenerator(signer);
        gen.addCertificates(certStore);
        MimeMultipart mmp = gen.generate(message);

所以现在什么时候应该签名、加密和使用 OAEP 填充:

    OutputEncryptor enc = new BcCMSContentEncryptorBuilder(CMSAlgorithm.AES192_CBC).build();
        SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();

        for (X509Certificate nCert : certs) {
                RecipientInfoGenerator keyTransportRecipient = 
                new JceKeyTransRecipientInfoGenerator(nCert).setProvider("BC").
setAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption, "RSA/ECB/OAEPWithSHA256AndMGF1Padding");
                gen.addRecipientInfoGenerator(keyTransportRecipient);
        }
                MimeBodyPart encryptedMimeBodyPart = gen.generate(message, enc);

我找不到正确的 setAlgorithmMapping() 描述,所以我尝试了以下组合:

.setAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption, "RSA/NONE/PKCS1Padding");
.setAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption, "RSA/ECB/OAEPWithSHA256AndMGF1Padding");
.setAlgorithmMapping(PKCSObjectIdentifiers.id_RSAES_OAEP, "RSA/ECB/OAEPWithSHA56AndMGF1Padding");

顺便说一句,谁能解释一下,这个模式在这里到底是什么意思 - “RSA/ECB/OAEPWithSHA256AndMGF1Padding”? 如果第一个参数是公钥算法,我是否正确,第二个“ECB”是我想 ECB AES 模式? (我也尝试过 CBC 模式,但没有出现此类算法异常,也尝试过 NONE)最后一个(“OAEPWithSHA56AndMGF1Padding”)显然是 OAEP p1#v2.1,这是我真正想要的。

因此,此时应该对消息进行签名和加密。 当我现在检查我的邮箱时(使用 Thunderbird),它显示:“Thunderbird 无法解密此邮件”、“发件人使用您的一个数字证书加密了此邮件给您,但是 Thunderbird 无法解密找到这个证书和对应的私钥。”

但是,当我和老签名者签约时

build("SHA256withRSAEncryption", pk.getPrivateKey(), pk.getCertificate()

并使用旧的密钥传输方案,即

setProvider("BC").setAlgorithmMapping(PKCSObjectIdentifiers.rsaEncryption, "RSA/NONE/PKCS1Padding");

一切正常。所以显然我的自签名 x509 证书不是这里的问题,如果我在这里,请纠正我。

我还使用 Outlook (2013)

对其进行了测试

旧方案(SHA256withRSAEncryption 签名 + PKCS1Padding 密钥传输) -> 一切都很好。

新方案(SHA256withRSAAndMGF1 签名 + RSA/ECB/OAEPWithSHA256AndMGF1Padding) ->“底层安全系统找不到您的数字 ID 名称”错误。

在这一点上,我不知道实际上出了什么问题。 这就是我使用 openssl 创建证书的方式:

openssl req -new -x509 -nodes -sha256 -days 365 -newkey rsa:2048 -out certificate.cer -keyout private.key -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -passin pass:mypass -utf8 -config _openssl.cfg -extensions v3_req
openssl pkcs12 -export -out certificate.pfx -name "testname" -inkey private.key -in certificate.cer

【问题讨论】:

  • "RSA/ECB/OAEPWithSHA256AndMGF1Padding" -> RSA,要使用的密码(OAEP 可以与其他密码一起使用),ECB -> 实际上应该是 None,历史文物,RSA 的加密模式(与此字符串中的 AES 无关)并且 OAEPWithSHA256AndMGF1Padding 是使用 SHA256 为 MGF1 配置的 OAEP。由于 SHA-1 是默认设置,实际上在这里使用是安全的,我会使用它而不是 SHA-256 并尝试一下。在很多情况下,哈希更改是问题所在。
  • 我不知道答案,但如果没有其他人回答,请尝试使用 BC 开发邮件列表(并在此处报告!)。
  • 对不起,我忘了说哈希函数的选择不是我的,我必须使用sha256

标签: java cryptography rsa bouncycastle signing


【解决方案1】:

将 RSA-OAEP 的算法标识符提供给 OutputEncryptor 是错误的方法。它会(至少对我而言)导致这样的错误:

 ... no such algorithm: 1.2.840.113549.1.1.7 for provider BC

如果您想使用 AES 和 RSA-OAEP,那么您必须将 AES 分配给 OutputEncryptor(负责对称加密) 和 RSA-OAEP 到RecipientInfoGenerator(分别负责密钥加密和非对称加密)。

代码如下:

OAEPParameterSpec 的定义已经在之前的帖子中正确解释过)。

// Note that at JcaAlgorithmParametersConverter is available since BC 1.50.
JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
OAEPParameterSpec oaepParameters = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec(
        "SHA-256"), PSource.PSpecified.DEFAULT);
AlgorithmIdentifier idRsaOaep = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepParameters);

SMIMEEnvelopedGenerator encryptor = new SMIMEEnvelopedGenerator();

// Assign OAEPParameterSpec and an instance of X509Certificate to the RecipientInfoGenerator.
// prov is an instance of BouncyCastleProvider.
encryptor.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(certificate, idRsaOaep)
        .setProvider(prov));

// Use an OutputEncryptor with AES.
OutputEncryptor outputEncryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC)
        .setProvider(prov)
        .build();

// Do encryption (were plaintextMsg is a MimeMessage instance).
MimeBodyPart payload = encryptor.generate(plaintextMsg, outputEncryptor);

【讨论】:

    【解决方案2】:

    我想我解决了你的问题。至少在我的情况下它是有效的。 对于 PKCSObjectIdentifiers.id_RSAES_OAEP 的 AlgorithmIdentifier,我添加了以下代码行:

    pubilc AlgorithmIdentifier getAlgo() {
    
            JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
            OAEPParameterSpec oaepSpec = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), new PSource.PSpecified(new byte[]{1, 2, 3, 4, 5}));
        return paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepSpec);
    }
    

    使用此参数化算法标识符,您现在可以加密您的消息:

    AlgorithmIdentifier algo = getAlgo();
        SMIMEEnvelopedGenerator encrypter = new SMIMEEnvelopedGenerator();
        RecipientInfoGenerator keyTransportRecipient = 
                                new JceKeyTransRecipientInfoGenerator(cert).setProvider("BC").setAlgorithmMapping(PKCSObjectIdentifiers.id_RSAES_OAEP, "RSA/ECB/OAEPWithSHA256AndMGF1Padding");
    
    encrypter.generate(bodyPart, new JceCMSContentEncryptorBuilder(algo).setProvider("BC").build());                            encrypter.addRecipientInfoGenerator(keyTransportRecipient);
    

    您在签名问题上取得了成功吗?就我而言,Outlook 说签名无效。

    【讨论】:

    • 仍在努力。感谢 David Hook(BC 开发人员)here 让它工作,但此时遇到与您相同的问题,outlook 说签名层上一定有错误。在雷鸟中,它甚至无法打开电子邮件,至少这是一些进步。如果我知道了,我会在这里留言!谢谢
    • 我想我可能找到了问题所在。在outlook中点击签名感叹号->详细信息...->显示详细信息->切换到详细信息选项卡,会出现“未知(1.2.840.113549.1.9.52)”字段,即签名中的CMSAlgorithmProtect块,这会导致 Outlook 出现问题,至少我有 99% 的把握。还没解决,但问题可能就在这里。
    • 我在单击详细信息选项卡时收到另一条错误消息。对我来说,消息类似于“此消息可能已被修改”。
    • 是的,我也有这个。
    • Sill,我猜签名问题没有进展?
    【解决方案3】:

    我认为的问题是大多数 S/MIME 客户端不支持 RSASSA-PSS。我发现的唯一支持验证的工具(除了 BC) S/MIME RSASSA-PSS 签名是 openssl 的最新版本。

    根据 openssl 文档,这需要 openssl >= 1.1.0。

    openssl cms -verify -in email.eml -CAfile root.pem

    这仅适用于 openssl cms 命令,不适用于 openssl 微笑命令。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-22
      • 2015-08-22
      • 1970-01-01
      • 2021-09-25
      • 1970-01-01
      • 2017-01-31
      • 2013-08-11
      • 2019-04-07
      相关资源
      最近更新 更多