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

PKCS#7 signing provides incorrect output #1040

Open
rafa-guillermo opened this issue Jun 30, 2023 · 2 comments
Open

PKCS#7 signing provides incorrect output #1040

rafa-guillermo opened this issue Jun 30, 2023 · 2 comments

Comments

@rafa-guillermo
Copy link

rafa-guillermo commented Jun 30, 2023

I'm trying to connect to an API which requires the endpoint to be signed with PKCS#7 signing. I've got the signing working in python and calling the endpoint results in a correct response.

Using the sample code provided for this with forge however results in a different output than what the py script gives me, and using the result in my request results in an error.

I do notice that when converting the outputs to bytes, the two outputs are very similar, though there are some major differences between the two (the output from forge has a lot of bytes with the value 194 interspersed through it, and in other places bytes with the value 195, with the subsequent byte being +64 of the corresponding byte in the py output.

The code I'm using is just the example code:

var p7 = forge.pkcs7.createSignedData();
p7.content = forge.util.createBuffer('Some content to be signed.', 'utf8');
p7.addCertificate(certOrCertPem);
p7.addSigner({
  key: privateKeyAssociatedWithCert,
  certificate: certOrCertPem,
  digestAlgorithm: forge.pki.oids.sha256,
  authenticatedAttributes: [{
    type: forge.pki.oids.contentType,
    value: forge.pki.oids.data
  }, {
    type: forge.pki.oids.messageDigest
    // value will be auto-populated at signing time
  }, {
    type: forge.pki.oids.signingTime,
    // value can also be auto-populated at signing time
    value: new Date()
  }]
});
p7.sign();

Example off the byte differences to demonstrate what I mean (bytes in two's compliment, -62 == 194):
JS:
48,-62,-126,5,72,6,9,42,-62,-122,72,-62,-122,-61,-73,13,1,7,2,-62,-96,-62,-126,5,57,48,-62,-126,5,53,2,1,1,49,15,48,13,6,9,96,-62,-122,72,1,101,3,4,2,1,5,0,48,15,6,9,42,-62,-122,72

py:
48,-126,5,68,6,9,42,-122,72,-122,-9,13,1,7,2,-96,-126,5,53,48,-126,5,49,2,1,1,49,15,48,13,6,9,96,-122,72,1,101,3,4,2,1,5,0,48,11,6,9,42,-122,72

@rafa-guillermo
Copy link
Author

All the values of -62 in the forge output are just not there in the py output, removing them and comparing we get:

48,-126,5,68,6,9,42,-122,72,-122,-9,13,1,7,2,-96,-126,5,53,48,-126,5,49,2,1,1,49,15,48,13,6,9,96,-122,72,1,101,3,4,2,1,5,0,48,11,6,9,42,-122,72
48,-126,5,72,6,9,42,-122,72,-122,-9,13,1,7,2,-96,-126,5,57,48,-126,5,53,2,1,1,49,15,48,13,6,9,96,-122,72,1,101,3,4,2,1,5,0,48,15,6,9,42,-122,72

so not identical but close. the other major discrepancy I found is that in the forge byte array there are often byte pairs [-61, x], which seem to correspond to a single byte in the py byte array with a value of x-64

here's an example:

js:
-61,-118,-62,-112,-62,-71,-61,-72,-61,-93

py:
54,-112,-71,-8,-29

step by step so you can see the correspondence:
adding in square brackets just to show the byte pairs that start with -61:
[-61, -118], -62, -112, -62, -71, [-61, -72], [-61, -93]

remove the -62s:
[-61, -118], -112, -71, [-61, -72], [-61, -93]

add 64 to the second half of the byte pairs where the left-hand byte is -61:
[-61, -118 + 64], -112, -71, [-61, -72 + 64], [-61, -93 + 64]
[-61, -54], -112, -71, [-61, -8], [-61, -29]

remove the -61s from the byte pairs and we get the same as the py bytes:
-54, -112, -71, -8, -29

@oceddi
Copy link

oceddi commented Feb 16, 2024

Not sure if it's the same issue but I was seeing problems when pulling data out of forge format into node.js buffer format. The work around I have is to do it this way:

const messageSignedASN1 = p7.toAsn1();
const messageSignedDER = asn1.toDer(messageSignedASN1).getBytes();
return Buffer.from(forge.util.bytesToHex(messageSignedDER), "hex");

The last line with the "bytesToHex" step seems to fix it for me.

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

2 participants