lovele0107 / signatures-conformance-checker

7 stars 0 forks source link

CAdES-Signature Validation #34

Open EichnerAdesso opened 2 years ago

EichnerAdesso commented 2 years ago

I’m trying to create a detached signature (CAdES) according to the Etsi-standard, but am having trouble getting it approved by the Etsi checker. Perhaps your could give me some insight as to what I am doing wrong? When I use the CAdES Checker (ETSI EN 319 122-1 v1.1.1 Building Blocks and Baseline) with the signature attached in the zip (test.p7s), the following errors are found:

grafik

It seems that the signer information in my signature is wrong. Regarding the 2nd error, it seems that I have not calculated the hash of the certificate correctly (which is encoded in the signingCertificateV2-attribute of the attribute table of the signer information). I use the DefaultSignedAttributeTableGenerator of BouncyCastle in Java to create the attribute table and add a sha256-hash of the certificate.

Could you please tell me how you perform the test? What hash algorithm is used? What would be the correct message-digest that the test expects? Am I on the right track or does the mentioned “message-digest” in the error message refer to the hash of the signed document?

I would be very grateful for your help or any link to more information you can give me.

test.zip

EichnerAdesso commented 2 years ago

Not sure if this is helpful, but here is the code snipped that I use to create the signingCertificateV2-Attribute in java with bouncy castle:

private CMSAttributeTableGenerator getCmsAttributeTableGenerator(X509Certificate certificate) throws Exception {

        ASN1EncodableVector attributeVector = new ASN1EncodableVector();
        attributeVector.add(new Attribute(CMSAttributes.contentType, new DERSet(PKCSObjectIdentifiers.data)));

        // CADES support section
        ASN1EncodableVector aaV2 = new ASN1EncodableVector();
        AlgorithmIdentifier algoId = new AlgorithmIdentifier(new ASN1ObjectIdentifier(CMSSignedDataGenerator.DIGEST_SHA256), null);
        aaV2.add(algoId);
        byte[] dig = SignUtils.calculateHASH(CMSSignedDataGenerator.DIGEST_SHA256, certificate.getEncoded());
        aaV2.add(new DEROctetString(dig));
        Attribute cades = new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificateV2, new DERSet(new DERSequence(new DERSequence(new DERSequence(aaV2)))));
        attributeVector.add(cades);

        AttributeTable attributeTable = new AttributeTable(attributeVector);
        return new DefaultSignedAttributeTableGenerator(attributeTable);
    }

    public static byte[] calculateHASH(String digestOID, byte[] data) throws Exception{
        String digestName = "";

        try{
            if(Security.getProvider("BC") == null)
                Security.addProvider(new BouncyCastleProvider());

            if(digestOID.equals(CMSSignedDataGenerator.DIGEST_MD5))
                digestName = "MD5";
            if(digestOID.equals(CMSSignedDataGenerator.DIGEST_SHA1))
                digestName = "SHA-1";
            if(digestOID.equals(CMSSignedDataGenerator.DIGEST_SHA256))
                digestName = "SHA-256";
            if(digestOID.equals(CMSSignedDataGenerator.DIGEST_SHA384))
                digestName = "SHA-384";
            if(digestOID.equals(CMSSignedDataGenerator.DIGEST_SHA512))
                digestName = "SHA-512";

            if(digestName.equals(""))
                throw new Exception("Unsupported digestOID");

            MessageDigest md = MessageDigest.getInstance(digestName, "BC");
            md.update(data);

            byte[] hash = md.digest();

            return hash;
        }catch(Exception e){
            throw new Exception("Error on the generation for the Hash "+digestName+":\n"+e.getMessage());
        }
    }
jccruellas commented 2 years ago

Good afternoon, I have downloaded your signature and indeed my local copy of CAdESCC generates this error. I need to inspect all the contributions to the input of the signature value computation. Unfortunately due to previous commitments, I will not be able to do this work until beginning next week. I am very sorry. I will keep you posted

Juan Carlos

EichnerAdesso commented 2 years ago

Hi, have you had time to look at the problem yet?

jccruellas commented 2 years ago

Good afternoon, First of all, sorry for not having reacted before. Last week was busier than expected. I have taken a look to your signature, and below I list my findings so that we may comment them. I also attach a screenshot of the output of a program that shows the contents of your CAdES signature.

  1. My local copy throws in the console the following error (apparently this error does not reach the final report: will check what is going on here):

There has been a problem while trying to assign names to the ASN1 components. The problem has occurred in field: Error has occurred while processing contentInfo.content.signedData.encapContentInfo.encapContentInfo. The specification line 'eContent,true,true,,false,false,1,0,0,1,216' that specifies that the child 'eContent' is mandatory, has not been successfuly processed because this child seems not to be present. --> Looking at your signature you have a encapContentInfo but its content is only an OID (field eContentType), and it misses the corresponding OCTET STRING. I see that the OID in this field is 1.2.840.113549.1.7.1, BUT there is NO any octet string following this OIDin the eContent field. Therefore the CAdESCC is not able to find the signed bytes.

You can notice in the attached image that your encapContentInfo has eContentType field, but NO eContent field.

  1. The other message (this one does appear in the report) reads: Field's children number of contentInfo.content.signedData.signerInfos.signerInfo[0].signatureAlgorithm.parameters does not match the specification. Minimum should be: 0, maximum should be 0. Number of children found: 3 Here the problem is that so far the CAdESCC assumed that no parameters would appear within the signatureAlgorithm field. This is something that I will have to fix for this RSASSA-PSS signature.

Below follow my initial conclusions:

  1. I would say that your signature does not encapsulate the signed data octet string despite the fact that there is a encapContentInfo field, and that this is at least one of the reasons for the failure in the cryptographic validation of the signature.
  2. The CAdESCC did not expected parameters in the signatureAlgorithm field. It then throws an error. However, I am not sure whether this is also another reason for the failure in the cryptographic validation of the signature. In the end, CAdESCC uses BouncyCastle, for parsing the ASN.1 structure. And BC does it well. The message raised by CAdESCC comes after the parsing has been completed: when it tries to name every node in the tree, and as the parameters of signatureAlgorithm depend on each algorithm and it does not expect any, it throws this error saying: "I have not been able to name these parameters"...but, again BC has parsed them and it should have properly used them in the cryptographic verification of the signature.
  3. Unless you clearly see something that I have overlooked with your encapContentInfo, I would suggest that you try to regenerate your signature with an octet string in encapContentInfo.eContent field.

And of course, please make any comment that you think is worthwhile.

Hope this helps Juan Carlos.

CAdESSignatureScreenShot
EichnerAdesso commented 2 years ago

Thank you for the answer. This gives me a clue where to start in troubleshooting.

EichnerAdesso commented 2 years ago

Hello Juan, I think I was able to understand your comments.

1) The uploaded signature was an "external signature" (also called "detached signature"). It was created analogous to the BouncyCastle example: https://www.bouncycastle.org/docs/pkixdocs1.8on/org/bouncycastle/cms/CMSSignedDataGenerator.html By setting the encapsulate attribute of the "generate" methode to true, a signature is created with an encapContentInfo-element (OID 1.2.840.113549.1.7.1) that actually contains an octet string (see encapsulated.zip)

grafik

However, this does not seem to be directly related to the reported problems, since the checker displays the identical error messages with this signature.

2) As far as I understand the CMS the EncapsulatedContentInfo Type doesn't require an octet string for detached signatures:

https://datatracker.ietf.org/doc/html/rfc5126.html#section-5.5 https://www.rfc-editor.org/rfc/rfc3852#section-5.2

But I wonder if then in such cases a message digest can be checked at all.

jccruellas commented 2 years ago

Thanks for the update. Indeed, in the view of your results, it seems that there is an issue in the CAdESCC. I will now going to take a look and come back to you.

Regards Juan Carlos

jccruellas commented 2 years ago

I have debugged the crypto verification of the digital signature of your CAdES signature, and this is what I have found: CAdESCC uses org.bouncycastle.cms.SignerInformation::verify(SignerInformationVerifier verifier) method (of BouncyCastle) for that. Now, this method, among other things, computes locally the message-digest that should have been signed in generation. The result of this computation should be the same as the octets in the message-digest signed attribute of your signature. Now, what i have seen is that while the message digest computed by CAdESCC using BC has 32 bytes, the bytes retrieved from your message-digest signed attribute are 13!!...so there is here a clear difference; and this is why the CAdESCC raises this message: Additional details follow: message-digest attribute value does not match calculated value because the calculated value has 32 bytes while your message-digest signed attribute seems to enclose only 13 bytes. I attach a screenshot of the debugger where: . resultDigest is the byte array computed locally by CAdESCC (BC) based on your signature. You may see that its length is 32 bytes . signedMessageDigest.getOctets() is the byte array retrieved from your signed attribute message-digest as it appears in your signature: you can see that there are 13 bytes.

I think that in both tools, your generating software and the CAdESCC (BC) software, should compute the same array of bytes....may I suggest that you review your tool so that you confirm what bytes it puts in the message-digest signed attribute? Regards Juan Carlos.

jccruellas commented 2 years ago

Here comes the screensho

ComputedDigestVersusPresentDigest

t

jccruellas commented 2 years ago

Dear EichnerAdesso, Any reaction to my last comments?

EichnerAdesso commented 2 years ago

Dear Juan, thank you for your feedback. As you suggested im currently reviewing the generation of the signature regarding the messageDigest of the SignerInfo. We apply a two-step-approach which involves a third party. Currently I assume that something between our two systems doesn't match correctly. The different messageDigest might indicate an encoding error or mismatching test data. I'll check that. However, this might take some time. Until then, I would like to thank you for showing me which method the checker used to calculate the digest.

jccruellas commented 2 years ago

Thanks a lot for the message. Glad this exchange has been useful. I understand that this might take some time. No problem. Could you please let me know when you have checked? Thanks a lot Juan-Carlos.

jccruellas commented 2 years ago

Good morning. As you can see, issue "CAdESCC fails to read explicit RSASSA-PSS-params #36", is reporting exactly the same two issues that yourself. Well, I have run the fixed local copy that I used for checking your signature, and it has succeeded also in cryptographically verifying that digital signature. This seems to indicate that this version of CADESCC is able of properly dealing with the RSASSA-PSS signatures. I just mention this for you to be aware. Finally, I have deployed CAdESCC v1.4 so that you can check that, with the signature that you passed me, the first error is not raised. Look forward to hear from you. Juan Carlos.