digitalbazaar / forge

A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps

Home Page:https://digitalbazaar.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PKCS#7 signing provides incorrect output

rafa-guillermo opened this issue · comments

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

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