phax / as2-lib

A generic Java AS2 library, servlet and server
107 stars 43 forks source link

Trying to use RSASSA_PKCS1_V1_5_WITH_SHA3_256 signing alg results in IllegalArgumentException: Unknown signature type requested: RSASSAPSS #143

Closed michaldaniel closed 1 year ago

michaldaniel commented 1 year ago

Hi, when sending message out that uses RSASSA_PKCS1_V1_5_WITH_SHA3_256 signing algorithm configured in ECryptoAlgorithmSign:

  // id_rsassa_pkcs1_v1_5_with_sha3_256
  RSASSA_PKCS1_V1_5_WITH_SHA3_256 ("rsassa_pkcs1_v1_5_with_sha3_256",
                                   NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_256,
                                   "RSASSAPSS");

I get an error from bouncycastle DefaultSignatureAlgorithmIdentifierFinder:

Caused by: java.lang.IllegalArgumentException: Unknown signature type requested: RSASSAPSS
    at org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder.generate(Unknown Source)
    at org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder.find(Unknown Source)
    at org.bouncycastle.operator.jcajce.JcaContentSignerBuilder.build(Unknown Source)
    at org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder$NamedHelper.createContentSigner(Unknown Source)
    at org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder.build(Unknown Source)
    at com.helger.as2lib.crypto.BCCryptoHelper.sign(BCCryptoHelper.java:555)
    at com.helger.as2lib.processor.sender.AS2SenderModule.secureMimeBodyPart(AS2SenderModule.java:507)
    at com.helger.as2lib.processor.sender.AS2SenderModule.secure(AS2SenderModule.java:642)
    at com.helger.as2lib.processor.sender.AS2SenderModule.handle(AS2SenderModule.java:1010)
    ... 128 more

Looking at sources of bouncycastle DefaultSignatureAlgorithmIdentifierFinder there is no "RSASSAPSS" algorithm definition.

phax commented 1 year ago

Yes you are right. According to the matching NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_256 identifier I would go for SHA3-256WITHRSA instead. What do you think?

phax commented 1 year ago

I think the RSASSAPSS identifier works with the SunRsaSign 1.8 Security Provider, but not with BC

See e.g. https://docs.oracle.com/en/java/javase/11/security/oracle-providers.html#GUID-17E3589E-E4BA-4881-9B12-9880DD2D128D

If you need a different algorithm, just let me know

michaldaniel commented 1 year ago

Well, I am looking to sign using SHA256 with RSASSA-PSS I believe the BC equivalent of the spec I'm looking at to be SHA256withRSAandMGF1 but the label of RSASSA_PKCS1_V1_5_WITH_SHA3_256 does point to SHA3-256WITHRSA as I think RSASSA PKCS1 1.5 shouldn't use RSAPSS.

phax commented 1 year ago

Am I assuming correctly, that it is about the edi@energy requirements described in https://www.psw-group.de/blog/rsassa-pss-was-sie-ueber-den-signaturalgorithmus-wissen-muessen/6749 ???

AS2 RSASSA_PKCS1_V1_5_WITH_SHA3_256 refers to OID NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_256.

That OID is mapped to the BC algorithms SHA3-256WITHRSA and SHA3-256WITHRSAENCRYPTION.

Can you easily make a locally patched version and try out if it works? Or shall I create a new version adding this enum entry and you try it then?

michaldaniel commented 1 year ago

Yes, it's about edi@energry, the RSASSA_PKCS1_V1_5_WITH_SHA3_256 should refer to "SHA3-256WITHRSA" (BC) but the described SHA256 with RSASSA-PSS that I need would refer to "SHA256withRSAandMGF1" in BC if I'm not mistaken and could be added under RSASSA_PSS_WITH_SHA256.

I'm working on creating locally patched version to test this.

michaldaniel commented 1 year ago

I made changes over at my local clone but I'm waiting for the opportunity to test them. This should work both with SunRsaSign and BC and be equivalent but under correct enum labeling.

michaldaniel commented 1 year ago

I ended up running into next error:

Caused by: java.security.NoSuchAlgorithmException: no such algorithm: 1.2.840.113549.1.1.10 for provider BC
at java.base/sun.security.jca.GetInstance.getService(GetInstance.java:87)
at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.base/java.security.MessageDigest.getInstance(MessageDigest.java:248)
at com.helger.as2lib.crypto.BCCryptoHelper.calculateMIC(BCCryptoHelper.java:322)
at com.helger.as2lib.processor.sender.AS2SenderModule.calculateAndStoreMIC(AS2SenderModule.java:395)
at com.helger.as2lib.processor.sender.AS2SenderModule.handle(AS2SenderModule.java:1016)
... 128 more

Probably by my choice of PKCSObjectIdentifiers.id_RSASSA_PSS for ASN1ObjectIdentifier aOID in ECryptoAlgorithmSign enum, but I'm struggling to figure out correct values to use.

michaldaniel commented 1 year ago

@phax I also noticed that ECryptoAlgorithmSign ID is used in MIC .toString(), so if I want to use RSASSA-PSS with SHA256 shouldn't that value be sha-256 paired with using "SHA256withRSAandMGF1" encryption, and NISTObjectIdentifiers.id_sha25 for MIC generation?

This setup does result in expected test failures:

[ERROR]   ECryptoAlgorithmSignTest.testBasic:58 expected same:<RSASSA_PSS_WITH_SHA256> was not:<DIGEST_SHA_256>
[INFO] 

But doesn't that suggest that mic algo should be decoupled from sign algo? Or am I getting all this structures wrong?

Using entry

RSASSA_PSS_WITH_SHA256("sha-256", NISTObjectIdentifiers.id_sha256, "SHA256WITHRSAANDMGF1");

I was able to establish communication with partner but naturally it required hacking away "sha-256" definition.

phax commented 1 year ago

Statement from RFC 4130, chapter 7.4.3:

For signed messages, the algorithm used to calculate the MIC MUST be the same as that used on the message that was signed.

The definition of "Use of the RSASSA-PSS Signature Algorithm in Cryptographic Message Syntax (CMS)" can be found in https://www.rfc-editor.org/rfc/rfc4056

Technically it seems to be

So if you give your entry in the enum a separate ID, it should be okay:

  RSASSA_PSS_WITH_SHA256 ("sha-256-with-rsa-and-mgf1",
                                     NISTObjectIdentifiers.id_rsassa_pkcs1_v1_5_with_sha3_256,
                                   "SHA256WITHRSAANDMGF1");

As the algorithm is not officially supported by AS2 you are outside the spec anyway - a decision edi@energy choose on purpose I guess....

michaldaniel commented 1 year ago

But signing with RSASSA-PSS with SHA256 consist of message digest with SHA256, then RSASSA-PSS signature, if we still had NONEWITHRSASSA-PSS we could separate it into two steps:

  1. Digest message

MessageDigest digestor = MessageDigest.getInstance("SHA256", "BC"); byte[] messageSha256 = digestor.digest(message);

3. Sign with RSASSA-PSS

Signature signator = Signature.getInstance("NONEWITHRSASSA-PSS", "BC"); MGF1ParameterSpec mgfParams = new MGF1ParameterSpec("SHA256"); PSSParameterSpec pssParams = new PSSParameterSpec("SHA256", "MGF1", mgfParams, 32, 1); signator.setParameter(pssParams); signator.initSign(privateKey); signator.update(messageSha256); byte[] signature = signator.sign();


BC, SUN, SunRsaSign, SunEC, SunJSSE, SunJCE, SunJGSS, SunSASL, XMLDSig, SunPCSC, JdkLDAP, JdkSASL, SunPKCS11 crypto providers don't recognize id_rsassa_pkcs1_v1_5_with_sha3_256, or any rsassa-pss identifier as valid digestion algorithm.

Cosnidering that MIC is calcuated using MessageDigest wouldn't that mean it's correct to use configurations like:

/**

Those seems to work with our test environment configured to accept RSASSA-PSS signatures and we don't see any complaints about MIC mismatch.

phax commented 1 year ago

@michaldaniel Thanks, I implemented the 2 algorithms for the upcoming 5.0.0 release

phax commented 1 year ago

@michaldaniel you were totally right with your analysed - I kicked the RSASSA_PKCS1_V1_5_WITH_SHA3_256 again for v5 because I couldn't get it to work. Based on your original proposal I will add the following algorithms to v5 so that the SHA2 and SHA3 versions can be used.


  /**
   * RSASSA-PSS with digest algorithm SHA224.
   *
   * @since 5.0.0
   */
  RSASSA_PSS_WITH_SHA224 ("rsassa-pss-sha-224", "sha-224", NISTObjectIdentifiers.id_sha224, "SHA224WITHRSAANDMGF1"),

  /**
   * RSASSA-PSS with digest algorithm SHA256
   *
   * @since 5.0.0
   */
  RSASSA_PSS_WITH_SHA256 ("rsassa-pss-sha-256", "sha-256", NISTObjectIdentifiers.id_sha256, "SHA256WITHRSAANDMGF1"),

  /**
   * RSASSA-PSS with digest algorithm SHA384
   *
   * @since 5.0.0
   */
  RSASSA_PSS_WITH_SHA384 ("rsassa-pss-sha-384", "sha-384", NISTObjectIdentifiers.id_sha384, "SHA384WITHRSAANDMGF1"),

  /**
   * RSASSA-PSS with digest algorithm SHA512
   *
   * @since 5.0.0
   */
  RSASSA_PSS_WITH_SHA512 ("rsassa-pss-sha-512", "sha-512", NISTObjectIdentifiers.id_sha512, "SHA512WITHRSAANDMGF1"),

  /**
   * RSASSA-PSS with digest algorithm SHA3-224
   *
   * @since 5.0.0
   */
  RSASSA_PSS_WITH_SHA3_224 ("rsassa-pss-sha3-224",
                            "sha3-224",
                            NISTObjectIdentifiers.id_sha3_224,
                            "SHA3-224WITHRSAANDMGF1"),

  /**
   * RSASSA-PSS with digest algorithm SHA3-256
   *
   * @since 5.0.0
   */
  RSASSA_PSS_WITH_SHA3_256 ("rsassa-pss-sha3-256",
                            "sha3-256",
                            NISTObjectIdentifiers.id_sha3_256,
                            "SHA3-256WITHRSAANDMGF1"),

  /**
   * RSASSA-PSS with digest algorithm SHA3-384
   *
   * @since 5.0.0
   */
  RSASSA_PSS_WITH_SHA3_384 ("rsassa-pss-sha3-384",
                            "sha3-384",
                            NISTObjectIdentifiers.id_sha3_384,
                            "SHA3-384WITHRSAANDMGF1"),

  /**
   * RSASSA-PSS with digest algorithm SHA3-512
   *
   * @since 5.0.0
   */
  RSASSA_PSS_WITH_SHA3_512 ("rsassa-pss-sha3-512",
                            "sha3-512",
                            NISTObjectIdentifiers.id_sha3_512,
                            "SHA3-512WITHRSAANDMGF1")
phax commented 1 year ago

This is part of the v5.0.0 release. Closing this for now