Skip to content

Commit

Permalink
refact(jose-to-der) unroll/manually encode der
Browse files Browse the repository at this point in the history
10 times faster on my machine, given we can be very specific and avoid
copies and allocations
  • Loading branch information
omsmith committed Jun 12, 2015
1 parent aad392a commit b911220
Showing 1 changed file with 54 additions and 14 deletions.
68 changes: 54 additions & 14 deletions src/ecdsa-sig-formatter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

var asn1 = require('asn1.js'),
BN = asn1.bignum,
base64Url = require('base64-url').escape;

var ECDSASigValue = asn1.define('ECDSASigValue', function () {
Expand All @@ -11,6 +10,9 @@ var ECDSASigValue = asn1.define('ECDSASigValue', function () {
);
});

var seq = 0x10,
int = 0x02;

function getParamSize (keySize) {
var result = ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1);
return result;
Expand All @@ -31,11 +33,6 @@ function getParamBytesForAlg (alg) {
throw new Error('Unknown algorithm "' + alg + '"');
}

function bufToBignum (buf) {
var bn = new BN(buf, 10, 'be').iabs();
return bn;
}

function bignumToBuf (bn, numBytes) {
var buf = new Buffer(bn.toString('hex', numBytes), 'hex');
return buf;
Expand Down Expand Up @@ -67,6 +64,34 @@ function derToJose(signature, alg) {
return signature;
}

function reduceBuffer (buf) {
var padding = 0;
for (var n = buf.length; padding < n && buf[padding] === 0;) {
++padding;
}

var needsSign = buf[padding] >= 0x80;
if (needsSign) {
--padding;

if (padding < 0) {
var old = buf;
buf = new Buffer(1 + buf.length);
buf[0] = 0;
old.copy(buf, 1);

return buf;
}
}

if (padding === 0) {
return buf;
}

buf = buf.slice(padding);
return buf;
}

function joseToDer(signature, alg) {
signature = signatureAsBuffer(signature);
var paramBytes = getParamBytesForAlg(alg);
Expand All @@ -76,15 +101,30 @@ function joseToDer(signature, alg) {
throw new TypeError('"' + alg + '" signatures must be "' + paramBytes * 2 + '" bytes, saw "' + signatureBytes + '"');
}

var r = signature.slice(0, paramBytes);
r = bufToBignum(r);
var s = signature.slice(paramBytes);
s = bufToBignum(s);
var r = reduceBuffer(signature.slice(0, paramBytes));
var s = reduceBuffer(signature.slice(paramBytes));

signature = ECDSASigValue.encode({
r: r,
s: s
}, 'der');
var rsBytes = 1 + 1 + r.length + 1 + 1 + s.length;

var oneByteLength = rsBytes < 0x80;

signature = new Buffer((oneByteLength ? 2 : 3) + rsBytes);

var offset = 0;
signature[offset++] = (seq | 0x20) | 0 << 6;
if (oneByteLength) {
signature[offset++] = rsBytes;
} else {
signature[offset++] = 0x80 | 1;
signature[offset++] = rsBytes & 0xff;
}
signature[offset++] = int | (0 << 6);
signature[offset++] = r.length;
r.copy(signature, offset);
offset += r.length;
signature[offset++] = int | (0 << 6);
signature[offset++] = s.length;
s.copy(signature, offset);

return signature;
}
Expand Down

0 comments on commit b911220

Please sign in to comment.