Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions lib/asn1.js
Original file line number Diff line number Diff line change
Expand Up @@ -778,17 +778,18 @@ asn1.oidToDer = function(oid) {
var values = oid.split('.');
var bytes = forge.util.createBuffer();

// first byte is 40 * value1 + value2
bytes.putByte(40 * parseInt(values[0], 10) + parseInt(values[1], 10));
// other bytes are each value in base 128 with 8th bit set except for
// the last byte for each value
// the first subidentifier is 40 * value1 + value2; the remaining
// subidentifiers are each a single value. every subidentifier is encoded in
// base 128 with the 8th bit set on every byte except its last.
var last, valueBytes, value, b;
for(var i = 2; i < values.length; ++i) {
for(var i = 1; i < values.length; ++i) {
// produce value bytes in reverse because we don't know how many
// bytes it will take to store the value
last = true;
valueBytes = [];
value = parseInt(values[i], 10);
value = (i === 1) ?
40 * parseInt(values[0], 10) + parseInt(values[1], 10) :
parseInt(values[i], 10);
// TODO: Change bitwise logic to allow larger values.
if(value > 0xffffffff) {
throw new Error('OID value too large; max is 32-bits.');
Expand Down Expand Up @@ -830,13 +831,12 @@ asn1.derToOid = function(bytes) {
bytes = forge.util.createBuffer(bytes);
}

// first byte is 40 * value1 + value2
var b = bytes.getByte();
oid = Math.floor(b / 40) + '.' + (b % 40);

// other bytes are each value in base 128 with 8th bit set except for
// the last byte for each value
// each subidentifier is encoded in base 128 with the 8th bit set on every
// byte except its last; the first subidentifier encodes the first two arcs
// as 40 * value1 + value2.
var b;
var value = 0;
var first = true;
while(bytes.length() > 0) {
// error if 7b shift would exceed Number.MAX_SAFE_INTEGER
// (Number.MAX_SAFE_INTEGER / 128)
Expand All @@ -850,7 +850,16 @@ asn1.derToOid = function(bytes) {
value += b & 0x7F;
} else {
// last byte
oid += '.' + (value + b);
value += b;
if(first) {
// split the first subidentifier into the first two arcs
oid = (value < 80) ?
Math.floor(value / 40) + '.' + (value % 40) :
'2.' + (value - 80);
first = false;
} else {
oid += '.' + value;
}
value = 0;
}
}
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/asn1.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ var UTIL = require('../../lib/util');
);
});

it('should convert an OID with a multi-byte first subidentifier to DER', function() {
// X.690 8.19: the first subidentifier (40 * arc1 + arc2) can exceed one
// byte when arc1 is 2, so it must be encoded in base 128
ASSERT.equal(ASN1.oidToDer('2.999.3').toHex(), '883703');
ASSERT.equal(ASN1.oidToDer('2.100').toHex(), '8134');
});

it('should convert an OID with a multi-byte first subidentifier from DER', function() {
ASSERT.equal(ASN1.derToOid(UTIL.hexToBytes('883703')), '2.999.3');
ASSERT.equal(ASN1.derToOid(UTIL.hexToBytes('8134')), '2.100');
});

it('should convert INTEGER 0 to DER', function() {
ASSERT.equal(ASN1.integerToDer(0).toHex(), '00');
});
Expand Down