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

x509 Interface #47

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
205 changes: 198 additions & 7 deletions lib/encoding/asn1.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,18 @@ const classesByVal = {
3: 'PRIVATE'
};

// ASN.1 type
const TARGET = 0xff;

// flags
const OPTIONAL = 1 << 8;
const MODE = 0xff << 9;
const NORMAL = 0 << 9;
const EXPLICIT = 1 << 9;
const IMPLICIT = 2 << 9;
const FORCE = 1 << 9;

// mode
const MODE = 0xff << 10;
const NORMAL = 0 << 10;
const EXPLICIT = 1 << 10;
const IMPLICIT = 1 << 11;

/**
* Node
Expand Down Expand Up @@ -154,6 +160,17 @@ class Node extends bio.Struct {
this.flags &= ~OPTIONAL;
}

get force() {
return (this.flags & FORCE) !== 0;
}

set force(value) {
if (value)
this.flags |= FORCE;
else
this.flags &= ~FORCE;
}

get target() {
return this.flags & TARGET;
}
Expand Down Expand Up @@ -239,7 +256,7 @@ class Node extends bio.Struct {
}

getSize(extra) {
if (this.opt && this.clean())
if (this.opt && this.clean() && !this.force)
return 0;

const body = this.getBodySize(extra);
Expand All @@ -256,7 +273,7 @@ class Node extends bio.Struct {
}

write(bw, extra) {
if (this.opt && this.clean())
if (this.opt && this.clean() && !this.force)
return bw;

const body = this.getBodySize();
Expand Down Expand Up @@ -490,6 +507,13 @@ class Any extends Node {
const Node = typeToClass(hdr.type);

this.node = new Node();

// If a Null node was present when reading,
// respect the preference and include the node
// when writing as well.
if (this.opt)
this.force = true;

this.node.flags = this.flags;
this.node.read(br, extra);

Expand Down Expand Up @@ -535,6 +559,32 @@ class Any extends Node {
node: this.node
};
}

getJSON() {
if (this.opt && !this.force)
return null;

return {
type: this.node.constructor.name,
node: this.node.getJSON()
};
}

fromJSON(json) {
if (!json)
return null;

if (this.opt)
this.force = true;

const type = types[json.type.toUpperCase()];
const Node = typeToClass(type);
this.node = new Node();
this.node.fromJSON(json.node);
this.node.flags = this.flags;

return this.node;
}
}

/**
Expand All @@ -547,6 +597,7 @@ class Choice extends Node {
assert(node instanceof Node);
this.node = node;
this.from(...options);
this.types = types;
}

get type() {
Expand All @@ -557,6 +608,10 @@ class Choice extends Node {
throw new Error('Unimplemented.');
}

typeToClass(type) {
return typeToClass(type);
}

getSize(extra) {
return this.node.getSize(extra);
}
Expand Down Expand Up @@ -584,7 +639,7 @@ class Choice extends Node {
if (choices.indexOf(hdr.type) === -1)
throw new Error(`Could not satisfy choice for: ${hdr.type}.`);

const Node = typeToClass(hdr.type);
const Node = this.typeToClass(hdr.type);
const el = new Node();
el.flags = this.flags;

Expand Down Expand Up @@ -621,6 +676,23 @@ class Choice extends Node {
node: this.node
};
}

getJSON() {
return {
type: this.node.constructor.name,
node: this.node.getJSON()
};
}

fromJSON(json) {
const type = this.types[json.type.toUpperCase()];
const Node = this.typeToClass(type);
this.node = new Node();
this.node.fromJSON(json.node);
this.node.flags = this.flags;

return this.node;
}
}

/**
Expand Down Expand Up @@ -693,6 +765,17 @@ const Str = class String extends Node {
format() {
return `<${this.constructor.name}: ${this.value}>`;
}

getJSON() {
return this.value;
}

fromJSON(json) {
assert(typeof json === 'string');
this.value = json;

return this;
}
};

/**
Expand Down Expand Up @@ -751,6 +834,17 @@ const Bool = class Boolean extends Node {
format() {
return `<${this.constructor.name}: ${this.value}>`;
}

getJSON() {
return this.value;
}

fromJSON(json) {
assert(typeof json === 'boolean');
this.value = json;

return this;
}
};

/**
Expand Down Expand Up @@ -954,6 +1048,21 @@ class Integer extends Node {

return `<${name}: ${sign}0x${hex}>`;
}

getJSON() {
return {
value: this.value.toString('hex'),
negative: this.negative
};
}

fromJSON(json) {
assert(typeof json.negative === 'boolean');
this.value = Buffer.from(json.value, 'hex');
this.negative = json.negative;

return this;
}
}

/**
Expand Down Expand Up @@ -995,6 +1104,14 @@ class Unsigned extends Integer {
assert(!this.negative);
return this;
}

getJSON() {
return this.toNumber();
}

fromJSON(json) {
return this.fromNumber(json);
}
}

/**
Expand Down Expand Up @@ -1121,6 +1238,21 @@ class BitString extends Node {

return `<${this.constructor.name}: ${this.bits}:${value.toString('hex')}>`;
}

getJSON() {
return {
bits: this.bits,
value: this.value.toString('hex')
};
}

fromJSON(json) {
assert(typeof json.bits === 'number');
this.bits = json.bits;
this.value = Buffer.from(json.value, 'hex');

return this;
}
}

/**
Expand Down Expand Up @@ -1175,6 +1307,16 @@ class OctString extends Node {

return `<${this.constructor.name}: ${value.toString('hex')}>`;
}

getJSON() {
return this.value.toString('hex');
}

fromJSON(json) {
this.value = Buffer.from(json, 'hex');

return this;
}
}

/**
Expand Down Expand Up @@ -1213,6 +1355,14 @@ class Null extends Node {
format() {
return `<${this.constructor.name}>`;
}

getJSON() {
return null;
}

fromJSON(json) {
return this;
}
}

/**
Expand Down Expand Up @@ -1368,6 +1518,10 @@ class OID extends Node {
str = objects.hashes[str];
else if (objects.curves.hasOwnProperty(str))
str = objects.curves[str];
else if (objects.sigAlgs.hasOwnProperty(str))
str = objects.sigAlgs[str];
else if (objects.extensions.hasOwnProperty(str))
str = objects.extensions[str];

const parts = str.split('.');
const out = new Uint32Array(parts.length);
Expand Down Expand Up @@ -1415,19 +1569,40 @@ class OID extends Node {
return objects.curvesByVal[this.toString()] || null;
}

getExtensionName() {
return objects.extensionsByVal[this.toString()] || null;
}

format() {
const oid = this.toString();
const name = objects.attrsByVal[oid]
|| objects.sigAlgsByVal[oid]
|| objects.keyAlgsByVal[oid]
|| objects.hashesByVal[oid]
|| objects.curvesByVal[oid]
|| objects.extensionsByVal[oid]
|| 'UNKNOWN';

const str = `${oid} (${name})`;

return `<${this.constructor.name}: ${str}>`;
}

getJSON() {
const oid = this.toString();
const name = objects.attrsByVal[oid]
|| objects.sigAlgsByVal[oid]
|| objects.keyAlgsByVal[oid]
|| objects.hashesByVal[oid]
|| objects.curvesByVal[oid]
|| objects.extensionsByVal[oid]
|| this.toString();
return name;
}

fromJSON(json) {
return this.fromString(json);
}
}

/**
Expand Down Expand Up @@ -1548,6 +1723,14 @@ class RawSequence extends Node {
format() {
return this.toArray();
}

getJSON() {
throw new Error('Not implemented.');
}

fromJSON(json) {
throw new Error('Not implemented.');
}
}

/**
Expand Down Expand Up @@ -1695,6 +1878,14 @@ class Time extends Node {

return `<${name}: ${value}${off} (${this.toString()})>`;
}

getJSON() {
return this.toString();
}

fromJSON(json) {
return this.fromString(json);
}
}

/**
Expand Down
Loading