digitalbazaar / forge

A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps
https://digitalbazaar.com/
Other
5.01k stars 767 forks source link

PKCS#7 signing provides incorrect output #1040

Open rafa-guillermo opened 1 year ago

rafa-guillermo commented 1 year ago

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 commented 1 year ago

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 commented 4 months ago

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.