Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CMS signature: signedAttrs should use DER encoding instead of BER #402

Open
mholy-arbes opened this issue Apr 4, 2024 · 0 comments
Open

Comments

@mholy-arbes
Copy link

mholy-arbes commented Apr 4, 2024

Hello,
according to the RFC 5652, when using SignedAttrs, the message digest should be calculated as

the complete DER encoding of the SignedAttrs value contained in the signedAttrs field

However, this is not happening right now as per code in SignedData.ts which uses BER encoding:

if (signerInfo.signedAttrs) {
      if (signerInfo.signedAttrs.encodedValue.byteLength !== 0)
        data = signerInfo.signedAttrs.encodedValue;
      else {
        data = signerInfo.signedAttrs.toSchema().toBER();

        //#region Change type from "[0]" to "SET" accordingly to standard
        const view = pvtsutils.BufferSourceConverter.toUint8Array(data);
        view[0] = 0x31;
        //#endregion
      }
    }

The main problem that I have is that when passing attributes into the SignedAndUnsignedAttributes, the message digest depends on the order I specify the attributes. I believe this should not be happening and the message digest should be the same, independent of the attributes order.

This causes problems when verifying the signature with Java Bouncy Castle library, which expects the DER (ordered) encoding of the signed attributes.

Examples

This attribute order does not validate

const signedAttrs = new SignedAndUnsignedAttributes({
    type: 0,
    attributes: [
        new Attribute({
            type: OID.ContentType,
            values: [new asn1js.ObjectIdentifier({ value: OID.Data })],
        }),
        new Attribute({
            type: OID.MessageDigest,
            values: [new asn1js.OctetString({ valueHex: dataDigest })],
        }),
        new Attribute({
            type: OID.SigningTime,
            values: [new asn1js.UTCTime({ valueDate: new Date() })],
        }),
    ],
});

Switching positions of SigningTime and MessageDigest produces a valid signature

const signedAttrs = new SignedAndUnsignedAttributes({
    type: 0,
    attributes: [
        new Attribute({
            type: OID.ContentType,
            values: [new asn1js.ObjectIdentifier({ value: OID.Data })],
        }),
        new Attribute({
            type: OID.SigningTime,
            values: [new asn1js.UTCTime({ valueDate: new Date() })],
        }),
        new Attribute({
            type: OID.MessageDigest,
            values: [new asn1js.OctetString({ valueHex: dataDigest })],
        }),
    ],
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant