pyasn1 0.4.3, pyasn1_modules 0.2.2

This commit is contained in:
Jay Lee
2018-07-04 20:14:52 -04:00
parent 19018e4854
commit 044686b564
57 changed files with 3047 additions and 1612 deletions

View File

@ -1,7 +1,7 @@
import sys
# http://www.python.org/dev/peps/pep-0396/
__version__ = '0.3.7'
# https://www.python.org/dev/peps/pep-0396/
__version__ = '0.4.3'
if sys.version_info[:2] < (2, 4):
raise RuntimeError('PyASN1 requires Python 2.4 or later')

View File

@ -1,14 +1,20 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import base, tag, univ, char, useful, tagmap
from pyasn1 import debug
from pyasn1 import error
from pyasn1.codec.ber import eoo
from pyasn1.compat.octets import oct2int, octs2ints, ints2octs, null
from pyasn1.compat.integer import from_bytes
from pyasn1 import debug, error
from pyasn1.compat.octets import oct2int, octs2ints, ints2octs, null
from pyasn1.type import base
from pyasn1.type import char
from pyasn1.type import tag
from pyasn1.type import tagmap
from pyasn1.type import univ
from pyasn1.type import useful
__all__ = ['decode']
@ -36,8 +42,10 @@ class AbstractSimpleDecoder(AbstractDecoder):
def substrateCollector(asn1Object, substrate, length):
return substrate[:length], substrate[length:]
def _createComponent(self, asn1Spec, tagSet, value=noValue):
if asn1Spec is None:
def _createComponent(self, asn1Spec, tagSet, value, **options):
if options.get('native'):
return value
elif asn1Spec is None:
return self.protoComponent.clone(value, tagSet=tagSet)
elif value is noValue:
return asn1Spec
@ -54,7 +62,7 @@ class ExplicitTagDecoder(AbstractSimpleDecoder):
**options):
if substrateFun:
return substrateFun(
self._createComponent(asn1Spec, tagSet, ''),
self._createComponent(asn1Spec, tagSet, '', **options),
substrate, length
)
@ -70,7 +78,7 @@ class ExplicitTagDecoder(AbstractSimpleDecoder):
**options):
if substrateFun:
return substrateFun(
self._createComponent(asn1Spec, tagSet, ''),
self._createComponent(asn1Spec, tagSet, '', **options),
substrate, length
)
@ -101,18 +109,18 @@ class IntegerDecoder(AbstractSimpleDecoder):
head, tail = substrate[:length], substrate[length:]
if not head:
return self._createComponent(asn1Spec, tagSet, 0), tail
return self._createComponent(asn1Spec, tagSet, 0, **options), tail
value = from_bytes(head, signed=True)
return self._createComponent(asn1Spec, tagSet, value), tail
return self._createComponent(asn1Spec, tagSet, value, **options), tail
class BooleanDecoder(IntegerDecoder):
protoComponent = univ.Boolean(0)
def _createComponent(self, asn1Spec, tagSet, value=noValue):
return IntegerDecoder._createComponent(self, asn1Spec, tagSet, value and 1 or 0)
def _createComponent(self, asn1Spec, tagSet, value, **options):
return IntegerDecoder._createComponent(self, asn1Spec, tagSet, value and 1 or 0, **options)
class BitStringDecoder(AbstractSimpleDecoder):
@ -124,53 +132,86 @@ class BitStringDecoder(AbstractSimpleDecoder):
decodeFun=None, substrateFun=None,
**options):
head, tail = substrate[:length], substrate[length:]
if substrateFun:
return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options),
substrate, length)
if not head:
raise error.PyAsn1Error('Empty BIT STRING substrate')
if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check?
if not head:
raise error.PyAsn1Error('Empty substrate')
trailingBits = oct2int(head[0])
if trailingBits > 7:
raise error.PyAsn1Error(
'Trailing bits overflow %s' % trailingBits
)
head = head[1:]
value = self.protoComponent.fromOctetString(head, trailingBits)
return self._createComponent(asn1Spec, tagSet, value), tail
value = self.protoComponent.fromOctetString(head[1:], internalFormat=True, padding=trailingBits)
return self._createComponent(asn1Spec, tagSet, value, **options), tail
if not self.supportConstructedForm:
raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__)
bitString = self._createComponent(asn1Spec, tagSet)
# All inner fragments are of the same type, treat them as octet string
substrateFun = self.substrateCollector
if substrateFun:
return substrateFun(bitString, substrate, length)
bitString = self.protoComponent.fromOctetString(null, internalFormat=True)
while head:
component, head = decodeFun(head, self.protoComponent, **options)
bitString += component
component, head = decodeFun(head, self.protoComponent,
substrateFun=substrateFun, **options)
return bitString, tail
trailingBits = oct2int(component[0])
if trailingBits > 7:
raise error.PyAsn1Error(
'Trailing bits overflow %s' % trailingBits
)
bitString = self.protoComponent.fromOctetString(
component[1:], internalFormat=True,
prepend=bitString, padding=trailingBits
)
return self._createComponent(asn1Spec, tagSet, bitString, **options), tail
def indefLenValueDecoder(self, substrate, asn1Spec,
tagSet=None, length=None, state=None,
decodeFun=None, substrateFun=None,
**options):
bitString = self._createComponent(asn1Spec, tagSet)
if substrateFun:
return substrateFun(bitString, substrate, length)
return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options), substrate, length)
# All inner fragments are of the same type, treat them as octet string
substrateFun = self.substrateCollector
bitString = self.protoComponent.fromOctetString(null, internalFormat=True)
while substrate:
component, substrate = decodeFun(substrate, self.protoComponent,
substrateFun=substrateFun,
allowEoo=True, **options)
if component is eoo.endOfOctets:
break
bitString += component
trailingBits = oct2int(component[0])
if trailingBits > 7:
raise error.PyAsn1Error(
'Trailing bits overflow %s' % trailingBits
)
bitString = self.protoComponent.fromOctetString(
component[1:], internalFormat=True,
prepend=bitString, padding=trailingBits
)
else:
raise error.SubstrateUnderrunError('No EOO seen before substrate ends')
return bitString, substrate
return self._createComponent(asn1Spec, tagSet, bitString, **options), substrate
class OctetStringDecoder(AbstractSimpleDecoder):
@ -184,11 +225,11 @@ class OctetStringDecoder(AbstractSimpleDecoder):
head, tail = substrate[:length], substrate[length:]
if substrateFun:
return substrateFun(self._createComponent(asn1Spec, tagSet),
return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options),
substrate, length)
if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check?
return self._createComponent(asn1Spec, tagSet, head), tail
return self._createComponent(asn1Spec, tagSet, head, **options), tail
if not self.supportConstructedForm:
raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__)
@ -204,14 +245,14 @@ class OctetStringDecoder(AbstractSimpleDecoder):
**options)
header += component
return self._createComponent(asn1Spec, tagSet, header), tail
return self._createComponent(asn1Spec, tagSet, header, **options), tail
def indefLenValueDecoder(self, substrate, asn1Spec,
tagSet=None, length=None, state=None,
decodeFun=None, substrateFun=None,
**options):
if substrateFun and substrateFun is not self.substrateCollector:
asn1Object = self._createComponent(asn1Spec, tagSet)
asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)
return substrateFun(asn1Object, substrate, length)
# All inner fragments are of the same type, treat them as octet string
@ -232,7 +273,7 @@ class OctetStringDecoder(AbstractSimpleDecoder):
'No EOO seen before substrate ends'
)
return self._createComponent(asn1Spec, tagSet, header), substrate
return self._createComponent(asn1Spec, tagSet, header, **options), substrate
class NullDecoder(AbstractSimpleDecoder):
@ -248,7 +289,7 @@ class NullDecoder(AbstractSimpleDecoder):
head, tail = substrate[:length], substrate[length:]
component = self._createComponent(asn1Spec, tagSet)
component = self._createComponent(asn1Spec, tagSet, '', **options)
if head:
raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length)
@ -296,7 +337,7 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder):
elif subId == 128:
# ASN.1 spec forbids leading zeros (0x80) in OID
# encoding, tolerating it opens a vulnerability. See
# http://www.cosic.esat.kuleuven.be/publications/article-1432.pdf
# https://www.esat.kuleuven.be/cosic/publications/article-1432.pdf
# page 7
raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')
@ -310,7 +351,7 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder):
else:
raise error.PyAsn1Error('Malformed first OID octet: %s' % head[0])
return self._createComponent(asn1Spec, tagSet, oid), tail
return self._createComponent(asn1Spec, tagSet, oid, **options), tail
class RealDecoder(AbstractSimpleDecoder):
@ -326,7 +367,7 @@ class RealDecoder(AbstractSimpleDecoder):
head, tail = substrate[:length], substrate[length:]
if not head:
return self._createComponent(asn1Spec, tagSet, 0.0), tail
return self._createComponent(asn1Spec, tagSet, 0.0, **options), tail
fo = oct2int(head[0])
head = head[1:]
@ -386,7 +427,7 @@ class RealDecoder(AbstractSimpleDecoder):
raise error.SubstrateUnderrunError(
'Unknown encoding (tag %s)' % fo
)
return self._createComponent(asn1Spec, tagSet, value), tail
return self._createComponent(asn1Spec, tagSet, value, **options), tail
class AbstractConstructedDecoder(AbstractDecoder):
@ -415,10 +456,9 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
# Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF
# The heuristics is:
# * 0-1 component -> likely SEQUENCE OF/SET OF
# * 1+ components of the same type -> likely SEQUENCE OF/SET OF
# * otherwise -> likely SEQUENCE/SET
if len(components) > 1 or len(componentTypes) > 1:
# * 1+ components of different types -> likely SEQUENCE/SET
# * otherwise -> likely SEQUENCE OF/SET OF
if len(componentTypes) > 1:
protoComponent = self.protoRecordComponent
else:
protoComponent = self.protoSequenceComponent
@ -467,34 +507,34 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
asn1Object = asn1Spec.clone()
if asn1Object.typeId in (univ.Sequence.typeId, univ.Set.typeId):
if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):
namedTypes = asn1Object.componentType
namedTypes = asn1Spec.componentType
isSetType = asn1Object.typeId == univ.Set.typeId
isSetType = asn1Spec.typeId == univ.Set.typeId
isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault
seenIndices = set()
idx = 0
while head:
if not namedTypes:
asn1Spec = None
componentType = None
elif isSetType:
asn1Spec = namedTypes.tagMapUnique
componentType = namedTypes.tagMapUnique
else:
try:
if isDeterministic:
asn1Spec = namedTypes[idx].asn1Object
componentType = namedTypes[idx].asn1Object
elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
asn1Spec = namedTypes.getTagMapNearPosition(idx)
componentType = namedTypes.getTagMapNearPosition(idx)
else:
asn1Spec = namedTypes[idx].asn1Object
componentType = namedTypes[idx].asn1Object
except IndexError:
raise error.PyAsn1Error(
'Excessive components decoded at %r' % (asn1Object,)
'Excessive components decoded at %r' % (asn1Spec,)
)
component, head = decodeFun(head, asn1Spec, **options)
component, head = decodeFun(head, componentType, **options)
if not isDeterministic and namedTypes:
if isSetType:
@ -514,14 +554,54 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
if namedTypes:
if not namedTypes.requiredComponents.issubset(seenIndices):
raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__)
if namedTypes.hasOpenTypes:
openTypes = options.get('openTypes', {})
if openTypes or options.get('decodeOpenTypes', False):
for idx, namedType in enumerate(namedTypes.namedTypes):
if not namedType.openType:
continue
if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue:
continue
governingValue = asn1Object.getComponentByName(
namedType.openType.name
)
try:
openType = openTypes[governingValue]
except KeyError:
try:
openType = namedType.openType[governingValue]
except KeyError:
continue
component, rest = decodeFun(
asn1Object.getComponentByPosition(idx).asOctets(),
asn1Spec=openType
)
asn1Object.setComponentByPosition(idx, component)
else:
asn1Object.verifySizeSpec()
else:
asn1Spec = asn1Object.componentType
asn1Object = asn1Spec.clone()
componentType = asn1Spec.componentType
idx = 0
while head:
component, head = decodeFun(head, asn1Spec, **options)
component, head = decodeFun(head, componentType, **options)
asn1Object.setComponentByPosition(
idx, component,
verifyConstraints=False,
@ -529,8 +609,6 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
)
idx += 1
asn1Object.verifySizeSpec()
return asn1Object, tail
def indefLenValueDecoder(self, substrate, asn1Spec,
@ -557,7 +635,7 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
asn1Object = asn1Spec.clone()
if asn1Object.typeId in (univ.Sequence.typeId, univ.Set.typeId):
if asn1Spec.typeId in (univ.Sequence.typeId, univ.Set.typeId):
namedTypes = asn1Object.componentType
@ -611,16 +689,59 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
if namedTypes:
if not namedTypes.requiredComponents.issubset(seenIndices):
raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__)
else:
asn1Object.verifySizeSpec()
if namedTypes.hasOpenTypes:
openTypes = options.get('openTypes', None)
if openTypes or options.get('decodeOpenTypes', False):
for idx, namedType in enumerate(namedTypes.namedTypes):
if not namedType.openType:
continue
if namedType.isOptional and not asn1Object.getComponentByPosition(idx).isValue:
continue
governingValue = asn1Object.getComponentByName(
namedType.openType.name
)
try:
openType = openTypes[governingValue]
except KeyError:
try:
openType = namedType.openType[governingValue]
except KeyError:
continue
component, rest = decodeFun(
asn1Object.getComponentByPosition(idx).asOctets(),
asn1Spec=openType, allowEoo=True
)
if component is not eoo.endOfOctets:
asn1Object.setComponentByPosition(idx, component)
else:
asn1Object.verifySizeSpec()
else:
asn1Spec = asn1Object.componentType
asn1Object = asn1Spec.clone()
componentType = asn1Spec.componentType
idx = 0
while substrate:
component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True, **options)
component, substrate = decodeFun(substrate, componentType, allowEoo=True, **options)
if component is eoo.endOfOctets:
break
asn1Object.setComponentByPosition(
idx, component,
verifyConstraints=False,
@ -631,7 +752,6 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
raise error.SubstrateUnderrunError(
'No EOO seen before substrate ends'
)
asn1Object.verifySizeSpec()
return asn1Object, substrate
@ -671,28 +791,35 @@ class ChoiceDecoder(AbstractConstructedDecoder):
decodeFun=None, substrateFun=None,
**options):
head, tail = substrate[:length], substrate[length:]
if asn1Spec is None:
asn1Object = self.protoComponent.clone(tagSet=tagSet)
else:
asn1Object = asn1Spec.clone()
if substrateFun:
return substrateFun(asn1Object, substrate, length)
if asn1Object.tagSet == tagSet: # explicitly tagged Choice
component, head = decodeFun(
head, asn1Object.componentTagMap, **options
)
else:
component, head = decodeFun(
head, asn1Object.componentTagMap,
tagSet, length, state, **options
)
effectiveTagSet = component.effectiveTagSet
asn1Object.setComponentByType(
effectiveTagSet, component,
verifyConstraints=False,
matchTags=False, matchConstraints=False,
innerFlag=False
)
return asn1Object, tail
def indefLenValueDecoder(self, substrate, asn1Spec,
@ -703,8 +830,10 @@ class ChoiceDecoder(AbstractConstructedDecoder):
asn1Object = self.protoComponent.clone(tagSet=tagSet)
else:
asn1Object = asn1Spec.clone()
if substrateFun:
return substrateFun(asn1Object, substrate, length)
if asn1Object.tagSet == tagSet: # explicitly tagged Choice
component, substrate = decodeFun(
substrate, asn1Object.componentType.tagMapUnique, **options
@ -715,18 +844,22 @@ class ChoiceDecoder(AbstractConstructedDecoder):
)
if eooMarker is not eoo.endOfOctets:
raise error.PyAsn1Error('No EOO seen before substrate ends')
else:
component, substrate = decodeFun(
substrate, asn1Object.componentType.tagMapUnique,
tagSet, length, state, **options
)
effectiveTagSet = component.effectiveTagSet
asn1Object.setComponentByType(
effectiveTagSet, component,
verifyConstraints=False,
matchTags=False, matchConstraints=False,
innerFlag=False
)
return asn1Object, substrate
@ -745,12 +878,12 @@ class AnyDecoder(AbstractSimpleDecoder):
substrate = fullSubstrate
if substrateFun:
return substrateFun(self._createComponent(asn1Spec, tagSet),
return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options),
substrate, length)
head, tail = substrate[:length], substrate[length:]
return self._createComponent(asn1Spec, tagSet, value=head), tail
return self._createComponent(asn1Spec, tagSet, head, **options), tail
def indefLenValueDecoder(self, substrate, asn1Spec,
tagSet=None, length=None, state=None,
@ -769,7 +902,7 @@ class AnyDecoder(AbstractSimpleDecoder):
asn1Spec = self.protoComponent
if substrateFun and substrateFun is not self.substrateCollector:
asn1Object = self._createComponent(asn1Spec, tagSet)
asn1Object = self._createComponent(asn1Spec, tagSet, noValue, **options)
return substrateFun(asn1Object, header + substrate, length + len(header))
# All inner fragments are of the same type, treat them as octet string
@ -789,7 +922,7 @@ class AnyDecoder(AbstractSimpleDecoder):
if substrateFun:
return header, substrate
else:
return self._createComponent(asn1Spec, tagSet, header), substrate
return self._createComponent(asn1Spec, tagSet, header, **options), substrate
# character string types
@ -1159,8 +1292,10 @@ class Decoder(object):
self, substrateFun,
**options
)
if logger:
logger('codec %s yields type %s, value:\n%s\n...remaining substrate is: %s' % (concreteDecoder.__class__.__name__, value.__class__.__name__, isinstance(value, base.Asn1Item) and value.prettyPrint() or value, substrate and debug.hexdump(substrate) or '<none>'))
state = stStop
break
if state is stTryAsExplicitTag:
@ -1190,15 +1325,17 @@ class Decoder(object):
#: Turns BER octet stream into an ASN.1 object.
#:
#: Takes BER octetstream and decode it into an ASN.1 object
#: Takes BER octet-stream and decode it into an ASN.1 object
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
#: may be a scalar or an arbitrary nested structure.
#:
#: Parameters
#: ----------
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: BER octetstream
#: BER octet-stream
#:
#: Keyword Args
#: ------------
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure
#: being decoded, *asn1Spec* may or may not be required. Most common reason for
@ -1212,8 +1349,30 @@ class Decoder(object):
#:
#: Raises
#: ------
#: : :py:class:`pyasn1.error.PyAsn1Error`
#: :py:class:`~pyasn1.error.PyAsn1Error`
#: On decoding errors
#:
#: Examples
#: --------
#: Decode BER serialisation without ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
#: >>> str(s)
#: SequenceOf:
#: 1 2 3
#:
#: Decode BER serialisation with ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq)
#: >>> str(s)
#: SequenceOf:
#: 1 2 3
#:
decode = Decoder(tagMap, typeMap)
# XXX

View File

@ -1,20 +1,25 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import tag, univ, char, useful
from pyasn1 import debug
from pyasn1 import error
from pyasn1.codec.ber import eoo
from pyasn1.compat.octets import int2oct, oct2int, ints2octs, null, str2octs
from pyasn1.compat.integer import to_bytes
from pyasn1 import debug, error
from pyasn1.compat.octets import (int2oct, oct2int, ints2octs, null,
str2octs, isOctetsType)
from pyasn1.type import char
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
__all__ = ['encode']
class AbstractItemEncoder(object):
supportIndefLenMode = 1
supportIndefLenMode = True
# An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)`
eooIntegerSubstrate = (0, 0)
@ -51,17 +56,20 @@ class AbstractItemEncoder(object):
raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen)
return (0x80 | substrateLen,) + substrate
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
raise error.PyAsn1Error('Not implemented')
def encode(self, value, encodeFun, **options):
def encode(self, value, asn1Spec=None, encodeFun=None, **options):
tagSet = value.tagSet
if asn1Spec is None:
tagSet = value.tagSet
else:
tagSet = asn1Spec.tagSet
# untagged item?
if not tagSet:
substrate, isConstructed, isOctets = self.encodeValue(
value, encodeFun, **options
value, asn1Spec, encodeFun, **options
)
return substrate
@ -74,10 +82,10 @@ class AbstractItemEncoder(object):
# base tag?
if not idx:
substrate, isConstructed, isOctets = self.encodeValue(
value, encodeFun, **options
value, asn1Spec, encodeFun, **options
)
if options.get('ifNotEmpty', False) and not substrate:
if not substrate and isConstructed and options.get('ifNotEmpty', False):
return substrate
# primitive form implies definite mode
@ -106,14 +114,14 @@ class AbstractItemEncoder(object):
class EndOfOctetsEncoder(AbstractItemEncoder):
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
return null, False, True
class BooleanEncoder(AbstractItemEncoder):
supportIndefLenMode = False
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
return value and (1,) or (0,), False, False
@ -121,7 +129,7 @@ class IntegerEncoder(AbstractItemEncoder):
supportIndefLenMode = False
supportCompactZero = False
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if value == 0:
# de-facto way to encode zero
if self.supportCompactZero:
@ -133,7 +141,11 @@ class IntegerEncoder(AbstractItemEncoder):
class BitStringEncoder(AbstractItemEncoder):
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is not None:
# TODO: try to avoid ASN.1 schema instantiation
value = asn1Spec.clone(value)
valueLength = len(value)
if valueLength % 8:
alignedValue = value << (8 - valueLength % 8)
@ -145,39 +157,79 @@ class BitStringEncoder(AbstractItemEncoder):
substrate = alignedValue.asOctets()
return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True
baseTag = value.tagSet.baseTag
# strip off explicit tags
alignedValue = alignedValue.clone(
tagSet=tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
)
if baseTag:
tagSet = tag.TagSet(baseTag, baseTag)
else:
tagSet = tag.TagSet()
alignedValue = alignedValue.clone(tagSet=tagSet)
stop = 0
substrate = null
while stop < valueLength:
start = stop
stop = min(start + maxChunkSize * 8, valueLength)
substrate += encodeFun(alignedValue[start:stop], **options)
substrate += encodeFun(alignedValue[start:stop], asn1Spec, **options)
return substrate, True, True
class OctetStringEncoder(AbstractItemEncoder):
def encodeValue(self, value, encodeFun, **options):
maxChunkSize = options.get('maxChunkSize', 0)
if not maxChunkSize or len(value) <= maxChunkSize:
return value.asOctets(), False, True
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is None:
substrate = value.asOctets()
elif not isOctetsType(value):
substrate = asn1Spec.clone(value).asOctets()
else:
# will strip off explicit tags
baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
substrate = value
maxChunkSize = options.get('maxChunkSize', 0)
if not maxChunkSize or len(substrate) <= maxChunkSize:
return substrate, False, True
else:
# strip off explicit tags for inner chunks
if asn1Spec is None:
baseTag = value.tagSet.baseTag
# strip off explicit tags
if baseTag:
tagSet = tag.TagSet(baseTag, baseTag)
else:
tagSet = tag.TagSet()
asn1Spec = value.clone(tagSet=tagSet)
elif not isOctetsType(value):
baseTag = asn1Spec.tagSet.baseTag
# strip off explicit tags
if baseTag:
tagSet = tag.TagSet(baseTag, baseTag)
else:
tagSet = tag.TagSet()
asn1Spec = asn1Spec.clone(tagSet=tagSet)
pos = 0
substrate = null
while True:
chunk = value.clone(value[pos:pos + maxChunkSize],
tagSet=baseTagSet)
chunk = value[pos:pos + maxChunkSize]
if not chunk:
break
substrate += encodeFun(chunk, **options)
substrate += encodeFun(chunk, asn1Spec, **options)
pos += maxChunkSize
return substrate, True, True
@ -186,14 +238,17 @@ class OctetStringEncoder(AbstractItemEncoder):
class NullEncoder(AbstractItemEncoder):
supportIndefLenMode = False
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
return null, False, True
class ObjectIdentifierEncoder(AbstractItemEncoder):
supportIndefLenMode = False
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is not None:
value = asn1Spec.clone(value)
oid = value.asTuple()
# Build the first pair
@ -291,7 +346,10 @@ class RealEncoder(AbstractItemEncoder):
encbase = encBase[i]
return sign, m, encbase, e
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is not None:
value = asn1Spec.clone(value)
if value.isPlusInf:
return (0x40,), False, False
if value.isMinusInf:
@ -362,44 +420,116 @@ class RealEncoder(AbstractItemEncoder):
class SequenceEncoder(AbstractItemEncoder):
def encodeValue(self, value, encodeFun, **options):
value.verifySizeSpec()
omitEmptyOptionals = False
# TODO: handling three flavors of input is too much -- split over codecs
def encodeValue(self, value, asn1Spec, encodeFun, **options):
namedTypes = value.componentType
substrate = null
idx = len(value)
while idx > 0:
idx -= 1
if namedTypes:
if namedTypes[idx].isOptional and not value[idx].isValue:
if asn1Spec is None:
# instance of ASN.1 schema
value.verifySizeSpec()
namedTypes = value.componentType
for idx, component in enumerate(value.values()):
if namedTypes:
namedType = namedTypes[idx]
if namedType.isOptional and not component.isValue:
continue
if namedType.isDefaulted and component == namedType.asn1Object:
continue
if self.omitEmptyOptionals:
options.update(ifNotEmpty=namedType.isOptional)
chunk = encodeFun(component, asn1Spec, **options)
# wrap open type blob if needed
if namedTypes and namedType.openType:
wrapType = namedType.asn1Object
if wrapType.tagSet and not wrapType.isSameTypeWith(component):
chunk = encodeFun(chunk, wrapType, **options)
substrate += chunk
else:
# bare Python value + ASN.1 schema
for idx, namedType in enumerate(asn1Spec.componentType.namedTypes):
try:
component = value[namedType.name]
except KeyError:
raise error.PyAsn1Error('Component name "%s" not found in %r' % (namedType.name, value))
if namedType.isOptional and namedType.name not in value:
continue
if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object:
if namedType.isDefaulted and component == namedType.asn1Object:
continue
substrate = encodeFun(value[idx], **options) + substrate
if self.omitEmptyOptionals:
options.update(ifNotEmpty=namedType.isOptional)
chunk = encodeFun(component, asn1Spec[idx], **options)
# wrap open type blob if needed
if namedType.openType:
wrapType = namedType.asn1Object
if wrapType.tagSet and not wrapType.isSameTypeWith(component):
chunk = encodeFun(chunk, wrapType, **options)
substrate += chunk
return substrate, True, True
class SequenceOfEncoder(AbstractItemEncoder):
def encodeValue(self, value, encodeFun, **options):
value.verifySizeSpec()
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is None:
value.verifySizeSpec()
else:
asn1Spec = asn1Spec.componentType
substrate = null
idx = len(value)
while idx > 0:
idx -= 1
substrate = encodeFun(value[idx], **options) + substrate
for idx, component in enumerate(value):
substrate += encodeFun(value[idx], asn1Spec, **options)
return substrate, True, True
class ChoiceEncoder(AbstractItemEncoder):
def encodeValue(self, value, encodeFun, **options):
return encodeFun(value.getComponent(), **options), True, True
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is None:
component = value.getComponent()
else:
names = [namedType.name for namedType in asn1Spec.componentType.namedTypes
if namedType.name in value]
if len(names) != 1:
raise error.PyAsn1Error('%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', value))
name = names[0]
component = value[name]
asn1Spec = asn1Spec[name]
return encodeFun(component, asn1Spec, **options), True, True
class AnyEncoder(OctetStringEncoder):
def encodeValue(self, value, encodeFun, **options):
return value.asOctets(), not options.get('defMode', True), True
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is None:
value = value.asOctets()
elif not isOctetsType(value):
value = asn1Spec.clone(value).asOctets()
return value, not options.get('defMode', True), True
tagMap = {
@ -479,7 +609,16 @@ class Encoder(object):
self.__tagMap = tagMap
self.__typeMap = typeMap
def __call__(self, value, **options):
def __call__(self, value, asn1Spec=None, **options):
try:
if asn1Spec is None:
typeId = value.typeId
else:
typeId = asn1Spec.typeId
except AttributeError:
raise error.PyAsn1Error('Value %r is not ASN.1 type instance '
'and "asn1Spec" not given' % (value,))
if debug.logger & debug.flagEncoder:
logger = debug.logger
@ -487,7 +626,8 @@ class Encoder(object):
logger = None
if logger:
logger('encoder called in %sdef mode, chunk size %s for type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), value.prettyPrintType(), value.prettyPrint()))
logger('encoder called in %sdef mode, chunk size %s for '
'type %s, value:\n%s' % (not options.get('defMode', True) and 'in' or '', options.get('maxChunkSize', 0), asn1Spec is None and value.prettyPrintType() or asn1Spec.prettyPrintType(), value))
if self.fixedDefLengthMode is not None:
options.update(defMode=self.fixedDefLengthMode)
@ -495,25 +635,32 @@ class Encoder(object):
if self.fixedChunkSize is not None:
options.update(maxChunkSize=self.fixedChunkSize)
tagSet = value.tagSet
try:
concreteEncoder = self.__typeMap[value.typeId]
concreteEncoder = self.__typeMap[typeId]
if logger:
logger('using value codec %s chosen by type ID %s' % (concreteEncoder.__class__.__name__, typeId))
except KeyError:
if asn1Spec is None:
tagSet = value.tagSet
else:
tagSet = asn1Spec.tagSet
# use base type for codec lookup to recover untagged types
baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
baseTagSet = tag.TagSet(tagSet.baseTag, tagSet.baseTag)
try:
concreteEncoder = self.__tagMap[baseTagSet]
except KeyError:
raise error.PyAsn1Error('No encoder for %s' % (value,))
raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet))
if logger:
logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
if logger:
logger('using value codec %s chosen by tagSet %s' % (concreteEncoder.__class__.__name__, tagSet))
substrate = concreteEncoder.encode(value, self, **options)
substrate = concreteEncoder.encode(value, asn1Spec, self, **options)
if logger:
logger('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate)))
@ -527,8 +674,14 @@ class Encoder(object):
#:
#: Parameters
#: ----------
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
#: A pyasn1 object to encode
#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
#: A Python or pyasn1 object to encode. If Python object is given, `asnSpec`
#: parameter is required to guide the encoding process.
#:
#: Keyword Args
#: ------------
#: asn1Spec:
#: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
#:
#: defMode: :py:class:`bool`
#: If `False`, produces indefinite length encoding
@ -543,6 +696,26 @@ class Encoder(object):
#:
#: Raises
#: ------
#: : :py:class:`pyasn1.error.PyAsn1Error`
#: :py:class:`~pyasn1.error.PyAsn1Error`
#: On encoding errors
#:
#: Examples
#: --------
#: Encode Python value into BER with ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> encode([1, 2, 3], asn1Spec=seq)
#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
#:
#: Encode ASN.1 value object into BER
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> seq.extend([1, 2, 3])
#: >>> encode(seq)
#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
#:
encode = Encoder(tagMap, typeMap)

View File

@ -1,10 +1,13 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import base, tag
from pyasn1.type import base
from pyasn1.type import tag
__all__ = ['endOfOctets']
class EndOfOctets(base.AbstractSimpleAsn1Item):

View File

@ -1,13 +1,13 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import univ
from pyasn1 import error
from pyasn1.codec.ber import decoder
from pyasn1.compat.octets import oct2int
from pyasn1 import error
from pyasn1.type import univ
__all__ = ['decode']
@ -25,14 +25,14 @@ class BooleanDecoder(decoder.AbstractSimpleDecoder):
byte = oct2int(head[0])
# CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while
# BER allows any non-zero value as TRUE; cf. sections 8.2.2. and 11.1
# in http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
# in https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
if byte == 0xff:
value = 1
elif byte == 0x00:
value = 0
else:
raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte)
return self._createComponent(asn1Spec, tagSet, value), tail
return self._createComponent(asn1Spec, tagSet, value, **options), tail
# TODO: prohibit non-canonical encoding
BitStringDecoder = decoder.BitStringDecoder
@ -63,15 +63,17 @@ class Decoder(decoder.Decoder):
#: Turns CER octet stream into an ASN.1 object.
#:
#: Takes CER octetstream and decode it into an ASN.1 object
#: Takes CER octet-stream and decode it into an ASN.1 object
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
#: may be a scalar or an arbitrary nested structure.
#:
#: Parameters
#: ----------
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: CER octetstream
#: CER octet-stream
#:
#: Keyword Args
#: ------------
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure
#: being decoded, *asn1Spec* may or may not be required. Most common reason for
@ -85,6 +87,28 @@ class Decoder(decoder.Decoder):
#:
#: Raises
#: ------
#: : :py:class:`pyasn1.error.PyAsn1Error`
#: :py:class:`~pyasn1.error.PyAsn1Error`
#: On decoding errors
#:
#: Examples
#: --------
#: Decode CER serialisation without ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> s, _ = decode(b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00')
#: >>> str(s)
#: SequenceOf:
#: 1 2 3
#:
#: Decode CER serialisation with ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> s, _ = decode(b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00', asn1Spec=seq)
#: >>> str(s)
#: SequenceOf:
#: 1 2 3
#:
decode = Decoder(tagMap, decoder.typeMap)

View File

@ -1,20 +1,20 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import univ
from pyasn1.type import useful
from pyasn1 import error
from pyasn1.codec.ber import encoder
from pyasn1.compat.octets import str2octs, null
from pyasn1 import error
from pyasn1.type import univ
from pyasn1.type import useful
__all__ = ['encode']
class BooleanEncoder(encoder.IntegerEncoder):
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if value == 0:
substrate = (0,)
else:
@ -38,7 +38,7 @@ class TimeEncoderMixIn(object):
minLength = 12
maxLength = 19
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
# Encoding constraints:
# - minutes are mandatory, seconds are optional
# - subseconds must NOT be zero
@ -46,6 +46,9 @@ class TimeEncoderMixIn(object):
# - time in UTC (Z)
# - only dot is allowed for fractions
if asn1Spec is not None:
value = asn1Spec.clone(value)
octets = value.asOctets()
if not self.minLength < len(octets) < self.maxLength:
@ -63,7 +66,7 @@ class TimeEncoderMixIn(object):
options.update(maxChunkSize=1000)
return encoder.OctetStringEncoder.encodeValue(
self, value, encodeFun, **options
self, value, asn1Spec, encodeFun, **options
)
@ -77,88 +80,140 @@ class UTCTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder):
maxLength = 14
class SetOfEncoder(encoder.SequenceOfEncoder):
class SetEncoder(encoder.SequenceEncoder):
@staticmethod
def _sortComponents(components):
# sort by tags regardless of the Choice value (static sort)
return sorted(components, key=lambda x: isinstance(x, univ.Choice) and x.minTagSet or x.tagSet)
def _componentSortKey(componentAndType):
"""Sort SET components by tag
def encodeValue(self, value, encodeFun, **options):
value.verifySizeSpec()
substrate = null
idx = len(value)
if value.typeId == univ.Set.typeId:
namedTypes = value.componentType
comps = []
compsMap = {}
while idx > 0:
idx -= 1
if namedTypes:
if namedTypes[idx].isOptional and not value[idx].isValue:
continue
if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object:
continue
Sort regardless of the Choice value (static sort)
"""
component, asn1Spec = componentAndType
comps.append(value[idx])
compsMap[id(value[idx])] = namedTypes and namedTypes[idx].isOptional
if asn1Spec is None:
asn1Spec = component
for comp in self._sortComponents(comps):
options.update(ifNotEmpty=compsMap[id(comp)])
substrate += encodeFun(comp, **options)
if asn1Spec.typeId == univ.Choice.typeId and not asn1Spec.tagSet:
if asn1Spec.tagSet:
return asn1Spec.tagSet
else:
return asn1Spec.componentType.minTagSet
else:
components = [encodeFun(x, **options) for x in value]
return asn1Spec.tagSet
# sort by serialized and padded components
if len(components) > 1:
zero = str2octs('\x00')
maxLen = max(map(len, components))
paddedComponents = [
(x.ljust(maxLen, zero), x) for x in components
def encodeValue(self, value, asn1Spec, encodeFun, **options):
substrate = null
comps = []
compsMap = {}
if asn1Spec is None:
# instance of ASN.1 schema
value.verifySizeSpec()
namedTypes = value.componentType
for idx, component in enumerate(value.values()):
if namedTypes:
namedType = namedTypes[idx]
if namedType.isOptional and not component.isValue:
continue
if namedType.isDefaulted and component == namedType.asn1Object:
continue
compsMap[id(component)] = namedType
else:
compsMap[id(component)] = None
comps.append((component, asn1Spec))
else:
# bare Python value + ASN.1 schema
for idx, namedType in enumerate(asn1Spec.componentType.namedTypes):
try:
component = value[namedType.name]
except KeyError:
raise error.PyAsn1Error('Component name "%s" not found in %r' % (namedType.name, value))
if namedType.isOptional and namedType.name not in value:
continue
if namedType.isDefaulted and component == namedType.asn1Object:
continue
compsMap[id(component)] = namedType
comps.append((component, asn1Spec[idx]))
for comp, compType in sorted(comps, key=self._componentSortKey):
namedType = compsMap[id(comp)]
if namedType:
options.update(ifNotEmpty=namedType.isOptional)
chunk = encodeFun(comp, compType, **options)
# wrap open type blob if needed
if namedType and namedType.openType:
wrapType = namedType.asn1Object
if wrapType.tagSet and not wrapType.isSameTypeWith(comp):
chunk = encodeFun(chunk, wrapType, **options)
substrate += chunk
return substrate, True, True
class SetOfEncoder(encoder.SequenceOfEncoder):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if asn1Spec is None:
value.verifySizeSpec()
else:
asn1Spec = asn1Spec.componentType
components = [encodeFun(x, asn1Spec, **options)
for x in value]
# sort by serialised and padded components
if len(components) > 1:
zero = str2octs('\x00')
maxLen = max(map(len, components))
paddedComponents = [
(x.ljust(maxLen, zero), x) for x in components
]
paddedComponents.sort(key=lambda x: x[0])
paddedComponents.sort(key=lambda x: x[0])
components = [x[1] for x in paddedComponents]
components = [x[1] for x in paddedComponents]
substrate = null.join(components)
substrate = null.join(components)
return substrate, True, True
class SequenceEncoder(encoder.SequenceEncoder):
def encodeValue(self, value, encodeFun, **options):
value.verifySizeSpec()
namedTypes = value.componentType
substrate = null
idx = len(value)
while idx > 0:
idx -= 1
if namedTypes:
if namedTypes[idx].isOptional and not value[idx].isValue:
continue
if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object:
continue
options.update(ifNotEmpty=namedTypes and namedTypes[idx].isOptional)
substrate = encodeFun(value[idx], **options) + substrate
return substrate, True, True
omitEmptyOptionals = True
class SequenceOfEncoder(encoder.SequenceOfEncoder):
def encodeValue(self, value, encodeFun, **options):
def encodeValue(self, value, asn1Spec, encodeFun, **options):
if options.get('ifNotEmpty', False) and not len(value):
return null, True, True
if asn1Spec is None:
value.verifySizeSpec()
else:
asn1Spec = asn1Spec.componentType
substrate = null
idx = len(value)
if options.get('ifNotEmpty', False) and not idx:
return substrate, True, True
for idx, component in enumerate(value):
substrate += encodeFun(value[idx], asn1Spec, **options)
value.verifySizeSpec()
while idx > 0:
idx -= 1
substrate = encodeFun(value[idx], **options) + substrate
return substrate, True, True
@ -180,7 +235,7 @@ typeMap.update({
useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(),
useful.UTCTime.typeId: UTCTimeEncoder(),
# Sequence & Set have same tags as SequenceOf & SetOf
univ.Set.typeId: SetOfEncoder(),
univ.Set.typeId: SetEncoder(),
univ.SetOf.typeId: SetOfEncoder(),
univ.Sequence.typeId: SequenceEncoder(),
univ.SequenceOf.typeId: SequenceOfEncoder()
@ -198,24 +253,44 @@ class Encoder(encoder.Encoder):
#:
#: Parameters
#: ----------
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
#: A pyasn1 object to encode
#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
#: A Python or pyasn1 object to encode. If Python object is given, `asnSpec`
#: parameter is required to guide the encoding process.
#:
#: defMode: :py:class:`bool`
#: If `False`, produces indefinite length encoding
#:
#: maxChunkSize: :py:class:`int`
#: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
#: Keyword Args
#: ------------
#: asn1Spec:
#: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
#:
#: Returns
#: -------
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: Given ASN.1 object encoded into BER octetstream
#: Given ASN.1 object encoded into BER octet-stream
#:
#: Raises
#: ------
#: : :py:class:`pyasn1.error.PyAsn1Error`
#: :py:class:`~pyasn1.error.PyAsn1Error`
#: On encoding errors
#:
#: Examples
#: --------
#: Encode Python value into CER with ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> encode([1, 2, 3], asn1Spec=seq)
#: b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00'
#:
#: Encode ASN.1 value object into CER
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> seq.extend([1, 2, 3])
#: >>> encode(seq)
#: b'0\x80\x02\x01\x01\x02\x01\x02\x02\x01\x03\x00\x00'
#:
encode = Encoder(tagMap, typeMap)
# EncoderFactory queries class instance and builds a map of tags -> encoders

View File

@ -1,11 +1,11 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import univ
from pyasn1.codec.cer import decoder
from pyasn1.type import univ
__all__ = ['decode']
@ -43,15 +43,17 @@ class Decoder(decoder.Decoder):
#: Turns DER octet stream into an ASN.1 object.
#:
#: Takes DER octetstream and decode it into an ASN.1 object
#: Takes DER octet-stream and decode it into an ASN.1 object
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
#: may be a scalar or an arbitrary nested structure.
#:
#: Parameters
#: ----------
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: DER octetstream
#: DER octet-stream
#:
#: Keyword Args
#: ------------
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
#: A pyasn1 type object to act as a template guiding the decoder. Depending on the ASN.1 structure
#: being decoded, *asn1Spec* may or may not be required. Most common reason for
@ -65,6 +67,28 @@ class Decoder(decoder.Decoder):
#:
#: Raises
#: ------
#: : :py:class:`pyasn1.error.PyAsn1Error`
#: :py:class:`~pyasn1.error.PyAsn1Error`
#: On decoding errors
#:
#: Examples
#: --------
#: Decode DER serialisation without ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03')
#: >>> str(s)
#: SequenceOf:
#: 1 2 3
#:
#: Decode DER serialisation with ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> s, _ = decode(b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03', asn1Spec=seq)
#: >>> str(s)
#: SequenceOf:
#: 1 2 3
#:
decode = Decoder(tagMap, typeMap)

View File

@ -1,32 +1,57 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import univ
from pyasn1 import error
from pyasn1.codec.cer import encoder
from pyasn1.type import univ
__all__ = ['encode']
class SetOfEncoder(encoder.SetOfEncoder):
class SetEncoder(encoder.SetEncoder):
@staticmethod
def _sortComponents(components):
# sort by tags depending on the actual Choice value (dynamic sort)
return sorted(components, key=lambda x: isinstance(x, univ.Choice) and x.getComponent().tagSet or x.tagSet)
def _componentSortKey(componentAndType):
"""Sort SET components by tag
Sort depending on the actual Choice value (dynamic sort)
"""
component, asn1Spec = componentAndType
if asn1Spec is None:
compType = component
else:
compType = asn1Spec
if compType.typeId == univ.Choice.typeId and not compType.tagSet:
if asn1Spec is None:
return component.getComponent().tagSet
else:
# TODO: move out of sorting key function
names = [namedType.name for namedType in asn1Spec.componentType.namedTypes
if namedType.name in component]
if len(names) != 1:
raise error.PyAsn1Error(
'%s components for Choice at %r' % (len(names) and 'Multiple ' or 'None ', component))
# TODO: support nested CHOICE ordering
return asn1Spec[names[0]].tagSet
else:
return compType.tagSet
tagMap = encoder.tagMap.copy()
tagMap.update({
# Set & SetOf have same tags
univ.SetOf.tagSet: SetOfEncoder()
univ.Set.tagSet: SetEncoder()
})
typeMap = encoder.typeMap.copy()
typeMap.update({
# Set & SetOf have same tags
univ.Set.typeId: SetOfEncoder(),
univ.SetOf.typeId: SetOfEncoder()
univ.Set.typeId: SetEncoder()
})
@ -41,22 +66,42 @@ class Encoder(encoder.Encoder):
#:
#: Parameters
#: ----------
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
#: A pyasn1 object to encode
#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
#: A Python or pyasn1 object to encode. If Python object is given, `asnSpec`
#: parameter is required to guide the encoding process.
#:
#: defMode: :py:class:`bool`
#: If `False`, produces indefinite length encoding
#:
#: maxChunkSize: :py:class:`int`
#: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
#: Keyword Args
#: ------------
#: asn1Spec:
#: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
#:
#: Returns
#: -------
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
#: Given ASN.1 object encoded into BER octetstream
#: Given ASN.1 object encoded into BER octet-stream
#:
#: Raises
#: ------
#: : :py:class:`pyasn1.error.PyAsn1Error`
#: :py:class:`~pyasn1.error.PyAsn1Error`
#: On encoding errors
#:
#: Examples
#: --------
#: Encode Python value into DER with ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> encode([1, 2, 3], asn1Spec=seq)
#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
#:
#: Encode ASN.1 value object into DER
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> seq.extend([1, 2, 3])
#: >>> encode(seq)
#: b'0\t\x02\x01\x01\x02\x01\x02\x02\x01\x03'
#:
encode = Encoder(tagMap, typeMap)

View File

@ -1,11 +1,16 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.type import base, univ, char, useful, tag
from pyasn1 import debug, error
from pyasn1 import debug
from pyasn1 import error
from pyasn1.type import base
from pyasn1.type import char
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
__all__ = ['decode']
@ -177,6 +182,8 @@ class Decoder(object):
#: pyObject: :py:class:`object`
#: A scalar or nested Python objects
#:
#: Keyword Args
#: ------------
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
#: A pyasn1 type object to act as a template guiding the decoder. It is required
#: for successful interpretation of Python objects mapping into their ASN.1
@ -189,6 +196,19 @@ class Decoder(object):
#:
#: Raises
#: ------
#: : :py:class:`pyasn1.error.PyAsn1Error`
#: :py:class:`~pyasn1.error.PyAsn1Error`
#: On decoding errors
#:
#: Examples
#: --------
#: Decode native Python object into ASN.1 objects with ASN.1 schema
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> s, _ = decode([1, 2, 3], asn1Spec=seq)
#: >>> str(s)
#: SequenceOf:
#: 1 2 3
#:
decode = Decoder(tagMap, typeMap)

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
try:
from collections import OrderedDict
@ -10,8 +10,13 @@ try:
except ImportError:
OrderedDict = dict
from pyasn1.type import base, univ, tag, char, useful
from pyasn1 import debug, error
from pyasn1 import debug
from pyasn1 import error
from pyasn1.type import base
from pyasn1.type import char
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
__all__ = ['encode']
@ -43,7 +48,7 @@ class OctetStringEncoder(AbstractItemEncoder):
class TextStringEncoder(AbstractItemEncoder):
def encode(self, value, encodeFun, **options):
return value.prettyPrint()
return str(value)
class NullEncoder(AbstractItemEncoder):
@ -207,6 +212,18 @@ class Encoder(object):
#:
#: Raises
#: ------
#: : :py:class:`pyasn1.error.PyAsn1Error`
#: :py:class:`~pyasn1.error.PyAsn1Error`
#: On encoding errors
#:
#: Examples
#: --------
#: Encode ASN.1 value object into native Python types
#:
#: .. code-block:: pycon
#:
#: >>> seq = SequenceOf(componentType=Integer())
#: >>> seq.extend([1, 2, 3])
#: >>> encode(seq)
#: [1, 2, 3]
#:
encode = Encoder(tagMap, typeMap)

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from sys import version_info

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from sys import version_info

View File

@ -1,12 +1,12 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from sys import version_info
from datetime import datetime
import time
from datetime import datetime
from sys import version_info
__all__ = ['strptime']

View File

@ -1,12 +1,14 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
try:
import platform
implementation = platform.python_implementation()
except (ImportError, AttributeError):

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from sys import version_info

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from sys import version_info

View File

@ -1,13 +1,14 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import logging
from pyasn1.compat.octets import octs2ints
from pyasn1 import error
from pyasn1 import __version__
from pyasn1 import error
from pyasn1.compat.octets import octs2ints
__all__ = ['Debug', 'setLogger', 'hexdump']
@ -17,6 +18,7 @@ flagDecoder = 0x0002
flagAll = 0xffff
flagMap = {
'none': flagNone,
'encoder': flagEncoder,
'decoder': flagDecoder,
'all': flagAll

View File

@ -1,18 +1,29 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
class PyAsn1Error(Exception):
pass
"""Create pyasn1 exception object
The `PyAsn1Error` exception represents generic, usually fatal, error.
"""
class ValueConstraintError(PyAsn1Error):
pass
"""Create pyasn1 exception object
The `ValueConstraintError` exception indicates an ASN.1 value
constraint violation.
"""
class SubstrateUnderrunError(PyAsn1Error):
pass
"""Create pyasn1 exception object
The `SubstrateUnderrunError` exception indicates insufficient serialised
data on input of a deserialisation routine.
"""

View File

@ -1,13 +1,16 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
from pyasn1.type import constraint, tagmap, tag
from pyasn1.compat import calling
from pyasn1 import error
from pyasn1.compat import calling
from pyasn1.type import constraint
from pyasn1.type import tag
from pyasn1.type import tagmap
__all__ = ['Asn1Item', 'Asn1ItemBase', 'AbstractSimpleAsn1Item', 'AbstractConstructedAsn1Item']
@ -52,6 +55,9 @@ class Asn1ItemBase(Asn1Item):
self.__dict__[name] = value
def __str__(self):
return self.prettyPrint()
@property
def readOnly(self):
return self._readOnly
@ -75,7 +81,7 @@ class Asn1ItemBase(Asn1Item):
(:py:mod:`~pyasn1.type.constraint`) are examined when carrying
out ASN.1 types comparison.
No Python inheritance relationship between PyASN1 objects is considered.
Python class inheritance relationship is NOT considered.
Parameters
----------
@ -94,18 +100,17 @@ class Asn1ItemBase(Asn1Item):
def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
"""Examine |ASN.1| type for subtype relationship with other ASN.1 type.
ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
(:py:mod:`~pyasn1.type.constraint`) are examined when carrying
out ASN.1 types comparison.
No Python inheritance relationship between PyASN1 objects is considered.
Python class inheritance relationship is NOT considered.
Parameters
----------
other: a pyasn1 type object
Class instance representing ASN.1 type.
Class instance representing ASN.1 type.
Returns
-------
@ -120,10 +125,13 @@ class Asn1ItemBase(Asn1Item):
@staticmethod
def isNoValue(*values):
for value in values:
if value is not None and value is not noValue:
if value is not noValue:
return False
return True
def prettyPrint(self, scope=0):
raise NotImplementedError()
# backward compatibility
def getTagSet(self):
@ -145,15 +153,42 @@ class Asn1ItemBase(Asn1Item):
class NoValue(object):
"""Create a singleton instance of NoValue class.
NoValue object can be used as an initializer on PyASN1 type class
instantiation to represent ASN.1 type rather than ASN.1 data value.
The *NoValue* sentinel object represents an instance of ASN.1 schema
object as opposed to ASN.1 value object.
No operations other than type comparison can be performed on
a PyASN1 type object.
Only ASN.1 schema-related operations can be performed on ASN.1
schema objects.
Warning
-------
Any operation attempted on the *noValue* object will raise the
*PyAsn1Error* exception.
"""
skipMethods = ('__getattribute__', '__getattr__', '__setattr__', '__delattr__',
'__class__', '__init__', '__del__', '__new__', '__repr__',
'__qualname__', '__objclass__', 'im_class', '__sizeof__')
skipMethods = set(
('__slots__',
# attributes
'__getattribute__',
'__getattr__',
'__setattr__',
'__delattr__',
# class instance
'__class__',
'__init__',
'__del__',
'__new__',
'__repr__',
'__qualname__',
'__objclass__',
'im_class',
'__sizeof__',
# pickle protocol
'__reduce__',
'__reduce_ex__',
'__getnewargs__',
'__getinitargs__',
'__getstate__',
'__setstate__')
)
_instance = None
@ -161,7 +196,7 @@ class NoValue(object):
if cls._instance is None:
def getPlug(name):
def plug(self, *args, **kw):
raise error.PyAsn1Error('Uninitialized ASN.1 value ("%s" attribute looked up)' % name)
raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % name)
return plug
op_names = [name
@ -181,11 +216,13 @@ class NoValue(object):
def __getattr__(self, attr):
if attr in self.skipMethods:
raise AttributeError('attribute %s not present' % attr)
raise error.PyAsn1Error('No value for "%s"' % attr)
raise AttributeError('Attribute %s not present' % attr)
raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % attr)
def __repr__(self):
return '%s()' % self.__class__.__name__
return '<%s object at 0x%x>' % (self.__class__.__name__, id(self))
noValue = NoValue()
@ -197,7 +234,7 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
def __init__(self, value=noValue, **kwargs):
Asn1ItemBase.__init__(self, **kwargs)
if value is noValue or value is None:
if value is noValue:
value = self.defaultValue
else:
value = self.prettyIn(value)
@ -211,17 +248,21 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
self._value = value
def __repr__(self):
representation = []
if self._value is not self.defaultValue:
representation.append(self.prettyOut(self._value))
if self.tagSet is not self.__class__.tagSet:
representation.append('tagSet=%r' % (self.tagSet,))
if self.subtypeSpec is not self.__class__.subtypeSpec:
representation.append('subtypeSpec=%r' % (self.subtypeSpec,))
return '%s(%s)' % (self.__class__.__name__, ', '.join(representation))
representation = '%s %s object at 0x%x' % (
self.__class__.__name__, self.isValue and 'value' or 'schema', id(self)
)
def __str__(self):
return str(self._value)
for attr, value in self.readOnly.items():
if value:
representation += ' %s %s' % (attr, value)
if self.isValue:
value = self.prettyPrint()
if len(value) > 32:
value = value[:16] + '...' + value[-16:]
representation += ' payload [%s]' % value
return '<%s>' % representation
def __eq__(self, other):
return self is other and True or self._value == other
@ -253,53 +294,50 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
@property
def isValue(self):
"""Indicate if |ASN.1| object represents ASN.1 type or ASN.1 value.
"""Indicate that |ASN.1| object represents ASN.1 value.
In other words, if *isValue* is `True`, then the ASN.1 object is
initialized.
If *isValue* is `False` then this object represents just ASN.1 schema.
If *isValue* is `True` then, in addition to its ASN.1 schema features,
this object can also be used like a Python built-in object (e.g. `int`,
`str`, `dict` etc.).
Returns
-------
: :class:`bool`
:class:`True` if object represents ASN.1 value and type,
:class:`False` if object represents just ASN.1 type.
:class:`False` if object represents just ASN.1 schema.
:class:`True` if object represents ASN.1 schema and can be used as a normal value.
Note
----
There is an important distinction between PyASN1 type and value objects.
The PyASN1 type objects can only participate in ASN.1 type
operations (subtyping, comparison etc) and serve as a
blueprint for serialization codecs to resolve ambiguous types.
There is an important distinction between PyASN1 schema and value objects.
The PyASN1 schema objects can only participate in ASN.1 schema-related
operations (e.g. defining or testing the structure of the data). Most
obvious uses of ASN.1 schema is to guide serialisation codecs whilst
encoding/decoding serialised ASN.1 contents.
The PyASN1 value objects can additionally participate in most
of built-in Python operations.
The PyASN1 value objects can **additionally** participate in many operations
involving regular Python objects (e.g. arithmetic, comprehension etc).
"""
return self._value is not noValue
def clone(self, value=noValue, **kwargs):
"""Create a copy of a |ASN.1| type or object.
"""Create a modified version of |ASN.1| schema or value object.
Any parameters to the *clone()* method will replace corresponding
properties of the |ASN.1| object.
The `clone()` method accepts the same set arguments as |ASN.1|
class takes on instantiation except that all arguments
of the `clone()` method are optional.
Parameters
----------
value: :class:`tuple`, :class:`str` or |ASN.1| object
Initialization value to pass to new ASN.1 object instead of
inheriting one from the caller.
Whatever arguments are supplied, they are used to create a copy
of `self` taking precedence over the ones used to instantiate `self`.
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
Object representing ASN.1 tag(s) to use in new object instead of inheriting from the caller
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Object representing ASN.1 subtype constraint(s) to use in new object instead of inheriting from the caller
Returns
-------
:
new instance of |ASN.1| type/value
Note
----
Due to the immutable nature of the |ASN.1| object, if no arguments
are supplied, no new |ASN.1| object will be created and `self` will
be returned instead.
"""
if value is noValue or value is None:
if value is noValue:
if not kwargs:
return self
@ -311,37 +349,53 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
return self.__class__(value, **initilaizers)
def subtype(self, value=noValue, **kwargs):
"""Create a copy of a |ASN.1| type or object.
"""Create a specialization of |ASN.1| schema or value object.
Any parameters to the *subtype()* method will be added to the corresponding
properties of the |ASN.1| object.
The subtype relationship between ASN.1 types has no correlation with
subtype relationship between Python types. ASN.1 type is mainly identified
by its tag(s) (:py:class:`~pyasn1.type.tag.TagSet`) and value range
constraints (:py:class:`~pyasn1.type.constraint.ConstraintsIntersection`).
These ASN.1 type properties are implemented as |ASN.1| attributes.
Parameters
----------
value: :class:`tuple`, :class:`str` or |ASN.1| object
Initialization value to pass to new ASN.1 object instead of
inheriting one from the caller.
The `subtype()` method accepts the same set arguments as |ASN.1|
class takes on instantiation except that all parameters
of the `subtype()` method are optional.
implicitTag: :py:class:`~pyasn1.type.tag.Tag`
Implicitly apply given ASN.1 tag object to caller's
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
new object's ASN.1 tag(s).
With the exception of the arguments described below, the rest of
supplied arguments they are used to create a copy of `self` taking
precedence over the ones used to instantiate `self`.
explicitTag: :py:class:`~pyasn1.type.tag.Tag`
Explicitly apply given ASN.1 tag object to caller's
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
new object's ASN.1 tag(s).
The following arguments to `subtype()` create a ASN.1 subtype out of
|ASN.1| type:
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Add ASN.1 constraints object to one of the caller, then
use the result as new object's ASN.1 constraints.
Other Parameters
----------------
implicitTag: :py:class:`~pyasn1.type.tag.Tag`
Implicitly apply given ASN.1 tag object to `self`'s
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
new object's ASN.1 tag(s).
Returns
-------
:
new instance of |ASN.1| type/value
explicitTag: :py:class:`~pyasn1.type.tag.Tag`
Explicitly apply given ASN.1 tag object to `self`'s
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
new object's ASN.1 tag(s).
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Add ASN.1 constraints object to one of the `self`'s, then
use the result as new object's ASN.1 constraints.
Returns
-------
:
new instance of |ASN.1| schema or value object
Note
----
Due to the immutable nature of the |ASN.1| object, if no arguments
are supplied, no new |ASN.1| object will be created and `self` will
be returned instead.
"""
if value is noValue or value is None:
if value is noValue:
if not kwargs:
return self
@ -369,21 +423,7 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
return str(value)
def prettyPrint(self, scope=0):
"""Provide human-friendly printable object representation.
Returns
-------
: :class:`str`
human-friendly type and/or value representation.
"""
if self.isValue:
return self.prettyOut(self._value)
else:
return '<no value>'
# XXX Compatibility stub
def prettyPrinter(self, scope=0):
return self.prettyPrint(scope)
return self.prettyOut(self._value)
# noinspection PyUnusedLocal
def prettyPrintType(self, scope=0):
@ -408,22 +448,6 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
# of types for Sequence/Set/Choice.
#
def setupComponent():
"""Returns a sentinel value.
Indicates to a constructed type to set up its inner component so that it
can be referred to. This is useful in situation when you want to populate
descendants of a constructed type what requires being able to refer to
their parent types along the way.
Example
-------
>>> constructed['record'] = setupComponent()
>>> constructed['record']['scalar'] = 42
"""
return noValue
class AbstractConstructedAsn1Item(Asn1ItemBase):
@ -446,20 +470,18 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
self._componentValues = []
def __repr__(self):
representation = []
if self.componentType is not self.__class__.componentType:
representation.append('componentType=%r' % (self.componentType,))
if self.tagSet is not self.__class__.tagSet:
representation.append('tagSet=%r' % (self.tagSet,))
if self.subtypeSpec is not self.__class__.subtypeSpec:
representation.append('subtypeSpec=%r' % (self.subtypeSpec,))
representation = '%s(%s)' % (self.__class__.__name__, ', '.join(representation))
if self._componentValues:
for idx, component in enumerate(self._componentValues):
if component is None or component is noValue:
continue
representation += '.setComponentByPosition(%d, %s)' % (idx, repr(component))
return representation
representation = '%s %s object at 0x%x' % (
self.__class__.__name__, self.isValue and 'value' or 'schema', id(self)
)
for attr, value in self.readOnly.items():
if value is not noValue:
representation += ' %s=%r' % (attr, value)
if self.isValue and self._componentValues:
representation += ' payload [%s]' % ', '.join([repr(x) for x in self._componentValues])
return '<%s>' % representation
def __eq__(self, other):
return self is other and True or self._componentValues == other
@ -486,31 +508,35 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
def __bool__(self):
return self._componentValues and True or False
def __len__(self):
return len(self._componentValues)
def _cloneComponentValues(self, myClone, cloneValueFlag):
pass
def clone(self, **kwargs):
"""Create a copy of a |ASN.1| type or object.
"""Create a modified version of |ASN.1| schema object.
Any parameters to the *clone()* method will replace corresponding
properties of the |ASN.1| object.
The `clone()` method accepts the same set arguments as |ASN.1|
class takes on instantiation except that all arguments
of the `clone()` method are optional.
Parameters
----------
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
Object representing non-default ASN.1 tag(s)
Whatever arguments are supplied, they are used to create a copy
of `self` taking precedence over the ones used to instantiate `self`.
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Object representing non-default ASN.1 subtype constraint(s)
sizeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Object representing non-default ASN.1 size constraint(s)
Possible values of `self` are never copied over thus `clone()` can
only create a new schema object.
Returns
-------
:
new instance of |ASN.1| type/value
Note
----
Due to the mutable nature of the |ASN.1| object, even if no arguments
are supplied, new |ASN.1| object will always be created as a shallow
copy of `self`.
"""
cloneValueFlag = kwargs.pop('cloneValueFlag', False)
@ -525,27 +551,46 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
return clone
def subtype(self, **kwargs):
"""Create a copy of a |ASN.1| type or object.
"""Create a specialization of |ASN.1| schema object.
Any parameters to the *subtype()* method will be added to the corresponding
properties of the |ASN.1| object.
The `subtype()` method accepts the same set arguments as |ASN.1|
class takes on instantiation except that all parameters
of the `subtype()` method are optional.
Parameters
----------
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
Object representing non-default ASN.1 tag(s)
With the exception of the arguments described below, the rest of
supplied arguments they are used to create a copy of `self` taking
precedence over the ones used to instantiate `self`.
The following arguments to `subtype()` create a ASN.1 subtype out of
|ASN.1| type.
Other Parameters
----------------
implicitTag: :py:class:`~pyasn1.type.tag.Tag`
Implicitly apply given ASN.1 tag object to `self`'s
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
new object's ASN.1 tag(s).
explicitTag: :py:class:`~pyasn1.type.tag.Tag`
Explicitly apply given ASN.1 tag object to `self`'s
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
new object's ASN.1 tag(s).
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Object representing non-default ASN.1 subtype constraint(s)
Add ASN.1 constraints object to one of the `self`'s, then
use the result as new object's ASN.1 constraints.
sizeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Object representing non-default ASN.1 size constraint(s)
Returns
-------
:
new instance of |ASN.1| type/value
Note
----
Due to the immutable nature of the |ASN.1| object, if no arguments
are supplied, no new |ASN.1| object will be created and `self` will
be returned instead.
"""
initializers = self.readOnly.copy()
@ -586,9 +631,6 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
self[k] = kwargs[k]
return self
def __len__(self):
return len(self._componentValues)
def clear(self):
self._componentValues = []

View File

@ -1,13 +1,14 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
from pyasn1.type import univ, tag
from pyasn1 import error
from pyasn1 import error
from pyasn1.type import tag
from pyasn1.type import univ
__all__ = ['NumericString', 'PrintableString', 'TeletexString', 'T61String', 'VideotexString',
'IA5String', 'GraphicString', 'VisibleString', 'ISO646String',
@ -18,16 +19,16 @@ noValue = univ.noValue
class AbstractCharacterString(univ.OctetString):
"""Creates |ASN.1| type or object.
"""Creates |ASN.1| schema or value object.
|ASN.1| objects are immutable and duck-type Python 2 :class:`unicode` or Python 3 :class:`str`.
When used in octet-stream context, |ASN.1| type assumes "|encoding|" encoding.
Parameters
----------
Keyword Args
------------
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
unicode object (Python 2) or string (Python 3), alternatively string
(Python 2) or bytes (Python 3) representing octet-stream of serialized
(Python 2) or bytes (Python 3) representing octet-stream of serialised
unicode string (note `encoding` parameter) or |ASN.1| class instance.
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
@ -43,14 +44,16 @@ class AbstractCharacterString(univ.OctetString):
Raises
------
: :py:class:`pyasn1.error.PyAsn1Error`
:py:class:`~pyasn1.error.PyAsn1Error`
On constraint violation or bad initializer.
"""
if sys.version_info[0] <= 2:
def __str__(self):
try:
# `str` is Py2 text representation
return self._value.encode(self.encoding)
except UnicodeEncodeError:
raise error.PyAsn1Error(
"Can't encode string '%s' with codec %s" % (self._value, self.encoding)
@ -85,6 +88,7 @@ class AbstractCharacterString(univ.OctetString):
else:
def __str__(self):
# `unicode` is Py3 text representation
return str(self._value)
def __bytes__(self):
@ -119,82 +123,25 @@ class AbstractCharacterString(univ.OctetString):
def asNumbers(self, padding=True):
return tuple(bytes(self))
#
# See OctetString.prettyPrint() for the explanation
#
def prettyOut(self, value):
return value
def prettyPrint(self, scope=0):
# first see if subclass has its own .prettyOut()
value = self.prettyOut(self._value)
if value is not self._value:
return value
return AbstractCharacterString.__str__(self)
def __reversed__(self):
return reversed(self._value)
def clone(self, value=noValue, **kwargs):
"""Creates a copy of a |ASN.1| type or object.
Any parameters to the *clone()* method will replace corresponding
properties of the |ASN.1| object.
Parameters
----------
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
unicode object (Python 2) or string (Python 3), alternatively string
(Python 2) or bytes (Python 3) representing octet-stream of serialized
unicode string (note `encoding` parameter) or |ASN.1| class instance.
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
Object representing non-default ASN.1 tag(s)
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Object representing non-default ASN.1 subtype constraint(s)
encoding: :py:class:`str`
Unicode codec ID to encode/decode :py:class:`unicode` (Python 2) or
:py:class:`str` (Python 3) the payload when |ASN.1| object is used
in octet-stream context.
Returns
-------
:
new instance of |ASN.1| type/value
"""
return univ.OctetString.clone(self, value, **kwargs)
def subtype(self, value=noValue, **kwargs):
"""Creates a copy of a |ASN.1| type or object.
Any parameters to the *subtype()* method will be added to the corresponding
properties of the |ASN.1| object.
Parameters
----------
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
unicode object (Python 2) or string (Python 3), alternatively string
(Python 2) or bytes (Python 3) representing octet-stream of serialized
unicode string (note `encoding` parameter) or |ASN.1| class instance.
implicitTag: :py:class:`~pyasn1.type.tag.Tag`
Implicitly apply given ASN.1 tag object to caller's
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
new object's ASN.1 tag(s).
explicitTag: :py:class:`~pyasn1.type.tag.Tag`
Explicitly apply given ASN.1 tag object to caller's
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
new object's ASN.1 tag(s).
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
Object representing non-default ASN.1 subtype constraint(s)
encoding: :py:class:`str`
Unicode codec ID to encode/decode :py:class:`unicode` (Python 2) or
:py:class:`str` (Python 3) the payload when |ASN.1| object is used
in octet-stream context.
Returns
-------
:
new instance of |ASN.1| type/value
"""
return univ.OctetString.subtype(self, value, **kwargs)
class NumericString(AbstractCharacterString):
__doc__ = AbstractCharacterString.__doc__

View File

@ -1,26 +1,23 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Original concept and code by Mike C. Fletcher.
#
import sys
from pyasn1.type import error
__all__ = ['SingleValueConstraint', 'ContainedSubtypeConstraint', 'ValueRangeConstraint',
'ValueSizeConstraint', 'PermittedAlphabetConstraint', 'InnerTypeConstraint',
'ConstraintsExclusion', 'ConstraintsIntersection', 'ConstraintsUnion']
__all__ = ['SingleValueConstraint', 'ContainedSubtypeConstraint',
'ValueRangeConstraint', 'ValueSizeConstraint',
'PermittedAlphabetConstraint', 'InnerTypeConstraint',
'ConstraintsExclusion', 'ConstraintsIntersection',
'ConstraintsUnion']
class AbstractConstraint(object):
"""Abstract base-class for constraint objects
Constraints should be stored in a simple sequence in the
namespace of their client Asn1Item sub-classes in cases
when ASN.1 constraint is define.
"""
def __init__(self, *values):
self._valueMap = set()
@ -40,10 +37,12 @@ class AbstractConstraint(object):
)
def __repr__(self):
return '%s(%s)' % (
self.__class__.__name__,
', '.join([repr(x) for x in self._values])
)
representation = '%s object at 0x%x' % (self.__class__.__name__, id(self))
if self._values:
representation += ' consts %s' % ', '.join([repr(x) for x in self._values])
return '<%s>' % representation
def __eq__(self, other):
return self is other and True or self._values == other
@ -96,9 +95,39 @@ class AbstractConstraint(object):
otherConstraint == self or
otherConstraint in self._valueMap)
class SingleValueConstraint(AbstractConstraint):
"""Value must be part of defined values constraint"""
class SingleValueConstraint(AbstractConstraint):
"""Create a SingleValueConstraint object.
The SingleValueConstraint satisfies any value that
is present in the set of permitted values.
The SingleValueConstraint object can be applied to
any ASN.1 type.
Parameters
----------
\*values: :class:`int`
Full set of values permitted by this constraint object.
Examples
--------
.. code-block:: python
class DivisorOfSix(Integer):
'''
ASN.1 specification:
Divisor-Of-6 ::= INTEGER (1 | 2 | 3 | 6)
'''
subtypeSpec = SingleValueConstraint(1, 2, 3, 6)
# this will succeed
divisor_of_six = DivisorOfSix(1)
# this will raise ValueConstraintError
divisor_of_six = DivisorOfSix(7)
"""
def _setValues(self, values):
self._values = values
self._set = set(values)
@ -109,16 +138,85 @@ class SingleValueConstraint(AbstractConstraint):
class ContainedSubtypeConstraint(AbstractConstraint):
"""Value must satisfy all of defined set of constraints"""
"""Create a ContainedSubtypeConstraint object.
The ContainedSubtypeConstraint satisfies any value that
is present in the set of permitted values and also
satisfies included constraints.
The ContainedSubtypeConstraint object can be applied to
any ASN.1 type.
Parameters
----------
\*values:
Full set of values and constraint objects permitted
by this constraint object.
Examples
--------
.. code-block:: python
class DivisorOfEighteen(Integer):
'''
ASN.1 specification:
Divisors-of-18 ::= INTEGER (INCLUDES Divisors-of-6 | 9 | 18)
'''
subtypeSpec = ContainedSubtypeConstraint(
SingleValueConstraint(1, 2, 3, 6), 9, 18
)
# this will succeed
divisor_of_eighteen = DivisorOfEighteen(9)
# this will raise ValueConstraintError
divisor_of_eighteen = DivisorOfEighteen(10)
"""
def _testValue(self, value, idx):
for c in self._values:
c(value, idx)
for constraint in self._values:
if isinstance(constraint, AbstractConstraint):
constraint(value, idx)
elif value not in self._set:
raise error.ValueConstraintError(value)
class ValueRangeConstraint(AbstractConstraint):
"""Value must be within start and stop values (inclusive)"""
"""Create a ValueRangeConstraint object.
The ValueRangeConstraint satisfies any value that
falls in the range of permitted values.
The ValueRangeConstraint object can only be applied
to :class:`~pyasn1.type.univ.Integer` and
:class:`~pyasn1.type.univ.Real` types.
Parameters
----------
start: :class:`int`
Minimum permitted value in the range (inclusive)
end: :class:`int`
Maximum permitted value in the range (inclusive)
Examples
--------
.. code-block:: python
class TeenAgeYears(Integer):
'''
ASN.1 specification:
TeenAgeYears ::= INTEGER (13 .. 19)
'''
subtypeSpec = ValueRangeConstraint(13, 19)
# this will succeed
teen_year = TeenAgeYears(18)
# this will raise ValueConstraintError
teen_year = TeenAgeYears(20)
"""
def _testValue(self, value, idx):
if value < self.start or value > self.stop:
raise error.ValueConstraintError(value)
@ -140,8 +238,59 @@ class ValueRangeConstraint(AbstractConstraint):
class ValueSizeConstraint(ValueRangeConstraint):
"""len(value) must be within start and stop values (inclusive)"""
"""Create a ValueSizeConstraint object.
The ValueSizeConstraint satisfies any value for
as long as its size falls within the range of
permitted sizes.
The ValueSizeConstraint object can be applied
to :class:`~pyasn1.type.univ.BitString`,
:class:`~pyasn1.type.univ.OctetString` (including
all :ref:`character ASN.1 types <type.char>`),
:class:`~pyasn1.type.univ.SequenceOf`
and :class:`~pyasn1.type.univ.SetOf` types.
Parameters
----------
minimum: :class:`int`
Minimum permitted size of the value (inclusive)
maximum: :class:`int`
Maximum permitted size of the value (inclusive)
Examples
--------
.. code-block:: python
class BaseballTeamRoster(SetOf):
'''
ASN.1 specification:
BaseballTeamRoster ::= SET SIZE (1..25) OF PlayerNames
'''
componentType = PlayerNames()
subtypeSpec = ValueSizeConstraint(1, 25)
# this will succeed
team = BaseballTeamRoster()
team.extend(['Jan', 'Matej'])
encode(team)
# this will raise ValueConstraintError
team = BaseballTeamRoster()
team.extend(['Jan'] * 26)
encode(team)
Note
----
Whenever ValueSizeConstraint is applied to mutable types
(e.g. :class:`~pyasn1.type.univ.SequenceOf`,
:class:`~pyasn1.type.univ.SetOf`), constraint
validation only happens at the serialisation phase rather
than schema instantiation phase (as it is with immutable
types).
"""
def _testValue(self, value, idx):
valueSize = len(value)
if valueSize < self.start or valueSize > self.stop:
@ -149,6 +298,40 @@ class ValueSizeConstraint(ValueRangeConstraint):
class PermittedAlphabetConstraint(SingleValueConstraint):
"""Create a PermittedAlphabetConstraint object.
The PermittedAlphabetConstraint satisfies any character
string for as long as all its characters are present in
the set of permitted characters.
The PermittedAlphabetConstraint object can only be applied
to the :ref:`character ASN.1 types <type.char>` such as
:class:`~pyasn1.type.char.IA5String`.
Parameters
----------
\*alphabet: :class:`str`
Full set of characters permitted by this constraint object.
Examples
--------
.. code-block:: python
class BooleanValue(IA5String):
'''
ASN.1 specification:
BooleanValue ::= IA5String (FROM ('T' | 'F'))
'''
subtypeSpec = PermittedAlphabetConstraint('T', 'F')
# this will succeed
truth = BooleanValue('T')
truth = BooleanValue('TF')
# this will raise ValueConstraintError
garbage = BooleanValue('TAF')
"""
def _setValues(self, values):
self._values = values
self._set = set(values)
@ -160,7 +343,7 @@ class PermittedAlphabetConstraint(SingleValueConstraint):
# This is a bit kludgy, meaning two op modes within a single constraint
class InnerTypeConstraint(AbstractConstraint):
"""Value must satisfy type and presense constraints"""
"""Value must satisfy the type and presence constraints"""
def _testValue(self, value, idx):
if self.__singleTypeConstraint:
@ -184,11 +367,50 @@ class InnerTypeConstraint(AbstractConstraint):
AbstractConstraint._setValues(self, values)
# Boolean ops on constraints
# Logic operations on constraints
class ConstraintsExclusion(AbstractConstraint):
"""Value must not fit the single constraint"""
"""Create a ConstraintsExclusion logic operator object.
The ConstraintsExclusion logic operator succeeds when the
value does *not* satisfy the operand constraint.
The ConstraintsExclusion object can be applied to
any constraint and logic operator object.
Parameters
----------
constraint:
Constraint or logic operator object.
Examples
--------
.. code-block:: python
class Lipogramme(IA5STRING):
'''
ASN.1 specification:
Lipogramme ::=
IA5String (FROM (ALL EXCEPT ("e"|"E")))
'''
subtypeSpec = ConstraintsExclusion(
PermittedAlphabetConstraint('e', 'E')
)
# this will succeed
lipogramme = Lipogramme('A work of fiction?')
# this will raise ValueConstraintError
lipogramme = Lipogramme('Eel')
Warning
-------
The above example involving PermittedAlphabetConstraint might
not work due to the way how PermittedAlphabetConstraint works.
The other constraints might work with ConstraintsExclusion
though.
"""
def _testValue(self, value, idx):
try:
self._values[0](value, idx)
@ -200,11 +422,11 @@ class ConstraintsExclusion(AbstractConstraint):
def _setValues(self, values):
if len(values) != 1:
raise error.PyAsn1Error('Single constraint expected')
AbstractConstraint._setValues(self, values)
class AbstractConstraintSet(AbstractConstraint):
"""Value must not satisfy the single constraint"""
def __getitem__(self, idx):
return self._values[idx]
@ -232,16 +454,88 @@ class AbstractConstraintSet(AbstractConstraint):
class ConstraintsIntersection(AbstractConstraintSet):
"""Value must satisfy all constraints"""
"""Create a ConstraintsIntersection logic operator object.
The ConstraintsIntersection logic operator only succeeds
if *all* its operands succeed.
The ConstraintsIntersection object can be applied to
any constraint and logic operator objects.
The ConstraintsIntersection object duck-types the immutable
container object like Python :py:class:`tuple`.
Parameters
----------
\*constraints:
Constraint or logic operator objects.
Examples
--------
.. code-block:: python
class CapitalAndSmall(IA5String):
'''
ASN.1 specification:
CapitalAndSmall ::=
IA5String (FROM ("A".."Z"|"a".."z"))
'''
subtypeSpec = ConstraintsIntersection(
PermittedAlphabetConstraint('A', 'Z'),
PermittedAlphabetConstraint('a', 'z')
)
# this will succeed
capital_and_small = CapitalAndSmall('Hello')
# this will raise ValueConstraintError
capital_and_small = CapitalAndSmall('hello')
"""
def _testValue(self, value, idx):
for constraint in self._values:
constraint(value, idx)
class ConstraintsUnion(AbstractConstraintSet):
"""Value must satisfy at least one constraint"""
"""Create a ConstraintsUnion logic operator object.
The ConstraintsUnion logic operator only succeeds if
*at least a single* operand succeeds.
The ConstraintsUnion object can be applied to
any constraint and logic operator objects.
The ConstraintsUnion object duck-types the immutable
container object like Python :py:class:`tuple`.
Parameters
----------
\*constraints:
Constraint or logic operator objects.
Examples
--------
.. code-block:: python
class CapitalOrSmall(IA5String):
'''
ASN.1 specification:
CapitalOrSmall ::=
IA5String (FROM ("A".."Z") | FROM ("a".."z"))
'''
subtypeSpec = ConstraintsIntersection(
PermittedAlphabetConstraint('A', 'Z'),
PermittedAlphabetConstraint('a', 'z')
)
# this will succeed
capital_or_small = CapitalAndSmall('Hello')
# this will raise ValueConstraintError
capital_or_small = CapitalOrSmall('hello!')
"""
def _testValue(self, value, idx):
for constraint in self._values:
try:
@ -250,9 +544,13 @@ class ConstraintsUnion(AbstractConstraintSet):
pass
else:
return
raise error.ValueConstraintError(
'all of %s failed for \"%s\"' % (self._values, value)
'all of %s failed for "%s"' % (self._values, value)
)
# XXX
# TODO:
# refactor InnerTypeConstraint
# add tests for type check
# implement other constraint types
# make constraint validation easy to skip

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1.error import PyAsn1Error

View File

@ -1,14 +1,23 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import sys
from pyasn1.type import tag, tagmap
from pyasn1 import error
__all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType', 'NamedTypes']
from pyasn1 import error
from pyasn1.type import tag
from pyasn1.type import tagmap
__all__ = ['NamedType', 'OptionalNamedType', 'DefaultedNamedType',
'NamedTypes']
try:
any
except NameError:
any = lambda x: bool(filter(bool, x))
class NamedType(object):
@ -30,13 +39,19 @@ class NamedType(object):
isOptional = False
isDefaulted = False
def __init__(self, name, asn1Object):
def __init__(self, name, asn1Object, openType=None):
self.__name = name
self.__type = asn1Object
self.__nameAndType = name, asn1Object
self.__openType = openType
def __repr__(self):
return '%s(%r, %r)' % (self.__class__.__name__, self.__name, self.__type)
representation = '%s=%r' % (self.name, self.asn1Object)
if self.openType:
representation += ' openType: %r' % self.openType
return '<%s object at 0x%x type %s>' % (self.__class__.__name__, id(self), representation)
def __eq__(self, other):
return self.__nameAndType == other
@ -68,11 +83,15 @@ class NamedType(object):
@property
def name(self):
return self.__name
@property
def asn1Object(self):
return self.__type
@property
def openType(self):
return self.__openType
# Backward compatibility
def getName(self):
@ -105,6 +124,31 @@ class NamedTypes(object):
Parameters
----------
*namedTypes: :class:`~pyasn1.type.namedtype.NamedType`
Examples
--------
.. code-block:: python
class Description(Sequence):
'''
ASN.1 specification:
Description ::= SEQUENCE {
surname IA5String,
first-name IA5String OPTIONAL,
age INTEGER DEFAULT 40
}
'''
componentType = NamedTypes(
NamedType('surname', IA5String()),
OptionalNamedType('first-name', IA5String()),
DefaultedNamedType('age', Integer(40))
)
descr = Description()
descr['surname'] = 'Smith'
descr['first-name'] = 'John'
"""
def __init__(self, *namedTypes, **kwargs):
self.__namedTypes = namedTypes
@ -115,8 +159,11 @@ class NamedTypes(object):
self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {}
self.__uniqueTagMap = self.__computeTagMaps(unique=True)
self.__nonUniqueTagMap = self.__computeTagMaps(unique=False)
self.__hasOptionalOrDefault = bool([True for namedType in self.__namedTypes
if namedType.isDefaulted or namedType.isOptional])
self.__hasOptionalOrDefault = any([True for namedType in self.__namedTypes
if namedType.isDefaulted or namedType.isOptional])
self.__hasOpenTypes = any([True for namedType in self.__namedTypes
if namedType.openType])
self.__requiredComponents = frozenset(
[idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted]
)
@ -125,9 +172,8 @@ class NamedTypes(object):
self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes])
def __repr__(self):
return '%s(%s)' % (
self.__class__.__name__, ', '.join([repr(x) for x in self.__namedTypes])
)
representation = ', '.join(['%r' % x for x in self.__namedTypes])
return '<%s object at 0x%x types %s>' % (self.__class__.__name__, id(self), representation)
def __eq__(self, other):
return self.__namedTypes == other
@ -331,7 +377,7 @@ class NamedTypes(object):
def getTagMapNearPosition(self, idx):
"""Return ASN.1 types that are allowed at or past given field position.
Some ASN.1 serialization allow for skipping optional and defaulted fields.
Some ASN.1 serialisation allow for skipping optional and defaulted fields.
Some constructed ASN.1 types allow reordering of the fields. When recovering
such objects it may be important to know which types can possibly be
present at any given position in the field sets.
@ -360,7 +406,7 @@ class NamedTypes(object):
def getPositionNearType(self, tagSet, idx):
"""Return the closest field position where given ASN.1 type is allowed.
Some ASN.1 serialization allow for skipping optional and defaulted fields.
Some ASN.1 serialisation allow for skipping optional and defaulted fields.
Some constructed ASN.1 types allow reordering of the fields. When recovering
such objects it may be important to know at which field position, in field set,
given *tagSet* is allowed at or past *idx* position.
@ -410,7 +456,7 @@ class NamedTypes(object):
def minTagSet(self):
"""Return the minimal TagSet among ASN.1 type in callee *NamedTypes*.
Some ASN.1 types/serialization protocols require ASN.1 types to be
Some ASN.1 types/serialisation protocols require ASN.1 types to be
arranged based on their numerical tag value. The *minTagSet* property
returns that.
@ -452,7 +498,6 @@ class NamedTypes(object):
Example
-------
.. code-block:: python
OuterType ::= CHOICE {
@ -477,7 +522,6 @@ class NamedTypes(object):
Example
-------
.. code-block:: python
OuterType ::= CHOICE {
@ -502,9 +546,13 @@ class NamedTypes(object):
def hasOptionalOrDefault(self):
return self.__hasOptionalOrDefault
@property
def hasOpenTypes(self):
return self.__hasOpenTypes
@property
def namedTypes(self):
return iter(self.__namedTypes)
return tuple(self.__namedTypes)
@property
def requiredComponents(self):

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# ASN.1 named integers
#
@ -23,26 +23,34 @@ class NamedValues(object):
Parameters
----------
\*args: variable number of two-element :py:class:`tuple`
\*args: variable number of two-element :py:class:`tuple`
\*\*kwargs: keyword parameters of:
name: :py:class:`str`
Value name
Value label
value: :py:class:`int`
A numerical value
Numeric value
Keyword Args
------------
name: :py:class:`str`
Value label
value: :py:class:`int`
Numeric value
Examples
--------
>>> nv = namedval.NamedValues('a', 'b', ('c', 0), d=1)
>>> nv
>>> {'c': 0, 'd': 1, 'a': 2, 'b': 3}
>>> nv[0]
'c'
>>> nv['a']
2
.. code-block:: pycon
>>> nv = NamedValues('a', 'b', ('c', 0), d=1)
>>> nv
>>> {'c': 0, 'd': 1, 'a': 2, 'b': 3}
>>> nv[0]
'c'
>>> nv['a']
2
"""
def __init__(self, *args, **kwargs):
self.__names = {}
@ -96,10 +104,12 @@ class NamedValues(object):
number += 1
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, tuple(self.items()))
representation = ', '.join(['%s=%d' % x for x in self.items()])
def __str__(self):
return str(self.items())
if len(representation) > 64:
representation = representation[:32] + '...' + representation[-32:]
return '<%s object 0x%x enums %s>' % (self.__class__.__name__, id(self), representation)
def __eq__(self, other):
return dict(self) == other

View File

@ -0,0 +1,75 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
__all__ = ['OpenType']
class OpenType(object):
"""Create ASN.1 type map indexed by a value
The *DefinedBy* object models the ASN.1 *DEFINED BY* clause which maps
values to ASN.1 types in the context of the ASN.1 SEQUENCE/SET type.
OpenType objects are duck-type a read-only Python :class:`dict` objects,
however the passed `typeMap` is stored by reference.
Parameters
----------
name: :py:class:`str`
Field name
typeMap: :py:class:`dict`
A map of value->ASN.1 type. It's stored by reference and can be
mutated later to register new mappings.
Examples
--------
.. code-block:: python
openType = OpenType(
'id',
{1: Integer(),
2: OctetString()}
)
Sequence(
componentType=NamedTypes(
NamedType('id', Integer()),
NamedType('blob', Any(), openType=openType)
)
)
"""
def __init__(self, name, typeMap=None):
self.__name = name
if typeMap is None:
self.__typeMap = {}
else:
self.__typeMap = typeMap
@property
def name(self):
return self.__name
# Python dict protocol
def values(self):
return self.__typeMap.values()
def keys(self):
return self.__typeMap.keys()
def items(self):
return self.__typeMap.items()
def __contains__(self, key):
return key in self.__typeMap
def __getitem__(self, key):
return self.__typeMap[key]
def __iter__(self):
return iter(self.__typeMap)

View File

@ -1,15 +1,15 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1 import error
__all__ = ['tagClassUniversal', 'tagClassApplication', 'tagClassContext',
'tagClassPrivate', 'tagFormatSimple', 'tagFormatConstructed',
'tagCategoryImplicit', 'tagCategoryExplicit', 'tagCategoryUntagged',
'Tag', 'TagSet']
'tagCategoryImplicit', 'tagCategoryExplicit',
'tagCategoryUntagged', 'Tag', 'TagSet']
#: Identifier for ASN.1 class UNIVERSAL
tagClassUniversal = 0x00
@ -63,13 +63,9 @@ class Tag(object):
self.__tagClassId = tagClass, tagId
self.__hash = hash(self.__tagClassId)
def __str__(self):
return '[%s:%s:%s]' % (self.__tagClass, self.__tagFormat, self.__tagId)
def __repr__(self):
return '%s(tagClass=%s, tagFormat=%s, tagId=%s)' % (
(self.__class__.__name__, self.__tagClass, self.__tagFormat, self.__tagId)
)
representation = '[%s:%s:%s]' % (self.__tagClass, self.__tagFormat, self.__tagId)
return '<%s object at 0x%x tag %s>' % (self.__class__.__name__, id(self), representation)
def __eq__(self, other):
return self.__tagClassId == other
@ -168,6 +164,23 @@ class TagSet(object):
*superTags: :class:`~pyasn1.type.tag.Tag`
Additional *Tag* objects taking part in subtyping.
Examples
--------
.. code-block:: python
class OrderNumber(NumericString):
'''
ASN.1 specification
Order-number ::=
[APPLICATION 5] IMPLICIT NumericString
'''
tagSet = NumericString.tagSet.tagImplicitly(
Tag(tagClassApplication, tagFormatSimple, 5)
)
orderNumber = OrderNumber('1234')
"""
def __init__(self, baseTag=(), *superTags):
self.__baseTag = baseTag
@ -178,13 +191,15 @@ class TagSet(object):
self.__lenOfSuperTags = len(superTags)
self.__hash = hash(self.__superTagsClassId)
def __str__(self):
return self.__superTags and '+'.join([str(x) for x in self.__superTags]) or '[untagged]'
def __repr__(self):
return '%s(%s)' % (
self.__class__.__name__, '(), ' + ', '.join([repr(x) for x in self.__superTags])
)
representation = '-'.join(['%s:%s:%s' % (x.tagClass, x.tagFormat, x.tagId)
for x in self.__superTags])
if representation:
representation = 'tags ' + representation
else:
representation = 'untagged'
return '<%s object at 0x%x %s>' % (self.__class__.__name__, id(self), representation)
def __add__(self, superTag):
return self.__class__(self.__baseTag, *self.__superTags + (superTag,))

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
from pyasn1 import error
@ -56,24 +56,18 @@ class TagMap(object):
return iter(self.__presentTypes)
def __repr__(self):
s = self.__class__.__name__ + '('
if self.__presentTypes:
s += 'presentTypes=%r, ' % (self.__presentTypes,)
if self.__skipTypes:
s += 'skipTypes=%r, ' % (self.__skipTypes,)
if self.__defaultType is not None:
s += 'defaultType=%r' % (self.__defaultType,)
return s + ')'
representation = '%s object at 0x%x' % (self.__class__.__name__, id(self))
def __str__(self):
s = self.__class__.__name__ + ': '
if self.__presentTypes:
s += 'presentTypes: %s, ' % ', '.join([x.prettyPrintType() for x in self.__presentTypes.values()])
representation += ' present %s' % repr(self.__presentTypes)
if self.__skipTypes:
s += 'skipTypes: %s, ' % ', '.join([x.prettyPrintType() for x in self.__skipTypes.values()])
representation += ' skip %s' % repr(self.__skipTypes)
if self.__defaultType is not None:
s += 'defaultType: %s, ' % self.__defaultType.prettyPrintType()
return s
representation += ' default %s' % repr(self.__defaultType)
return '<%s>' % representation
@property
def presentTypes(self):

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,17 @@
#
# This file is part of pyasn1 software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import datetime
from pyasn1.type import univ, char, tag
from pyasn1.compat import string, dateandtime
from pyasn1 import error
from pyasn1.compat import dateandtime
from pyasn1.compat import string
from pyasn1.type import char
from pyasn1.type import tag
from pyasn1.type import univ
__all__ = ['ObjectDescriptor', 'GeneralizedTime', 'UTCTime']
@ -61,7 +65,7 @@ class TimeMixIn(object):
Returns
-------
:
new instance of :py:class:`datetime.datetime` object
new instance of :py:class:`datetime.datetime` object
"""
text = str(self)
if text.endswith('Z'):
@ -100,7 +104,7 @@ class TimeMixIn(object):
text, _, ms = string.partition(text, ',')
try:
ms = int(ms) * 10000
ms = int(ms) * 1000
except ValueError:
raise error.PyAsn1Error('bad sub-second time specification %s' % self)
@ -127,10 +131,10 @@ class TimeMixIn(object):
Parameters
----------
dt : :py:class:`datetime.datetime` object
The `datetime.datetime` object to initialize the |ASN.1| object from
dt: :py:class:`datetime.datetime` object
The `datetime.datetime` object to initialize the |ASN.1| object
from
Returns
-------
:
@ -138,7 +142,7 @@ class TimeMixIn(object):
"""
text = dt.strftime(cls._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S')
if cls._hasSubsecond:
text += '.%d' % (dt.microsecond // 10000)
text += '.%d' % (dt.microsecond // 1000)
if dt.utcoffset():
seconds = dt.utcoffset().seconds

View File

@ -1,2 +1,2 @@
# http://www.python.org/dev/peps/pep-0396/
__version__ = '0.1.4'
__version__ = '0.2.2'

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
import base64
import sys

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# SNMPv1 message syntax
#
@ -12,7 +12,10 @@
# Sample captures from:
# http://wiki.wireshark.org/SampleCaptures/
#
from pyasn1.type import univ, namedtype, tag, constraint
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import tag
from pyasn1.type import univ
class ObjectName(univ.ObjectIdentifier):

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# SNMPv1 message syntax
#
@ -12,7 +12,11 @@
# Sample captures from:
# http://wiki.wireshark.org/SampleCaptures/
#
from pyasn1.type import univ, namedtype, namedval, tag
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1_modules import rfc1155

View File

@ -1,15 +1,17 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# SNMPv2c message syntax
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc1901.txt
#
from pyasn1.type import univ, namedtype, namedval
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import univ
class Message(univ.Sequence):

View File

@ -1,15 +1,18 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# SNMPv2c message syntax
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc1902.txt
#
from pyasn1.type import univ, namedtype, tag, constraint
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import tag
from pyasn1.type import univ
class Integer(univ.Integer):

View File

@ -1,15 +1,20 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# SNMPv2c PDU syntax
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc1905.txt
#
from pyasn1.type import univ, namedtype, namedval, tag, constraint
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1_modules import rfc1902
max_bindings = rfc1902.Integer(2147483647)

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# LDAP message syntax
#
@ -12,7 +12,11 @@
# Sample captures from:
# http://wiki.wireshark.org/SampleCaptures/
#
from pyasn1.type import tag, namedtype, namedval, univ, constraint
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
maxInt = univ.Integer(2147483647)

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# PKCS#10 syntax
#

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# PKCS#7 message syntax
#
@ -25,7 +25,8 @@ class Attribute(univ.Sequence):
class AttributeValueAssertion(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('attributeType', AttributeType()),
namedtype.NamedType('attributeValue', AttributeValue())
namedtype.NamedType('attributeValue', AttributeValue(),
openType=opentype.OpenType('type', certificateAttributesMap))
)
@ -50,12 +51,19 @@ class EncryptedContent(univ.OctetString):
pass
contentTypeMap = {}
class EncryptedContentInfo(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('contentType', ContentType()),
namedtype.NamedType('contentEncryptionAlgorithm', ContentEncryptionAlgorithmIdentifier()),
namedtype.OptionalNamedType('encryptedContent', EncryptedContent().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)))
namedtype.OptionalNamedType(
'encryptedContent', EncryptedContent().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)
),
openType=opentype.OpenType('contentType', contentTypeMap)
)
)
@ -85,8 +93,11 @@ class Digest(univ.OctetString):
class ContentInfo(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('contentType', ContentType()),
namedtype.OptionalNamedType('content', univ.Any().subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)))
namedtype.OptionalNamedType(
'content',
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)),
openType=opentype.OpenType('contentType', contentTypeMap)
)
)
@ -270,3 +281,14 @@ class SignedData(univ.Sequence):
class Data(univ.OctetString):
pass
_contentTypeMapUpdate = {
data: Data(),
signedData: SignedData(),
envelopedData: EnvelopedData(),
signedAndEnvelopedData: SignedAndEnvelopedData(),
digestedData: DigestedData(),
encryptedData: EncryptedData()
}
contentTypeMap.update(_contentTypeMapUpdate)

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# PKCS#1 syntax
#
@ -11,7 +11,10 @@
#
# Sample captures could be obtained with "openssl genrsa" command
#
from pyasn1.type import tag, namedtype, univ
from pyasn1.type import namedtype
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1_modules.rfc2459 import AlgorithmIdentifier
pkcs_1 = univ.ObjectIdentifier('1.2.840.113549.1.1')

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# X.509 message syntax
#
@ -13,7 +13,14 @@
# Sample captures from:
# http://wiki.wireshark.org/SampleCaptures/
#
from pyasn1.type import tag, namedtype, namedval, univ, constraint, char, useful
from pyasn1.type import char
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import opentype
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
MAX = float('inf')
@ -84,26 +91,6 @@ id_ad_ocsp = univ.ObjectIdentifier('1.3.6.1.5.5.7.48.1')
id_ad_caIssuers = univ.ObjectIdentifier('1.3.6.1.5.5.7.48.2')
class AttributeValue(univ.Any):
pass
class AttributeType(univ.ObjectIdentifier):
pass
class AttributeTypeAndValue(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('value', AttributeValue())
)
class Attribute(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('vals', univ.SetOf(componentType=AttributeValue()))
)
id_at = univ.ObjectIdentifier('2.5.4')
@ -277,19 +264,6 @@ class DSAPrivateKey(univ.Sequence):
# ----
class RelativeDistinguishedName(univ.SetOf):
componentType = AttributeTypeAndValue()
class RDNSequence(univ.SequenceOf):
componentType = RelativeDistinguishedName()
class Name(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('', RDNSequence())
)
class DirectoryString(univ.Choice):
componentType = namedtype.NamedTypes(
@ -316,111 +290,6 @@ class AlgorithmIdentifier(univ.Sequence):
)
class Extension(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('extnID', univ.ObjectIdentifier()),
namedtype.DefaultedNamedType('critical', univ.Boolean('False')),
namedtype.NamedType('extnValue', univ.Any())
)
class Extensions(univ.SequenceOf):
componentType = Extension()
sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX)
class SubjectPublicKeyInfo(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('algorithm', AlgorithmIdentifier()),
namedtype.NamedType('subjectPublicKey', univ.BitString())
)
class UniqueIdentifier(univ.BitString):
pass
class Time(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('utcTime', useful.UTCTime()),
namedtype.NamedType('generalTime', useful.GeneralizedTime())
)
class Validity(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('notBefore', Time()),
namedtype.NamedType('notAfter', Time())
)
class CertificateSerialNumber(univ.Integer):
pass
class Version(univ.Integer):
namedValues = namedval.NamedValues(
('v1', 0), ('v2', 1), ('v3', 2)
)
class TBSCertificate(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.DefaultedNamedType('version', Version('v1').subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
namedtype.NamedType('serialNumber', CertificateSerialNumber()),
namedtype.NamedType('signature', AlgorithmIdentifier()),
namedtype.NamedType('issuer', Name()),
namedtype.NamedType('validity', Validity()),
namedtype.NamedType('subject', Name()),
namedtype.NamedType('subjectPublicKeyInfo', SubjectPublicKeyInfo()),
namedtype.OptionalNamedType('issuerUniqueID', UniqueIdentifier().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.OptionalNamedType('subjectUniqueID', UniqueIdentifier().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
namedtype.OptionalNamedType('extensions', Extensions().subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)))
)
class Certificate(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('tbsCertificate', TBSCertificate()),
namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()),
namedtype.NamedType('signatureValue', univ.BitString())
)
# CRL structures
class RevokedCertificate(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('userCertificate', CertificateSerialNumber()),
namedtype.NamedType('revocationDate', Time()),
namedtype.OptionalNamedType('crlEntryExtensions', Extensions())
)
class TBSCertList(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('version', Version()),
namedtype.NamedType('signature', AlgorithmIdentifier()),
namedtype.NamedType('issuer', Name()),
namedtype.NamedType('thisUpdate', Time()),
namedtype.OptionalNamedType('nextUpdate', Time()),
namedtype.OptionalNamedType('revokedCertificates', univ.SequenceOf(componentType=RevokedCertificate())),
namedtype.OptionalNamedType('crlExtensions', Extensions().subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)))
)
class CertificateList(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('tbsCertList', TBSCertList()),
namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()),
namedtype.NamedType('signature', univ.BitString())
)
# Algorithm OIDs and parameter structures
@ -972,11 +841,6 @@ class BasicConstraints(univ.Sequence):
id_ce_subjectDirectoryAttributes = univ.ObjectIdentifier('2.5.29.9')
class SubjectDirectoryAttributes(univ.SequenceOf):
componentType = Attribute()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
class EDIPartyName(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('nameAssigner', DirectoryString().subtype(
@ -986,76 +850,10 @@ class EDIPartyName(univ.Sequence):
)
class AnotherName(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type-id', univ.ObjectIdentifier()),
namedtype.NamedType('value',
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))
)
class GeneralName(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('otherName',
AnotherName().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
namedtype.NamedType('rfc822Name',
char.IA5String().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.NamedType('dNSName',
char.IA5String().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
namedtype.NamedType('x400Address',
ORAddress().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
namedtype.NamedType('directoryName',
Name().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))),
namedtype.NamedType('ediPartyName',
EDIPartyName().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))),
namedtype.NamedType('uniformResourceIdentifier',
char.IA5String().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 6))),
namedtype.NamedType('iPAddress', univ.OctetString().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))),
namedtype.NamedType('registeredID', univ.ObjectIdentifier().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8)))
)
class GeneralNames(univ.SequenceOf):
componentType = GeneralName()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
class AccessDescription(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('accessMethod', univ.ObjectIdentifier()),
namedtype.NamedType('accessLocation', GeneralName())
)
class AuthorityInfoAccessSyntax(univ.SequenceOf):
componentType = AccessDescription()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
id_ce_deltaCRLIndicator = univ.ObjectIdentifier('2.5.29.27')
class DistributionPointName(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('fullName', GeneralNames().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.NamedType('nameRelativeToCRLIssuer', RelativeDistinguishedName().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
)
class DistributionPoint(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('distributionPoint', DistributionPointName().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.OptionalNamedType('reasons', ReasonFlags().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.OptionalNamedType('cRLIssuer', GeneralNames().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2)))
)
class BaseDistance(univ.Integer):
subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueRangeConstraint(0, MAX)
@ -1064,56 +862,14 @@ class BaseDistance(univ.Integer):
id_ce_cRLDistributionPoints = univ.ObjectIdentifier('2.5.29.31')
class CRLDistPointsSyntax(univ.SequenceOf):
componentType = DistributionPoint()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
id_ce_issuingDistributionPoint = univ.ObjectIdentifier('2.5.29.28')
class IssuingDistributionPoint(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('distributionPoint', DistributionPointName().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.NamedType('onlyContainsUserCerts', univ.Boolean(False).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.NamedType('onlyContainsCACerts', univ.Boolean(False).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
namedtype.OptionalNamedType('onlySomeReasons', ReasonFlags().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
namedtype.NamedType('indirectCRL', univ.Boolean(False).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)))
)
class GeneralSubtree(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('base', GeneralName()),
namedtype.DefaultedNamedType('minimum', BaseDistance(0).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.OptionalNamedType('maximum', BaseDistance().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
)
class GeneralSubtrees(univ.SequenceOf):
componentType = GeneralSubtree()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
id_ce_nameConstraints = univ.ObjectIdentifier('2.5.29.30')
class NameConstraints(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('permittedSubtrees', GeneralSubtrees().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.OptionalNamedType('excludedSubtrees', GeneralSubtrees().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
)
class DisplayText(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('visibleString',
@ -1232,6 +988,110 @@ class SubjectKeyIdentifier(KeyIdentifier):
pass
id_ce_certificateIssuer = univ.ObjectIdentifier('2.5.29.29')
id_ce_subjectAltName = univ.ObjectIdentifier('2.5.29.17')
id_ce_issuerAltName = univ.ObjectIdentifier('2.5.29.18')
class AttributeValue(univ.Any):
pass
class AttributeType(univ.ObjectIdentifier):
pass
certificateAttributesMap = {}
class AttributeTypeAndValue(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('value', AttributeValue(),
openType=opentype.OpenType('type', certificateAttributesMap))
)
class Attribute(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('vals', univ.SetOf(componentType=AttributeValue()))
)
class SubjectDirectoryAttributes(univ.SequenceOf):
componentType = Attribute()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
class RelativeDistinguishedName(univ.SetOf):
componentType = AttributeTypeAndValue()
class RDNSequence(univ.SequenceOf):
componentType = RelativeDistinguishedName()
class Name(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('', RDNSequence())
)
class CertificateSerialNumber(univ.Integer):
pass
class AnotherName(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type-id', univ.ObjectIdentifier()),
namedtype.NamedType('value',
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))
)
class GeneralName(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('otherName',
AnotherName().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
namedtype.NamedType('rfc822Name',
char.IA5String().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.NamedType('dNSName',
char.IA5String().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
namedtype.NamedType('x400Address',
ORAddress().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
namedtype.NamedType('directoryName',
Name().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))),
namedtype.NamedType('ediPartyName',
EDIPartyName().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5))),
namedtype.NamedType('uniformResourceIdentifier',
char.IA5String().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 6))),
namedtype.NamedType('iPAddress', univ.OctetString().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 7))),
namedtype.NamedType('registeredID', univ.ObjectIdentifier().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 8)))
)
class GeneralNames(univ.SequenceOf):
componentType = GeneralName()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
class AccessDescription(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('accessMethod', univ.ObjectIdentifier()),
namedtype.NamedType('accessLocation', GeneralName())
)
class AuthorityInfoAccessSyntax(univ.SequenceOf):
componentType = AccessDescription()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
class AuthorityKeyIdentifier(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('keyIdentifier', KeyIdentifier().subtype(
@ -1243,30 +1103,189 @@ class AuthorityKeyIdentifier(univ.Sequence):
)
id_ce_certificateIssuer = univ.ObjectIdentifier('2.5.29.29')
class DistributionPointName(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('fullName', GeneralNames().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.NamedType('nameRelativeToCRLIssuer', RelativeDistinguishedName().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
)
class DistributionPoint(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('distributionPoint', DistributionPointName().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.OptionalNamedType('reasons', ReasonFlags().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.OptionalNamedType('cRLIssuer', GeneralNames().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2)))
)
class CRLDistPointsSyntax(univ.SequenceOf):
componentType = DistributionPoint()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
class IssuingDistributionPoint(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('distributionPoint', DistributionPointName().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.NamedType('onlyContainsUserCerts', univ.Boolean(False).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.NamedType('onlyContainsCACerts', univ.Boolean(False).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
namedtype.OptionalNamedType('onlySomeReasons', ReasonFlags().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
namedtype.NamedType('indirectCRL', univ.Boolean(False).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4)))
)
class GeneralSubtree(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('base', GeneralName()),
namedtype.DefaultedNamedType('minimum', BaseDistance(0).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.OptionalNamedType('maximum', BaseDistance().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
)
class GeneralSubtrees(univ.SequenceOf):
componentType = GeneralSubtree()
subtypeSpec = univ.SequenceOf.subtypeSpec + constraint.ValueSizeConstraint(1, MAX)
class NameConstraints(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('permittedSubtrees', GeneralSubtrees().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.OptionalNamedType('excludedSubtrees', GeneralSubtrees().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
)
class CertificateIssuer(GeneralNames):
pass
id_ce_subjectAltName = univ.ObjectIdentifier('2.5.29.17')
class SubjectAltName(GeneralNames):
pass
id_ce_issuerAltName = univ.ObjectIdentifier('2.5.29.18')
class IssuerAltName(GeneralNames):
pass
certificateExtensionsMap = {}
class Extension(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('extnID', univ.ObjectIdentifier()),
namedtype.DefaultedNamedType('critical', univ.Boolean('False')),
namedtype.NamedType('extnValue', univ.OctetString(),
openType=opentype.OpenType('extnID', certificateExtensionsMap))
)
class Extensions(univ.SequenceOf):
componentType = Extension()
sizeSpec = univ.SequenceOf.sizeSpec + constraint.ValueSizeConstraint(1, MAX)
class SubjectPublicKeyInfo(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('algorithm', AlgorithmIdentifier()),
namedtype.NamedType('subjectPublicKey', univ.BitString())
)
class UniqueIdentifier(univ.BitString):
pass
class Time(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('utcTime', useful.UTCTime()),
namedtype.NamedType('generalTime', useful.GeneralizedTime())
)
class Validity(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('notBefore', Time()),
namedtype.NamedType('notAfter', Time())
)
class Version(univ.Integer):
namedValues = namedval.NamedValues(
('v1', 0), ('v2', 1), ('v3', 2)
)
class TBSCertificate(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.DefaultedNamedType('version', Version('v1').subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
namedtype.NamedType('serialNumber', CertificateSerialNumber()),
namedtype.NamedType('signature', AlgorithmIdentifier()),
namedtype.NamedType('issuer', Name()),
namedtype.NamedType('validity', Validity()),
namedtype.NamedType('subject', Name()),
namedtype.NamedType('subjectPublicKeyInfo', SubjectPublicKeyInfo()),
namedtype.OptionalNamedType('issuerUniqueID', UniqueIdentifier().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.OptionalNamedType('subjectUniqueID', UniqueIdentifier().subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
namedtype.OptionalNamedType('extensions', Extensions().subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)))
)
class Certificate(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('tbsCertificate', TBSCertificate()),
namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()),
namedtype.NamedType('signatureValue', univ.BitString())
)
# CRL structures
class RevokedCertificate(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('userCertificate', CertificateSerialNumber()),
namedtype.NamedType('revocationDate', Time()),
namedtype.OptionalNamedType('crlEntryExtensions', Extensions())
)
class TBSCertList(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.OptionalNamedType('version', Version()),
namedtype.NamedType('signature', AlgorithmIdentifier()),
namedtype.NamedType('issuer', Name()),
namedtype.NamedType('thisUpdate', Time()),
namedtype.OptionalNamedType('nextUpdate', Time()),
namedtype.OptionalNamedType('revokedCertificates', univ.SequenceOf(componentType=RevokedCertificate())),
namedtype.OptionalNamedType('crlExtensions', Extensions().subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)))
)
class CertificateList(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('tbsCertList', TBSCertList()),
namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()),
namedtype.NamedType('signature', univ.BitString())
)
# map of AttributeType -> AttributeValue
certificateAttributesMap = {
_certificateAttributesMapUpdate = {
id_at_name: X520name(),
id_at_surname: X520name(),
id_at_givenName: X520name(),
@ -1283,14 +1302,18 @@ certificateAttributesMap = {
emailAddress: Pkcs9email(),
}
certificateAttributesMap.update(_certificateAttributesMapUpdate)
# map of Certificate Extension OIDs to Extensions
certificateExtensionsMap = {
_certificateExtensionsMapUpdate = {
id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier(),
id_ce_subjectKeyIdentifier: SubjectKeyIdentifier(),
id_ce_keyUsage: KeyUsage(),
id_ce_privateKeyUsagePeriod: PrivateKeyUsagePeriod(),
id_ce_certificatePolicies: PolicyInformation(), # could be a sequence of concat'ed objects?
# TODO
# id_ce_certificatePolicies: PolicyInformation(), # could be a sequence of concat'ed objects?
id_ce_policyMappings: PolicyMappings(),
id_ce_subjectAltName: SubjectAltName(),
id_ce_issuerAltName: IssuerAltName(),
@ -1309,3 +1332,6 @@ certificateExtensionsMap = {
id_ce_invalidityDate: useful.GeneralizedTime(),
id_ce_certificateIssuer: GeneralNames(),
}
certificateExtensionsMap.update(_certificateExtensionsMapUpdate)

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# X.509 certificate Request Message Format (CRMF) syntax
#
@ -11,8 +11,8 @@
#
# Sample captures could be obtained with OpenSSL
#
from pyasn1_modules.rfc2459 import *
from pyasn1_modules import rfc2315
from pyasn1_modules.rfc2459 import *
MAX = float('inf')

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# OCSP request/response syntax
#
@ -21,7 +21,12 @@
# * dates are left as strings in GeneralizedTime format -- datetime.datetime
# would be nicer
#
from pyasn1.type import tag, namedtype, namedval, univ, useful
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
from pyasn1_modules import rfc2459
@ -124,9 +129,9 @@ class KeyHash(univ.OctetString):
class ResponderID(univ.Choice):
componentType = namedtype.NamedTypes(
namedtype.NamedType('byName',
rfc2459.Name().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
rfc2459.Name().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
namedtype.NamedType('byKey',
KeyHash().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)))
KeyHash().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)))
)

View File

@ -0,0 +1,124 @@
# coding: utf-8
#
# This file is part of pyasn1-modules software.
#
# Created by Joel Johnson with asn1ate tool.
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# PKCS #10: Certification Request Syntax Specification
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc2986.txt
#
from pyasn1.type import univ
from pyasn1.type import char
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import opentype
from pyasn1.type import tag
from pyasn1.type import constraint
from pyasn1.type import useful
MAX = float('inf')
class AttributeType(univ.ObjectIdentifier):
pass
class AttributeValue(univ.Any):
pass
certificateAttributesMap = {}
class AttributeTypeAndValue(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType(
'value', AttributeValue(),
openType=opentype.OpenType('type', certificateAttributesMap)
)
)
class Attribute(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('values',
univ.SetOf(componentType=AttributeValue()),
openType=opentype.OpenType('type', certificateAttributesMap))
)
class Attributes(univ.SetOf):
pass
Attributes.componentType = Attribute()
class RelativeDistinguishedName(univ.SetOf):
pass
RelativeDistinguishedName.componentType = AttributeTypeAndValue()
RelativeDistinguishedName.subtypeSpec = constraint.ValueSizeConstraint(1, MAX)
class RDNSequence(univ.SequenceOf):
pass
RDNSequence.componentType = RelativeDistinguishedName()
class Name(univ.Choice):
pass
Name.componentType = namedtype.NamedTypes(
namedtype.NamedType('rdnSequence', RDNSequence())
)
class AlgorithmIdentifier(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('algorithm', univ.ObjectIdentifier()),
namedtype.OptionalNamedType('parameters', univ.Any())
)
class SubjectPublicKeyInfo(univ.Sequence):
pass
SubjectPublicKeyInfo.componentType = namedtype.NamedTypes(
namedtype.NamedType('algorithm', AlgorithmIdentifier()),
namedtype.NamedType('subjectPublicKey', univ.BitString())
)
class CertificationRequestInfo(univ.Sequence):
pass
CertificationRequestInfo.componentType = namedtype.NamedTypes(
namedtype.NamedType('version', univ.Integer()),
namedtype.NamedType('subject', Name()),
namedtype.NamedType('subjectPKInfo', SubjectPublicKeyInfo()),
namedtype.NamedType('attributes', Attributes().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))
)
class CertificationRequest(univ.Sequence):
pass
CertificationRequest.componentType = namedtype.NamedTypes(
namedtype.NamedType('certificationRequestInfo', CertificationRequestInfo()),
namedtype.NamedType('signatureAlgorithm', AlgorithmIdentifier()),
namedtype.NamedType('signature', univ.BitString())
)

View File

@ -2,11 +2,13 @@
# This file is part of pyasn1-modules.
#
# Copyright (c) 2017, Danielle Madeley <danielle@madeley.id.au>
# License: http://pyasn1.sf.net/license.html
# License: http://snmplabs.com/pyasn1/license.html
#
# Derived from RFC 3279
#
from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import univ
def _OID(*components):

View File

@ -3,8 +3,8 @@
# This file is part of pyasn1-modules software.
#
# Created by Stanisław Pitucha with asn1ate tool.
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Internet X.509 Public Key Infrastructure Certificate and Certificate
# Revocation List (CRL) Profile
@ -12,7 +12,13 @@
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc3280.txt
#
from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful
from pyasn1.type import char
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
MAX = float('inf')

View File

@ -3,20 +3,20 @@
# This file is part of pyasn1-modules software.
#
# Created by Stanisław Pitucha with asn1ate tool.
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# An Internet Attribute Certificate Profile for Authorization
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc3281.txt
#
from pyasn1.type import univ
from pyasn1.type import char
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import constraint
from pyasn1.type import univ
from pyasn1.type import useful
from pyasn1_modules import rfc3280

View File

@ -1,15 +1,18 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# SNMPv3 message syntax
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc3412.txt
#
from pyasn1.type import univ, namedtype, constraint
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import univ
from pyasn1_modules import rfc1905

View File

@ -1,15 +1,17 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# SNMPv3 message syntax
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc3414.txt
#
from pyasn1.type import univ, namedtype, constraint
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import univ
class UsmSecurityParameters(univ.Sequence):

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# PKCS#1 syntax
#
@ -11,7 +11,9 @@
#
# Sample captures could be obtained with "openssl genrsa" command
#
from pyasn1.type import constraint, namedval
from pyasn1.type import constraint
from pyasn1.type import namedval
from pyasn1_modules.rfc2437 import *

View File

@ -3,15 +3,20 @@
# This file is part of pyasn1-modules software.
#
# Created by Stanisław Pitucha with asn1ate tool.
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Cryptographic Message Syntax (CMS)
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc3852.txt
#
from pyasn1.type import univ, namedtype, namedval, tag, constraint, useful
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
from pyasn1_modules import rfc3280
from pyasn1_modules import rfc3281

View File

@ -1,15 +1,24 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Certificate Management Protocol structures as per RFC4210
#
# Based on Alex Railean's work
#
from pyasn1.type import tag, namedtype, namedval, univ, constraint, char, useful
from pyasn1_modules import rfc2459, rfc2511, rfc2314
from pyasn1.type import char
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
from pyasn1_modules import rfc2314
from pyasn1_modules import rfc2459
from pyasn1_modules import rfc2511
MAX = float('inf')

View File

@ -3,8 +3,8 @@
# This file is part of pyasn1-modules software.
#
# Created by Stanisław Pitucha with asn1ate tool.
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Internet X.509 Public Key Infrastructure Certificate Request
# Message Format (CRMF)
@ -12,7 +12,12 @@
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc4211.txt
#
from pyasn1.type import univ, char, namedtype, namedval, tag, constraint
from pyasn1.type import char
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1_modules import rfc3280
from pyasn1_modules import rfc3852

View File

@ -1,8 +1,8 @@
#
# This file is part of pyasn1-modules software.
#
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# PKCS#8 syntax
#
@ -11,8 +11,8 @@
#
# Sample captures could be obtained with "openssl pkcs8 -topk8" command
#
from pyasn1_modules.rfc2459 import *
from pyasn1_modules import rfc2251
from pyasn1_modules.rfc2459 import *
class KeyEncryptionAlgorithms(AlgorithmIdentifier):

View File

@ -3,8 +3,8 @@
# This file is part of pyasn1-modules software.
#
# Created by Stanisław Pitucha with asn1ate tool.
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Internet X.509 Public Key Infrastructure Certificate and Certificate
# Revocation List (CRL) Profile
@ -12,16 +12,18 @@
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc5280.txt
#
from pyasn1.type import univ
from pyasn1.type import char
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import opentype
from pyasn1.type import tag
from pyasn1.type import constraint
from pyasn1.type import univ
from pyasn1.type import useful
MAX = float('inf')
def _buildOid(*components):
output = []
for x in tuple(components):
@ -279,13 +281,10 @@ class CertificateSerialNumber(univ.Integer):
class AlgorithmIdentifier(univ.Sequence):
pass
AlgorithmIdentifier.componentType = namedtype.NamedTypes(
namedtype.NamedType('algorithm', univ.ObjectIdentifier()),
namedtype.OptionalNamedType('parameters', univ.Any())
)
componentType = namedtype.NamedTypes(
namedtype.NamedType('algorithm', univ.ObjectIdentifier()),
namedtype.OptionalNamedType('parameters', univ.Any())
)
class Time(univ.Choice):
@ -302,14 +301,17 @@ class AttributeValue(univ.Any):
pass
certificateAttributesMap = {}
class AttributeTypeAndValue(univ.Sequence):
pass
AttributeTypeAndValue.componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('value', AttributeValue())
)
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType(
'value', AttributeValue(),
openType=opentype.OpenType('type', certificateAttributesMap)
)
)
class RelativeDistinguishedName(univ.SetOf):
@ -379,18 +381,21 @@ class PhysicalDeliveryOfficeName(PDSParameter):
ub_extension_attributes = univ.Integer(256)
certificateExtensionsMap = {
}
class ExtensionAttribute(univ.Sequence):
pass
ExtensionAttribute.componentType = namedtype.NamedTypes(
namedtype.NamedType('extension-attribute-type', univ.Integer().subtype(
subtypeSpec=constraint.ValueRangeConstraint(0, ub_extension_attributes)).subtype(
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
namedtype.NamedType('extension-attribute-value',
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)))
)
componentType = namedtype.NamedTypes(
namedtype.NamedType(
'extension-attribute-type',
univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, ub_extension_attributes)).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
namedtype.NamedType(
'extension-attribute-value',
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)),
openType=opentype.OpenType('type', certificateExtensionsMap))
)
id_qt = _buildOid(id_pkix, 2)
@ -737,13 +742,12 @@ X520SerialNumber.subtypeSpec = constraint.ValueSizeConstraint(1, ub_serial_numbe
class Attribute(univ.Sequence):
pass
Attribute.componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('values', univ.SetOf(componentType=AttributeValue()))
)
componentType = namedtype.NamedTypes(
namedtype.NamedType('type', AttributeType()),
namedtype.NamedType('values',
univ.SetOf(componentType=AttributeValue()),
openType=opentype.OpenType('type', certificateAttributesMap))
)
ub_common_name = univ.Integer(64)
@ -1066,14 +1070,20 @@ PrivateKeyUsagePeriod.componentType = namedtype.NamedTypes(
)
anotherNameMap = {
}
class AnotherName(univ.Sequence):
pass
AnotherName.componentType = namedtype.NamedTypes(
namedtype.NamedType('type-id', univ.ObjectIdentifier()),
namedtype.NamedType('value', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))
)
componentType = namedtype.NamedTypes(
namedtype.NamedType('type-id', univ.ObjectIdentifier()),
namedtype.NamedType(
'value',
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)),
openType=opentype.OpenType('type-id', anotherNameMap)
)
)
class EDIPartyName(univ.Sequence):
@ -1311,14 +1321,19 @@ class PolicyQualifierId(univ.ObjectIdentifier):
pass
policyQualifierInfoMap = {
}
class PolicyQualifierInfo(univ.Sequence):
pass
PolicyQualifierInfo.componentType = namedtype.NamedTypes(
namedtype.NamedType('policyQualifierId', PolicyQualifierId()),
namedtype.NamedType('qualifier', univ.Any())
)
componentType = namedtype.NamedTypes(
namedtype.NamedType('policyQualifierId', PolicyQualifierId()),
namedtype.NamedType(
'qualifier', univ.Any(),
openType=opentype.OpenType('policyQualifierId', policyQualifierInfoMap)
)
)
class CertPolicyId(univ.ObjectIdentifier):
@ -1549,7 +1564,7 @@ id_ce_inhibitAnyPolicy = _buildOid(id_ce, 54)
# map of AttributeType -> AttributeValue
certificateAttributesMap = {
_certificateAttributesMapUpdate = {
id_at_name: X520name(),
id_at_surname: X520name(),
id_at_givenName: X520name(),
@ -1569,9 +1584,12 @@ certificateAttributesMap = {
id_emailAddress: EmailAddress(),
}
certificateAttributesMap.update(_certificateAttributesMapUpdate)
# map of Certificate Extension OIDs to Extensions
certificateExtensionsMap = {
_certificateExtensionsMap = {
id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier(),
id_ce_subjectKeyIdentifier: SubjectKeyIdentifier(),
id_ce_keyUsage: KeyUsage(),
@ -1595,3 +1613,5 @@ certificateExtensionsMap = {
id_ce_invalidityDate: useful.GeneralizedTime(),
id_ce_certificateIssuer: GeneralNames(),
}
certificateExtensionsMap.update(_certificateExtensionsMap)

View File

@ -3,8 +3,8 @@
# This file is part of pyasn1-modules software.
#
# Created by Stanisław Pitucha with asn1ate tool.
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Cryptographic Message Syntax (CMS)
#

View File

@ -3,15 +3,21 @@
# This file is part of pyasn1-modules software.
#
# Created by Stanisław Pitucha with asn1ate tool.
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
# License: http://pyasn1.sf.net/license.html
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
# License: http://snmplabs.com/pyasn1/license.html
#
# Certificate Management over CMS (CMC) Updates
#
# ASN.1 source from:
# http://www.ietf.org/rfc/rfc6402.txt
#
from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful
from pyasn1.type import char
from pyasn1.type import constraint
from pyasn1.type import namedtype
from pyasn1.type import namedval
from pyasn1.type import tag
from pyasn1.type import univ
from pyasn1.type import useful
from pyasn1_modules import rfc4211
from pyasn1_modules import rfc5280