Here's how RFC 5280 defines an X.509 extension field:
Extension ::= SEQUENCE {
extnID OBJECT IDENTIFIER,
critical BOOLEAN DEFAULT FALSE,
extnValue OCTET STRING
-- contains the DER encoding of an ASN.1 value
-- corresponding to the extension type identified
-- by extnID
}
When I use the pyasn1 decoder, I'll get an object foo
whose foo['extnValue'].asOctets()
can be further decoded, with another call to the decoder, using the schema appropriate to foo['extnID']
.
Question: supposing that there's one special extnID
in my application, is it possible in pyasn1 to define a schema that (a) doesn't accept any OBJECT IDENTIFIER, only the special one; and (b) steps past the OCTET STRING wrapper to decode the payload according to the appropriate special "sub-schema" ?
I can do this by special-case logic in the code, but I'd prefer to define a special-case schema if that is supported.
You should use OpenType for extnValue
type definition. When you pass decoder the map of extnID
-> ASN.1 type
, the decoder then will step past the outermost extnValue
wrapper trying to decode its contents.
Here's a quick example:
openType = opentype.OpenType(
'id',
{1: univ.Integer(),
2: univ.OctetString()}
)
self.s = univ.Sequence(
componentType=namedtype.NamedTypes(
namedtype.NamedType('id', univ.Integer()),
namedtype.NamedType('blob', univ.Any(), openType=openType)
)
)
Make sure to pass decodeOpenTypes=True
argument to the decode()
function if you want the decoder to unwrap these open types.
BTW, if you look at the pyasn1-modules, that map is already there. If you use these definitions and just pass decodeOpenTypes=True
keyword argument to decoder, you should get your extensions unwrapped.
There is no ready-made way to fail the decoder on unknown extnID
. You can probably model that my giving it your own map (perhaps based on dict
) which would fail on unsuccessful key in my_map
operation.