phax / as2-lib

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

micalg=sha-1 vs sha1 #18

Closed undernorthernsky closed 8 years ago

undernorthernsky commented 8 years ago

I have run into a problem with a partner rejecting a message with an "unsupported mic-algorithms" error.

The mime content starts like this:

Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg=sha-1; 
    boundary="----=_Part_1_1009538009.1460639689958"

This seems to be caused by an old change in bouncycastle:

RFC 5751 changed the definition of the micalg parameters defined in RFC 3851. The SMIMESignedGenerator is now up to date with the latest micalg parameter set and a constructor has been added to allow the old micalg parameter set to be used.

https://www.rfc-editor.org/errata_search.php?rfc=4130 https://www.drummondgroup.com/images/pdf/AS2-1Q14_Issues_Resolved.pdf

The latest version of the sending participants Crypto API uses RFC 5751 which has micalg=sha-1 by default when signing data. The receiving participant required the older RFC 3851 micalg=sha1. The sending participant modified their code to accommodate the receiving participant as described in the following note. All other participants accepted either sha1 or sha-1. Note from Crypto API vendor: between RFC 3851 and RFC 5751 the values used in the micalg parameter for signed messages changed. We will accept both, but the default is now to use RFC 5751. In the event you are dealing with an RFC 3851 based system you will also need to use a constructor that sets the micalgs table and call it with RFC3851_MICALGS.

As I understand it sending "sha-1" is correct (in general); the only solution for compat with old software appears to be an additional flag (per partnership) to switch to old micalg names?

The following is minimally tested and seems to work for me:

diff --git a/as2-lib/src/main/java/com/helger/as2lib/crypto/BCCryptoHelper.java b/as2-lib/src/main/java/com/helger/as2lib/crypto/BCCryptoHelper.java
index 65670e0..b1b784f 100644
--- a/as2-lib/src/main/java/com/helger/as2lib/crypto/BCCryptoHelper.java
+++ b/as2-lib/src/main/java/com/helger/as2lib/crypto/BCCryptoHelper.java
@@ -413,7 +413,8 @@ public final class BCCryptoHelper implements ICryptoHelper
                             @Nonnull final X509Certificate aX509Cert,
                             @Nonnull final PrivateKey aPrivateKey,
                             @Nonnull final ECryptoAlgorithmSign eAlgorithm,
-                            final boolean bIncludeCertificateInSignedContent) throws GeneralSecurityException,
+                            final boolean bIncludeCertificateInSignedContent,
+                            final boolean rfc3851MicAlgs) throws GeneralSecurityException,
                                                                               SMIMEException,
                                                                               MessagingException,
                                                                               OperatorCreationException
@@ -454,7 +455,9 @@ public final class BCCryptoHelper implements ICryptoHelper
     // aSignedAttrs.add (new SMIMEEncryptionKeyPreferenceAttribute (issAndSer));

     // create the generator for creating an smime/signed message
-    final SMIMESignedGenerator aSGen = new SMIMESignedGenerator ();
+    final SMIMESignedGenerator aSGen = rfc3851MicAlgs
+            ? new SMIMESignedGenerator(SMIMESignedGenerator.RFC3851_MICALGS)
+            : new SMIMESignedGenerator ();
     // aSGen.addSigner (aPrivKey, aX509Cert, aSignDigest.getId ());

     // add a signer to the generator - this specifies we are using SHA1 and
diff --git a/as2-lib/src/main/java/com/helger/as2lib/crypto/ICryptoHelper.java b/as2-lib/src/main/java/com/helger/as2lib/crypto/ICryptoHelper.java
index dcfadae..cfe1aed 100644
--- a/as2-lib/src/main/java/com/helger/as2lib/crypto/ICryptoHelper.java
+++ b/as2-lib/src/main/java/com/helger/as2lib/crypto/ICryptoHelper.java
@@ -186,7 +186,8 @@ public interface ICryptoHelper
                      @Nonnull X509Certificate aCert,
                      @Nonnull PrivateKey aKey,
                      @Nonnull ECryptoAlgorithmSign eAlgorithm,
-                     boolean bIncludeCertificateInSignedContent) throws Exception;
+                     boolean bIncludeCertificateInSignedContent,
+                     boolean rfc3851MicAlgs) throws Exception;

   /**
    * Verify the specified Mime Body part against the part certificate
diff --git a/as2-lib/src/main/java/com/helger/as2lib/partner/CPartnershipIDs.java b/as2-lib/src/main/java/com/helger/as2lib/partner/CPartnershipIDs.java
index 6853dfe..698e762 100644
--- a/as2-lib/src/main/java/com/helger/as2lib/partner/CPartnershipIDs.java
+++ b/as2-lib/src/main/java/com/helger/as2lib/partner/CPartnershipIDs.java
@@ -81,6 +81,9 @@ public final class CPartnershipIDs
    * (using the value of the <code>getID()</code> method)
    */
   public static final String PA_ENCRYPT = "encrypt";
+  
+  public static final String PA_RFC3851_MICALGS = "rfc3851_micalgs";
+  
   /**
    * Set this to the signature digest algorithm to sign sent messages, check
    * {@link com.helger.as2lib.crypto.ECryptoAlgorithmSign} constants for values
diff --git a/as2-lib/src/main/java/com/helger/as2lib/partner/Partnership.java b/as2-lib/src/main/java/com/helger/as2lib/partner/Partnership.java
index 110a1d4..311cf12 100644
--- a/as2-lib/src/main/java/com/helger/as2lib/partner/Partnership.java
+++ b/as2-lib/src/main/java/com/helger/as2lib/partner/Partnership.java
@@ -788,6 +788,16 @@ public class Partnership implements Serializable
   {
     return setAttribute (CPartnershipIDs.PA_DISABLE_DECOMPRESS, Boolean.toString (bValue));
   }
+  
+  public boolean isRfc3851MicAlgs()
+  {
+    return m_aAttributes.getAttributeAsBoolean(CPartnershipIDs.PA_RFC3851_MICALGS, false);
+  }
+  
+  public EChange setRfc3851MicAlgs(final boolean bValue)
+  {
+    return setAttribute (CPartnershipIDs.PA_RFC3851_MICALGS, Boolean.toString(bValue));
+  }

   /**
    * @return A copy of all contained attributes. Never <code>null</code>.
diff --git a/as2-lib/src/main/java/com/helger/as2lib/processor/sender/AS2SenderModule.java b/as2-lib/src/main/java/com/helger/as2lib/processor/sender/AS2SenderModule.java
index eb59d0d..c20649f 100644
--- a/as2-lib/src/main/java/com/helger/as2lib/processor/sender/AS2SenderModule.java
+++ b/as2-lib/src/main/java/com/helger/as2lib/processor/sender/AS2SenderModule.java
@@ -348,7 +348,8 @@ public class AS2SenderModule extends AbstractHttpSenderModule

       // Main signing
       aDataBP = AS2Helper.getCryptoHelper ()
-                         .sign (aDataBP, aSenderCert, aSenderKey, eSignAlgorithm, bIncludeCertificateInSignedContent);
+                         .sign (aDataBP, aSenderCert, aSenderKey, eSignAlgorithm, bIncludeCertificateInSignedContent,
+                                 aPartnership.isRfc3851MicAlgs());

       if (s_aLogger.isDebugEnabled ())
         s_aLogger.debug ("Signed data with " +
diff --git a/as2-lib/src/main/java/com/helger/as2lib/util/AS2Helper.java b/as2-lib/src/main/java/com/helger/as2lib/util/AS2Helper.java
index d32105a..9271938 100644
--- a/as2-lib/src/main/java/com/helger/as2lib/util/AS2Helper.java
+++ b/as2-lib/src/main/java/com/helger/as2lib/util/AS2Helper.java
@@ -118,7 +118,8 @@ public final class AS2Helper
                                     @Nonnull final IMessageMDN aMdn,
                                     final boolean bSignMDN,
                                     final boolean bIncludeCertificateInSignedContent,
-                                    @Nullable final ECryptoAlgorithmSign eMICAlg) throws Exception
+                                    @Nullable final ECryptoAlgorithmSign eMICAlg,
+                                    final boolean rfc3851MicAlgs) throws Exception
   {
     ValueEnforcer.notNull (aSession, "AS2Session");
     ValueEnforcer.notNull (aMdn, "MDN");
@@ -175,7 +176,7 @@ public final class AS2Helper
                                                                     aSenderCert,
                                                                     aSenderKey,
                                                                     eMICAlg,
-                                                                    bIncludeCertificateInSignedContent);
+                                                                    bIncludeCertificateInSignedContent, rfc3851MicAlgs);
         aMdn.setData (aSignedReport);
       }
       catch (final CertificateNotFoundException ex)
@@ -322,7 +323,8 @@ public final class AS2Helper
       }
     }

-    createMDNData (aSession, aMDN, bSignMDN, bIncludeCertificateInSignedContent, aDispositionOptions.getFirstMICAlg ());
+    createMDNData (aSession, aMDN, bSignMDN, bIncludeCertificateInSignedContent, aDispositionOptions.getFirstMICAlg (),
+            aMsg.getPartnership().isRfc3851MicAlgs());

     aMDN.updateMessageID ();
phax commented 8 years ago

Thanks for pointing that out. Look at it in detail after my vacation - so next week. Looks good :)

undernorthernsky commented 8 years ago

You are welcome; enjoy your vacation.

phax commented 8 years ago

Took over your suggestions basically as they were. Thanks for pointing that out and clarifying the differences between S/MIME 3.1 and 3.2! Additionally I added support for the SHA-224 algorithm :)