asn1.js
asn1.js copied to clipboard
A way to reuse generic definition with custom parts
There are parts of ASN.1 definition which content depends on the object identifier.
For example, to encode/decode PKCS7 ContentInfo we need 2 steps:
- decode generic ContentInfo
- decode specific part based on content type using specific model.
http://tools.ietf.org/html/rfc2315#section-7
ContentInfo ::= SEQUENCE {
contentType ContentType,
content
[0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
Is there a way to define ASN.1 js model to do that in one step? I.e. some kind of conditional typing/objid mapping, maybe...
The same problem goes with AlgorithmIdentifier.
Say, something like this:
var PKCS7_CONTENT_TYPES = {
"1 2 840 113549 1 7 1": "data",
"1 2 840 113549 1 7 2": "signedData",
"1 2 840 113549 1 7 3": "envelopedData",
"1 2 840 113549 1 7 4": "signedAndEnvelopedData",
"1 2 840 113549 1 7 5": "digestData",
"1 2 840 113549 1 7 6": "encryptedData",
};
var EnvelopedData = ...
var SignedData = ...
var ContentInfo = asn1.define('ContentInfo', function() {
this.seq().obj(
this.key('contentType').objid(PKCS7_CONTENT_TYPES),
this.key('content').optional().explicit(0).anydefinedby('contentType', {
...
'signedData': this.use(SignedData),
'envelopedData': this.use(EnvelopedData),
...
})
);
});
Notice the anydefinedby tag I propose.
Well, we can just pass some function to use() that would return another model. Something like
var ContenModels = {
signedData: SignedData,
envelopedData: EnvelopedData
};
var ContentInfo = asn1.define('ContentInfo', function() {
this.seq().obj(
this.key('contentType').objid(PKCS7_CONTENT_TYPES),
this.key('content').optional().explicit(0).use(function () {
return ContenModels[this.contentType];
})
);
});
Great! P.S. but it's not so declarative and doesn't intuitively match ASN.1 notation.
A bit more declarative way:
var ContentInfo = asn1.define('ContentInfo', function() {
this.seq().obj(
this.key('contentType').objid(PKCS7_CONTENT_TYPES),
this.key('content').optional().explicit(0).use(function () {
return {
signedData: SignedData,
envelopedData: EnvelopedData
}[this.contentType];
})
);
});
Or even this:
var ContentInfo = asn1.define('ContentInfo', function() {
this.seq().obj(
this.key('contentType').objid(PKCS7_CONTENT_TYPES),
this.key('content').optional().explicit(0).definedby('contentType', {
signedData: SignedData,
envelopedData: EnvelopedData
})
);
});
// Somewhere in ans1js
Node.prototype.definedby = function(tagName, mapping) {
return this.use(function() {
return mapping[this[tagName]];
});
}
Not sure what to do with error handling (if the key is missing).
Is this considered fixed?