mirror of
https://github.com/GAM-team/GAM.git
synced 2025-07-09 22:23:35 +00:00
pyasn1 0.4.3, pyasn1_modules 0.2.2
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
# http://www.python.org/dev/peps/pep-0396/
|
# https://www.python.org/dev/peps/pep-0396/
|
||||||
__version__ = '0.3.7'
|
__version__ = '0.4.3'
|
||||||
|
|
||||||
if sys.version_info[:2] < (2, 4):
|
if sys.version_info[:2] < (2, 4):
|
||||||
raise RuntimeError('PyASN1 requires Python 2.4 or later')
|
raise RuntimeError('PyASN1 requires Python 2.4 or later')
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# 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.codec.ber import eoo
|
||||||
from pyasn1.compat.octets import oct2int, octs2ints, ints2octs, null
|
|
||||||
from pyasn1.compat.integer import from_bytes
|
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']
|
__all__ = ['decode']
|
||||||
|
|
||||||
@ -36,8 +42,10 @@ class AbstractSimpleDecoder(AbstractDecoder):
|
|||||||
def substrateCollector(asn1Object, substrate, length):
|
def substrateCollector(asn1Object, substrate, length):
|
||||||
return substrate[:length], substrate[length:]
|
return substrate[:length], substrate[length:]
|
||||||
|
|
||||||
def _createComponent(self, asn1Spec, tagSet, value=noValue):
|
def _createComponent(self, asn1Spec, tagSet, value, **options):
|
||||||
if asn1Spec is None:
|
if options.get('native'):
|
||||||
|
return value
|
||||||
|
elif asn1Spec is None:
|
||||||
return self.protoComponent.clone(value, tagSet=tagSet)
|
return self.protoComponent.clone(value, tagSet=tagSet)
|
||||||
elif value is noValue:
|
elif value is noValue:
|
||||||
return asn1Spec
|
return asn1Spec
|
||||||
@ -54,7 +62,7 @@ class ExplicitTagDecoder(AbstractSimpleDecoder):
|
|||||||
**options):
|
**options):
|
||||||
if substrateFun:
|
if substrateFun:
|
||||||
return substrateFun(
|
return substrateFun(
|
||||||
self._createComponent(asn1Spec, tagSet, ''),
|
self._createComponent(asn1Spec, tagSet, '', **options),
|
||||||
substrate, length
|
substrate, length
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,7 +78,7 @@ class ExplicitTagDecoder(AbstractSimpleDecoder):
|
|||||||
**options):
|
**options):
|
||||||
if substrateFun:
|
if substrateFun:
|
||||||
return substrateFun(
|
return substrateFun(
|
||||||
self._createComponent(asn1Spec, tagSet, ''),
|
self._createComponent(asn1Spec, tagSet, '', **options),
|
||||||
substrate, length
|
substrate, length
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -101,18 +109,18 @@ class IntegerDecoder(AbstractSimpleDecoder):
|
|||||||
head, tail = substrate[:length], substrate[length:]
|
head, tail = substrate[:length], substrate[length:]
|
||||||
|
|
||||||
if not head:
|
if not head:
|
||||||
return self._createComponent(asn1Spec, tagSet, 0), tail
|
return self._createComponent(asn1Spec, tagSet, 0, **options), tail
|
||||||
|
|
||||||
value = from_bytes(head, signed=True)
|
value = from_bytes(head, signed=True)
|
||||||
|
|
||||||
return self._createComponent(asn1Spec, tagSet, value), tail
|
return self._createComponent(asn1Spec, tagSet, value, **options), tail
|
||||||
|
|
||||||
|
|
||||||
class BooleanDecoder(IntegerDecoder):
|
class BooleanDecoder(IntegerDecoder):
|
||||||
protoComponent = univ.Boolean(0)
|
protoComponent = univ.Boolean(0)
|
||||||
|
|
||||||
def _createComponent(self, asn1Spec, tagSet, value=noValue):
|
def _createComponent(self, asn1Spec, tagSet, value, **options):
|
||||||
return IntegerDecoder._createComponent(self, asn1Spec, tagSet, value and 1 or 0)
|
return IntegerDecoder._createComponent(self, asn1Spec, tagSet, value and 1 or 0, **options)
|
||||||
|
|
||||||
|
|
||||||
class BitStringDecoder(AbstractSimpleDecoder):
|
class BitStringDecoder(AbstractSimpleDecoder):
|
||||||
@ -124,53 +132,86 @@ class BitStringDecoder(AbstractSimpleDecoder):
|
|||||||
decodeFun=None, substrateFun=None,
|
decodeFun=None, substrateFun=None,
|
||||||
**options):
|
**options):
|
||||||
head, tail = substrate[:length], substrate[length:]
|
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 tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check?
|
||||||
if not head:
|
|
||||||
raise error.PyAsn1Error('Empty substrate')
|
|
||||||
trailingBits = oct2int(head[0])
|
trailingBits = oct2int(head[0])
|
||||||
if trailingBits > 7:
|
if trailingBits > 7:
|
||||||
raise error.PyAsn1Error(
|
raise error.PyAsn1Error(
|
||||||
'Trailing bits overflow %s' % trailingBits
|
'Trailing bits overflow %s' % trailingBits
|
||||||
)
|
)
|
||||||
head = head[1:]
|
|
||||||
value = self.protoComponent.fromOctetString(head, trailingBits)
|
value = self.protoComponent.fromOctetString(head[1:], internalFormat=True, padding=trailingBits)
|
||||||
return self._createComponent(asn1Spec, tagSet, value), tail
|
|
||||||
|
return self._createComponent(asn1Spec, tagSet, value, **options), tail
|
||||||
|
|
||||||
if not self.supportConstructedForm:
|
if not self.supportConstructedForm:
|
||||||
raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__)
|
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:
|
bitString = self.protoComponent.fromOctetString(null, internalFormat=True)
|
||||||
return substrateFun(bitString, substrate, length)
|
|
||||||
|
|
||||||
while head:
|
while head:
|
||||||
component, head = decodeFun(head, self.protoComponent, **options)
|
component, head = decodeFun(head, self.protoComponent,
|
||||||
bitString += component
|
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,
|
def indefLenValueDecoder(self, substrate, asn1Spec,
|
||||||
tagSet=None, length=None, state=None,
|
tagSet=None, length=None, state=None,
|
||||||
decodeFun=None, substrateFun=None,
|
decodeFun=None, substrateFun=None,
|
||||||
**options):
|
**options):
|
||||||
bitString = self._createComponent(asn1Spec, tagSet)
|
|
||||||
|
|
||||||
if substrateFun:
|
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:
|
while substrate:
|
||||||
component, substrate = decodeFun(substrate, self.protoComponent,
|
component, substrate = decodeFun(substrate, self.protoComponent,
|
||||||
|
substrateFun=substrateFun,
|
||||||
allowEoo=True, **options)
|
allowEoo=True, **options)
|
||||||
if component is eoo.endOfOctets:
|
if component is eoo.endOfOctets:
|
||||||
break
|
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:
|
else:
|
||||||
raise error.SubstrateUnderrunError('No EOO seen before substrate ends')
|
raise error.SubstrateUnderrunError('No EOO seen before substrate ends')
|
||||||
|
|
||||||
return bitString, substrate
|
return self._createComponent(asn1Spec, tagSet, bitString, **options), substrate
|
||||||
|
|
||||||
|
|
||||||
class OctetStringDecoder(AbstractSimpleDecoder):
|
class OctetStringDecoder(AbstractSimpleDecoder):
|
||||||
@ -184,11 +225,11 @@ class OctetStringDecoder(AbstractSimpleDecoder):
|
|||||||
head, tail = substrate[:length], substrate[length:]
|
head, tail = substrate[:length], substrate[length:]
|
||||||
|
|
||||||
if substrateFun:
|
if substrateFun:
|
||||||
return substrateFun(self._createComponent(asn1Spec, tagSet),
|
return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options),
|
||||||
substrate, length)
|
substrate, length)
|
||||||
|
|
||||||
if tagSet[0].tagFormat == tag.tagFormatSimple: # XXX what tag to check?
|
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:
|
if not self.supportConstructedForm:
|
||||||
raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__)
|
raise error.PyAsn1Error('Constructed encoding form prohibited at %s' % self.__class__.__name__)
|
||||||
@ -204,14 +245,14 @@ class OctetStringDecoder(AbstractSimpleDecoder):
|
|||||||
**options)
|
**options)
|
||||||
header += component
|
header += component
|
||||||
|
|
||||||
return self._createComponent(asn1Spec, tagSet, header), tail
|
return self._createComponent(asn1Spec, tagSet, header, **options), tail
|
||||||
|
|
||||||
def indefLenValueDecoder(self, substrate, asn1Spec,
|
def indefLenValueDecoder(self, substrate, asn1Spec,
|
||||||
tagSet=None, length=None, state=None,
|
tagSet=None, length=None, state=None,
|
||||||
decodeFun=None, substrateFun=None,
|
decodeFun=None, substrateFun=None,
|
||||||
**options):
|
**options):
|
||||||
if substrateFun and substrateFun is not self.substrateCollector:
|
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)
|
return substrateFun(asn1Object, substrate, length)
|
||||||
|
|
||||||
# All inner fragments are of the same type, treat them as octet string
|
# 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'
|
'No EOO seen before substrate ends'
|
||||||
)
|
)
|
||||||
|
|
||||||
return self._createComponent(asn1Spec, tagSet, header), substrate
|
return self._createComponent(asn1Spec, tagSet, header, **options), substrate
|
||||||
|
|
||||||
|
|
||||||
class NullDecoder(AbstractSimpleDecoder):
|
class NullDecoder(AbstractSimpleDecoder):
|
||||||
@ -248,7 +289,7 @@ class NullDecoder(AbstractSimpleDecoder):
|
|||||||
|
|
||||||
head, tail = substrate[:length], substrate[length:]
|
head, tail = substrate[:length], substrate[length:]
|
||||||
|
|
||||||
component = self._createComponent(asn1Spec, tagSet)
|
component = self._createComponent(asn1Spec, tagSet, '', **options)
|
||||||
|
|
||||||
if head:
|
if head:
|
||||||
raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length)
|
raise error.PyAsn1Error('Unexpected %d-octet substrate for Null' % length)
|
||||||
@ -296,7 +337,7 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder):
|
|||||||
elif subId == 128:
|
elif subId == 128:
|
||||||
# ASN.1 spec forbids leading zeros (0x80) in OID
|
# ASN.1 spec forbids leading zeros (0x80) in OID
|
||||||
# encoding, tolerating it opens a vulnerability. See
|
# 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
|
# page 7
|
||||||
raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')
|
raise error.PyAsn1Error('Invalid octet 0x80 in OID encoding')
|
||||||
|
|
||||||
@ -310,7 +351,7 @@ class ObjectIdentifierDecoder(AbstractSimpleDecoder):
|
|||||||
else:
|
else:
|
||||||
raise error.PyAsn1Error('Malformed first OID octet: %s' % head[0])
|
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):
|
class RealDecoder(AbstractSimpleDecoder):
|
||||||
@ -326,7 +367,7 @@ class RealDecoder(AbstractSimpleDecoder):
|
|||||||
head, tail = substrate[:length], substrate[length:]
|
head, tail = substrate[:length], substrate[length:]
|
||||||
|
|
||||||
if not head:
|
if not head:
|
||||||
return self._createComponent(asn1Spec, tagSet, 0.0), tail
|
return self._createComponent(asn1Spec, tagSet, 0.0, **options), tail
|
||||||
|
|
||||||
fo = oct2int(head[0])
|
fo = oct2int(head[0])
|
||||||
head = head[1:]
|
head = head[1:]
|
||||||
@ -386,7 +427,7 @@ class RealDecoder(AbstractSimpleDecoder):
|
|||||||
raise error.SubstrateUnderrunError(
|
raise error.SubstrateUnderrunError(
|
||||||
'Unknown encoding (tag %s)' % fo
|
'Unknown encoding (tag %s)' % fo
|
||||||
)
|
)
|
||||||
return self._createComponent(asn1Spec, tagSet, value), tail
|
return self._createComponent(asn1Spec, tagSet, value, **options), tail
|
||||||
|
|
||||||
|
|
||||||
class AbstractConstructedDecoder(AbstractDecoder):
|
class AbstractConstructedDecoder(AbstractDecoder):
|
||||||
@ -415,10 +456,9 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
|
|||||||
|
|
||||||
# Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF
|
# Now we have to guess is it SEQUENCE/SET or SEQUENCE OF/SET OF
|
||||||
# The heuristics is:
|
# The heuristics is:
|
||||||
# * 0-1 component -> likely SEQUENCE OF/SET OF
|
# * 1+ components of different types -> likely SEQUENCE/SET
|
||||||
# * 1+ components of the same type -> likely SEQUENCE OF/SET OF
|
# * otherwise -> likely SEQUENCE OF/SET OF
|
||||||
# * otherwise -> likely SEQUENCE/SET
|
if len(componentTypes) > 1:
|
||||||
if len(components) > 1 or len(componentTypes) > 1:
|
|
||||||
protoComponent = self.protoRecordComponent
|
protoComponent = self.protoRecordComponent
|
||||||
else:
|
else:
|
||||||
protoComponent = self.protoSequenceComponent
|
protoComponent = self.protoSequenceComponent
|
||||||
@ -467,34 +507,34 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
|
|||||||
|
|
||||||
asn1Object = asn1Spec.clone()
|
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
|
isDeterministic = not isSetType and not namedTypes.hasOptionalOrDefault
|
||||||
|
|
||||||
seenIndices = set()
|
seenIndices = set()
|
||||||
idx = 0
|
idx = 0
|
||||||
while head:
|
while head:
|
||||||
if not namedTypes:
|
if not namedTypes:
|
||||||
asn1Spec = None
|
componentType = None
|
||||||
elif isSetType:
|
elif isSetType:
|
||||||
asn1Spec = namedTypes.tagMapUnique
|
componentType = namedTypes.tagMapUnique
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
if isDeterministic:
|
if isDeterministic:
|
||||||
asn1Spec = namedTypes[idx].asn1Object
|
componentType = namedTypes[idx].asn1Object
|
||||||
elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
|
elif namedTypes[idx].isOptional or namedTypes[idx].isDefaulted:
|
||||||
asn1Spec = namedTypes.getTagMapNearPosition(idx)
|
componentType = namedTypes.getTagMapNearPosition(idx)
|
||||||
else:
|
else:
|
||||||
asn1Spec = namedTypes[idx].asn1Object
|
componentType = namedTypes[idx].asn1Object
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise error.PyAsn1Error(
|
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 not isDeterministic and namedTypes:
|
||||||
if isSetType:
|
if isSetType:
|
||||||
@ -514,14 +554,54 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
|
|||||||
if namedTypes:
|
if namedTypes:
|
||||||
if not namedTypes.requiredComponents.issubset(seenIndices):
|
if not namedTypes.requiredComponents.issubset(seenIndices):
|
||||||
raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__)
|
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:
|
else:
|
||||||
asn1Object.verifySizeSpec()
|
asn1Object.verifySizeSpec()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
asn1Spec = asn1Object.componentType
|
asn1Object = asn1Spec.clone()
|
||||||
|
|
||||||
|
componentType = asn1Spec.componentType
|
||||||
|
|
||||||
idx = 0
|
idx = 0
|
||||||
|
|
||||||
while head:
|
while head:
|
||||||
component, head = decodeFun(head, asn1Spec, **options)
|
component, head = decodeFun(head, componentType, **options)
|
||||||
asn1Object.setComponentByPosition(
|
asn1Object.setComponentByPosition(
|
||||||
idx, component,
|
idx, component,
|
||||||
verifyConstraints=False,
|
verifyConstraints=False,
|
||||||
@ -529,8 +609,6 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
|
|||||||
)
|
)
|
||||||
idx += 1
|
idx += 1
|
||||||
|
|
||||||
asn1Object.verifySizeSpec()
|
|
||||||
|
|
||||||
return asn1Object, tail
|
return asn1Object, tail
|
||||||
|
|
||||||
def indefLenValueDecoder(self, substrate, asn1Spec,
|
def indefLenValueDecoder(self, substrate, asn1Spec,
|
||||||
@ -557,7 +635,7 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
|
|||||||
|
|
||||||
asn1Object = asn1Spec.clone()
|
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 = asn1Object.componentType
|
||||||
|
|
||||||
@ -611,16 +689,59 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
|
|||||||
if namedTypes:
|
if namedTypes:
|
||||||
if not namedTypes.requiredComponents.issubset(seenIndices):
|
if not namedTypes.requiredComponents.issubset(seenIndices):
|
||||||
raise error.PyAsn1Error('ASN.1 object %s has uninitialized components' % asn1Object.__class__.__name__)
|
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:
|
else:
|
||||||
asn1Spec = asn1Object.componentType
|
asn1Object = asn1Spec.clone()
|
||||||
|
|
||||||
|
componentType = asn1Spec.componentType
|
||||||
|
|
||||||
idx = 0
|
idx = 0
|
||||||
|
|
||||||
while substrate:
|
while substrate:
|
||||||
component, substrate = decodeFun(substrate, asn1Spec, allowEoo=True, **options)
|
component, substrate = decodeFun(substrate, componentType, allowEoo=True, **options)
|
||||||
|
|
||||||
if component is eoo.endOfOctets:
|
if component is eoo.endOfOctets:
|
||||||
break
|
break
|
||||||
|
|
||||||
asn1Object.setComponentByPosition(
|
asn1Object.setComponentByPosition(
|
||||||
idx, component,
|
idx, component,
|
||||||
verifyConstraints=False,
|
verifyConstraints=False,
|
||||||
@ -631,7 +752,6 @@ class UniversalConstructedTypeDecoder(AbstractConstructedDecoder):
|
|||||||
raise error.SubstrateUnderrunError(
|
raise error.SubstrateUnderrunError(
|
||||||
'No EOO seen before substrate ends'
|
'No EOO seen before substrate ends'
|
||||||
)
|
)
|
||||||
asn1Object.verifySizeSpec()
|
|
||||||
|
|
||||||
return asn1Object, substrate
|
return asn1Object, substrate
|
||||||
|
|
||||||
@ -671,28 +791,35 @@ class ChoiceDecoder(AbstractConstructedDecoder):
|
|||||||
decodeFun=None, substrateFun=None,
|
decodeFun=None, substrateFun=None,
|
||||||
**options):
|
**options):
|
||||||
head, tail = substrate[:length], substrate[length:]
|
head, tail = substrate[:length], substrate[length:]
|
||||||
|
|
||||||
if asn1Spec is None:
|
if asn1Spec is None:
|
||||||
asn1Object = self.protoComponent.clone(tagSet=tagSet)
|
asn1Object = self.protoComponent.clone(tagSet=tagSet)
|
||||||
else:
|
else:
|
||||||
asn1Object = asn1Spec.clone()
|
asn1Object = asn1Spec.clone()
|
||||||
|
|
||||||
if substrateFun:
|
if substrateFun:
|
||||||
return substrateFun(asn1Object, substrate, length)
|
return substrateFun(asn1Object, substrate, length)
|
||||||
|
|
||||||
if asn1Object.tagSet == tagSet: # explicitly tagged Choice
|
if asn1Object.tagSet == tagSet: # explicitly tagged Choice
|
||||||
component, head = decodeFun(
|
component, head = decodeFun(
|
||||||
head, asn1Object.componentTagMap, **options
|
head, asn1Object.componentTagMap, **options
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
component, head = decodeFun(
|
component, head = decodeFun(
|
||||||
head, asn1Object.componentTagMap,
|
head, asn1Object.componentTagMap,
|
||||||
tagSet, length, state, **options
|
tagSet, length, state, **options
|
||||||
)
|
)
|
||||||
|
|
||||||
effectiveTagSet = component.effectiveTagSet
|
effectiveTagSet = component.effectiveTagSet
|
||||||
|
|
||||||
asn1Object.setComponentByType(
|
asn1Object.setComponentByType(
|
||||||
effectiveTagSet, component,
|
effectiveTagSet, component,
|
||||||
verifyConstraints=False,
|
verifyConstraints=False,
|
||||||
matchTags=False, matchConstraints=False,
|
matchTags=False, matchConstraints=False,
|
||||||
innerFlag=False
|
innerFlag=False
|
||||||
)
|
)
|
||||||
|
|
||||||
return asn1Object, tail
|
return asn1Object, tail
|
||||||
|
|
||||||
def indefLenValueDecoder(self, substrate, asn1Spec,
|
def indefLenValueDecoder(self, substrate, asn1Spec,
|
||||||
@ -703,8 +830,10 @@ class ChoiceDecoder(AbstractConstructedDecoder):
|
|||||||
asn1Object = self.protoComponent.clone(tagSet=tagSet)
|
asn1Object = self.protoComponent.clone(tagSet=tagSet)
|
||||||
else:
|
else:
|
||||||
asn1Object = asn1Spec.clone()
|
asn1Object = asn1Spec.clone()
|
||||||
|
|
||||||
if substrateFun:
|
if substrateFun:
|
||||||
return substrateFun(asn1Object, substrate, length)
|
return substrateFun(asn1Object, substrate, length)
|
||||||
|
|
||||||
if asn1Object.tagSet == tagSet: # explicitly tagged Choice
|
if asn1Object.tagSet == tagSet: # explicitly tagged Choice
|
||||||
component, substrate = decodeFun(
|
component, substrate = decodeFun(
|
||||||
substrate, asn1Object.componentType.tagMapUnique, **options
|
substrate, asn1Object.componentType.tagMapUnique, **options
|
||||||
@ -715,18 +844,22 @@ class ChoiceDecoder(AbstractConstructedDecoder):
|
|||||||
)
|
)
|
||||||
if eooMarker is not eoo.endOfOctets:
|
if eooMarker is not eoo.endOfOctets:
|
||||||
raise error.PyAsn1Error('No EOO seen before substrate ends')
|
raise error.PyAsn1Error('No EOO seen before substrate ends')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
component, substrate = decodeFun(
|
component, substrate = decodeFun(
|
||||||
substrate, asn1Object.componentType.tagMapUnique,
|
substrate, asn1Object.componentType.tagMapUnique,
|
||||||
tagSet, length, state, **options
|
tagSet, length, state, **options
|
||||||
)
|
)
|
||||||
|
|
||||||
effectiveTagSet = component.effectiveTagSet
|
effectiveTagSet = component.effectiveTagSet
|
||||||
|
|
||||||
asn1Object.setComponentByType(
|
asn1Object.setComponentByType(
|
||||||
effectiveTagSet, component,
|
effectiveTagSet, component,
|
||||||
verifyConstraints=False,
|
verifyConstraints=False,
|
||||||
matchTags=False, matchConstraints=False,
|
matchTags=False, matchConstraints=False,
|
||||||
innerFlag=False
|
innerFlag=False
|
||||||
)
|
)
|
||||||
|
|
||||||
return asn1Object, substrate
|
return asn1Object, substrate
|
||||||
|
|
||||||
|
|
||||||
@ -745,12 +878,12 @@ class AnyDecoder(AbstractSimpleDecoder):
|
|||||||
substrate = fullSubstrate
|
substrate = fullSubstrate
|
||||||
|
|
||||||
if substrateFun:
|
if substrateFun:
|
||||||
return substrateFun(self._createComponent(asn1Spec, tagSet),
|
return substrateFun(self._createComponent(asn1Spec, tagSet, noValue, **options),
|
||||||
substrate, length)
|
substrate, length)
|
||||||
|
|
||||||
head, tail = substrate[:length], 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,
|
def indefLenValueDecoder(self, substrate, asn1Spec,
|
||||||
tagSet=None, length=None, state=None,
|
tagSet=None, length=None, state=None,
|
||||||
@ -769,7 +902,7 @@ class AnyDecoder(AbstractSimpleDecoder):
|
|||||||
asn1Spec = self.protoComponent
|
asn1Spec = self.protoComponent
|
||||||
|
|
||||||
if substrateFun and substrateFun is not self.substrateCollector:
|
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))
|
return substrateFun(asn1Object, header + substrate, length + len(header))
|
||||||
|
|
||||||
# All inner fragments are of the same type, treat them as octet string
|
# All inner fragments are of the same type, treat them as octet string
|
||||||
@ -789,7 +922,7 @@ class AnyDecoder(AbstractSimpleDecoder):
|
|||||||
if substrateFun:
|
if substrateFun:
|
||||||
return header, substrate
|
return header, substrate
|
||||||
else:
|
else:
|
||||||
return self._createComponent(asn1Spec, tagSet, header), substrate
|
return self._createComponent(asn1Spec, tagSet, header, **options), substrate
|
||||||
|
|
||||||
|
|
||||||
# character string types
|
# character string types
|
||||||
@ -1159,8 +1292,10 @@ class Decoder(object):
|
|||||||
self, substrateFun,
|
self, substrateFun,
|
||||||
**options
|
**options
|
||||||
)
|
)
|
||||||
|
|
||||||
if logger:
|
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>'))
|
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
|
state = stStop
|
||||||
break
|
break
|
||||||
if state is stTryAsExplicitTag:
|
if state is stTryAsExplicitTag:
|
||||||
@ -1190,15 +1325,17 @@ class Decoder(object):
|
|||||||
|
|
||||||
#: Turns BER octet stream into an ASN.1 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
|
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
|
||||||
#: may be a scalar or an arbitrary nested structure.
|
#: may be a scalar or an arbitrary nested structure.
|
||||||
#:
|
#:
|
||||||
#: Parameters
|
#: Parameters
|
||||||
#: ----------
|
#: ----------
|
||||||
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
#: 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
|
#: 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
|
#: 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
|
#: being decoded, *asn1Spec* may or may not be required. Most common reason for
|
||||||
@ -1212,8 +1349,30 @@ class Decoder(object):
|
|||||||
#:
|
#:
|
||||||
#: Raises
|
#: Raises
|
||||||
#: ------
|
#: ------
|
||||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
#: :py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
#: On decoding errors
|
#: 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)
|
decode = Decoder(tagMap, typeMap)
|
||||||
|
|
||||||
# XXX
|
# XXX
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# 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.codec.ber import eoo
|
||||||
from pyasn1.compat.octets import int2oct, oct2int, ints2octs, null, str2octs
|
|
||||||
from pyasn1.compat.integer import to_bytes
|
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']
|
__all__ = ['encode']
|
||||||
|
|
||||||
|
|
||||||
class AbstractItemEncoder(object):
|
class AbstractItemEncoder(object):
|
||||||
supportIndefLenMode = 1
|
supportIndefLenMode = True
|
||||||
|
|
||||||
# An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)`
|
# An outcome of otherwise legit call `encodeFun(eoo.endOfOctets)`
|
||||||
eooIntegerSubstrate = (0, 0)
|
eooIntegerSubstrate = (0, 0)
|
||||||
@ -51,17 +56,20 @@ class AbstractItemEncoder(object):
|
|||||||
raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen)
|
raise error.PyAsn1Error('Length octets overflow (%d)' % substrateLen)
|
||||||
return (0x80 | substrateLen,) + substrate
|
return (0x80 | substrateLen,) + substrate
|
||||||
|
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
raise error.PyAsn1Error('Not implemented')
|
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?
|
# untagged item?
|
||||||
if not tagSet:
|
if not tagSet:
|
||||||
substrate, isConstructed, isOctets = self.encodeValue(
|
substrate, isConstructed, isOctets = self.encodeValue(
|
||||||
value, encodeFun, **options
|
value, asn1Spec, encodeFun, **options
|
||||||
)
|
)
|
||||||
return substrate
|
return substrate
|
||||||
|
|
||||||
@ -74,10 +82,10 @@ class AbstractItemEncoder(object):
|
|||||||
# base tag?
|
# base tag?
|
||||||
if not idx:
|
if not idx:
|
||||||
substrate, isConstructed, isOctets = self.encodeValue(
|
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
|
return substrate
|
||||||
|
|
||||||
# primitive form implies definite mode
|
# primitive form implies definite mode
|
||||||
@ -106,14 +114,14 @@ class AbstractItemEncoder(object):
|
|||||||
|
|
||||||
|
|
||||||
class EndOfOctetsEncoder(AbstractItemEncoder):
|
class EndOfOctetsEncoder(AbstractItemEncoder):
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
return null, False, True
|
return null, False, True
|
||||||
|
|
||||||
|
|
||||||
class BooleanEncoder(AbstractItemEncoder):
|
class BooleanEncoder(AbstractItemEncoder):
|
||||||
supportIndefLenMode = False
|
supportIndefLenMode = False
|
||||||
|
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
return value and (1,) or (0,), False, False
|
return value and (1,) or (0,), False, False
|
||||||
|
|
||||||
|
|
||||||
@ -121,7 +129,7 @@ class IntegerEncoder(AbstractItemEncoder):
|
|||||||
supportIndefLenMode = False
|
supportIndefLenMode = False
|
||||||
supportCompactZero = False
|
supportCompactZero = False
|
||||||
|
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
if value == 0:
|
if value == 0:
|
||||||
# de-facto way to encode zero
|
# de-facto way to encode zero
|
||||||
if self.supportCompactZero:
|
if self.supportCompactZero:
|
||||||
@ -133,7 +141,11 @@ class IntegerEncoder(AbstractItemEncoder):
|
|||||||
|
|
||||||
|
|
||||||
class BitStringEncoder(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)
|
valueLength = len(value)
|
||||||
if valueLength % 8:
|
if valueLength % 8:
|
||||||
alignedValue = value << (8 - valueLength % 8)
|
alignedValue = value << (8 - valueLength % 8)
|
||||||
@ -145,39 +157,79 @@ class BitStringEncoder(AbstractItemEncoder):
|
|||||||
substrate = alignedValue.asOctets()
|
substrate = alignedValue.asOctets()
|
||||||
return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True
|
return int2oct(len(substrate) * 8 - valueLength) + substrate, False, True
|
||||||
|
|
||||||
|
baseTag = value.tagSet.baseTag
|
||||||
|
|
||||||
# strip off explicit tags
|
# strip off explicit tags
|
||||||
alignedValue = alignedValue.clone(
|
if baseTag:
|
||||||
tagSet=tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
|
tagSet = tag.TagSet(baseTag, baseTag)
|
||||||
)
|
else:
|
||||||
|
tagSet = tag.TagSet()
|
||||||
|
|
||||||
|
alignedValue = alignedValue.clone(tagSet=tagSet)
|
||||||
|
|
||||||
stop = 0
|
stop = 0
|
||||||
substrate = null
|
substrate = null
|
||||||
while stop < valueLength:
|
while stop < valueLength:
|
||||||
start = stop
|
start = stop
|
||||||
stop = min(start + maxChunkSize * 8, valueLength)
|
stop = min(start + maxChunkSize * 8, valueLength)
|
||||||
substrate += encodeFun(alignedValue[start:stop], **options)
|
substrate += encodeFun(alignedValue[start:stop], asn1Spec, **options)
|
||||||
|
|
||||||
return substrate, True, True
|
return substrate, True, True
|
||||||
|
|
||||||
|
|
||||||
class OctetStringEncoder(AbstractItemEncoder):
|
class OctetStringEncoder(AbstractItemEncoder):
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
|
||||||
maxChunkSize = options.get('maxChunkSize', 0)
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
if not maxChunkSize or len(value) <= maxChunkSize:
|
|
||||||
return value.asOctets(), False, True
|
if asn1Spec is None:
|
||||||
|
substrate = value.asOctets()
|
||||||
|
|
||||||
|
elif not isOctetsType(value):
|
||||||
|
substrate = asn1Spec.clone(value).asOctets()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# will strip off explicit tags
|
substrate = value
|
||||||
baseTagSet = tag.TagSet(value.tagSet.baseTag, value.tagSet.baseTag)
|
|
||||||
|
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
|
pos = 0
|
||||||
substrate = null
|
substrate = null
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
chunk = value.clone(value[pos:pos + maxChunkSize],
|
chunk = value[pos:pos + maxChunkSize]
|
||||||
tagSet=baseTagSet)
|
|
||||||
if not chunk:
|
if not chunk:
|
||||||
break
|
break
|
||||||
substrate += encodeFun(chunk, **options)
|
|
||||||
|
substrate += encodeFun(chunk, asn1Spec, **options)
|
||||||
pos += maxChunkSize
|
pos += maxChunkSize
|
||||||
|
|
||||||
return substrate, True, True
|
return substrate, True, True
|
||||||
@ -186,14 +238,17 @@ class OctetStringEncoder(AbstractItemEncoder):
|
|||||||
class NullEncoder(AbstractItemEncoder):
|
class NullEncoder(AbstractItemEncoder):
|
||||||
supportIndefLenMode = False
|
supportIndefLenMode = False
|
||||||
|
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
return null, False, True
|
return null, False, True
|
||||||
|
|
||||||
|
|
||||||
class ObjectIdentifierEncoder(AbstractItemEncoder):
|
class ObjectIdentifierEncoder(AbstractItemEncoder):
|
||||||
supportIndefLenMode = False
|
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()
|
oid = value.asTuple()
|
||||||
|
|
||||||
# Build the first pair
|
# Build the first pair
|
||||||
@ -291,7 +346,10 @@ class RealEncoder(AbstractItemEncoder):
|
|||||||
encbase = encBase[i]
|
encbase = encBase[i]
|
||||||
return sign, m, encbase, e
|
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:
|
if value.isPlusInf:
|
||||||
return (0x40,), False, False
|
return (0x40,), False, False
|
||||||
if value.isMinusInf:
|
if value.isMinusInf:
|
||||||
@ -362,44 +420,116 @@ class RealEncoder(AbstractItemEncoder):
|
|||||||
|
|
||||||
|
|
||||||
class SequenceEncoder(AbstractItemEncoder):
|
class SequenceEncoder(AbstractItemEncoder):
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
omitEmptyOptionals = False
|
||||||
value.verifySizeSpec()
|
|
||||||
|
# TODO: handling three flavors of input is too much -- split over codecs
|
||||||
|
|
||||||
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
|
|
||||||
namedTypes = value.componentType
|
|
||||||
substrate = null
|
substrate = null
|
||||||
|
|
||||||
idx = len(value)
|
if asn1Spec is None:
|
||||||
while idx > 0:
|
# instance of ASN.1 schema
|
||||||
idx -= 1
|
value.verifySizeSpec()
|
||||||
if namedTypes:
|
|
||||||
if namedTypes[idx].isOptional and not value[idx].isValue:
|
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
|
continue
|
||||||
if namedTypes[idx].isDefaulted and value[idx] == namedTypes[idx].asn1Object:
|
|
||||||
|
if namedType.isDefaulted and component == namedType.asn1Object:
|
||||||
continue
|
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
|
return substrate, True, True
|
||||||
|
|
||||||
|
|
||||||
class SequenceOfEncoder(AbstractItemEncoder):
|
class SequenceOfEncoder(AbstractItemEncoder):
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
value.verifySizeSpec()
|
if asn1Spec is None:
|
||||||
|
value.verifySizeSpec()
|
||||||
|
else:
|
||||||
|
asn1Spec = asn1Spec.componentType
|
||||||
|
|
||||||
substrate = null
|
substrate = null
|
||||||
idx = len(value)
|
|
||||||
while idx > 0:
|
for idx, component in enumerate(value):
|
||||||
idx -= 1
|
substrate += encodeFun(value[idx], asn1Spec, **options)
|
||||||
substrate = encodeFun(value[idx], **options) + substrate
|
|
||||||
return substrate, True, True
|
return substrate, True, True
|
||||||
|
|
||||||
|
|
||||||
class ChoiceEncoder(AbstractItemEncoder):
|
class ChoiceEncoder(AbstractItemEncoder):
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
return encodeFun(value.getComponent(), **options), True, True
|
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):
|
class AnyEncoder(OctetStringEncoder):
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
return value.asOctets(), not options.get('defMode', True), True
|
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 = {
|
tagMap = {
|
||||||
@ -479,7 +609,16 @@ class Encoder(object):
|
|||||||
self.__tagMap = tagMap
|
self.__tagMap = tagMap
|
||||||
self.__typeMap = typeMap
|
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:
|
if debug.logger & debug.flagEncoder:
|
||||||
logger = debug.logger
|
logger = debug.logger
|
||||||
@ -487,7 +626,8 @@ class Encoder(object):
|
|||||||
logger = None
|
logger = None
|
||||||
|
|
||||||
if logger:
|
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:
|
if self.fixedDefLengthMode is not None:
|
||||||
options.update(defMode=self.fixedDefLengthMode)
|
options.update(defMode=self.fixedDefLengthMode)
|
||||||
@ -495,25 +635,32 @@ class Encoder(object):
|
|||||||
if self.fixedChunkSize is not None:
|
if self.fixedChunkSize is not None:
|
||||||
options.update(maxChunkSize=self.fixedChunkSize)
|
options.update(maxChunkSize=self.fixedChunkSize)
|
||||||
|
|
||||||
tagSet = value.tagSet
|
|
||||||
|
|
||||||
try:
|
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:
|
except KeyError:
|
||||||
|
if asn1Spec is None:
|
||||||
|
tagSet = value.tagSet
|
||||||
|
else:
|
||||||
|
tagSet = asn1Spec.tagSet
|
||||||
|
|
||||||
# use base type for codec lookup to recover untagged types
|
# 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:
|
try:
|
||||||
concreteEncoder = self.__tagMap[baseTagSet]
|
concreteEncoder = self.__tagMap[baseTagSet]
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise error.PyAsn1Error('No encoder for %s' % (value,))
|
raise error.PyAsn1Error('No encoder for %r (%s)' % (value, tagSet))
|
||||||
|
|
||||||
if logger:
|
if logger:
|
||||||
logger('using value codec %s chosen by %s' % (concreteEncoder.__class__.__name__, tagSet))
|
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:
|
if logger:
|
||||||
logger('codec %s built %s octets of substrate: %s\nencoder completed' % (concreteEncoder, len(substrate), debug.hexdump(substrate)))
|
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
|
#: Parameters
|
||||||
#: ----------
|
#: ----------
|
||||||
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||||
#: A pyasn1 object to encode
|
#: 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`
|
#: defMode: :py:class:`bool`
|
||||||
#: If `False`, produces indefinite length encoding
|
#: If `False`, produces indefinite length encoding
|
||||||
@ -543,6 +696,26 @@ class Encoder(object):
|
|||||||
#:
|
#:
|
||||||
#: Raises
|
#: Raises
|
||||||
#: ------
|
#: ------
|
||||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
#: :py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
#: On encoding errors
|
#: 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)
|
encode = Encoder(tagMap, typeMap)
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# 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):
|
class EndOfOctets(base.AbstractSimpleAsn1Item):
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from pyasn1.type import univ
|
from pyasn1 import error
|
||||||
from pyasn1.codec.ber import decoder
|
from pyasn1.codec.ber import decoder
|
||||||
from pyasn1.compat.octets import oct2int
|
from pyasn1.compat.octets import oct2int
|
||||||
from pyasn1 import error
|
from pyasn1.type import univ
|
||||||
|
|
||||||
__all__ = ['decode']
|
__all__ = ['decode']
|
||||||
|
|
||||||
@ -25,14 +25,14 @@ class BooleanDecoder(decoder.AbstractSimpleDecoder):
|
|||||||
byte = oct2int(head[0])
|
byte = oct2int(head[0])
|
||||||
# CER/DER specifies encoding of TRUE as 0xFF and FALSE as 0x0, while
|
# 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
|
# 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:
|
if byte == 0xff:
|
||||||
value = 1
|
value = 1
|
||||||
elif byte == 0x00:
|
elif byte == 0x00:
|
||||||
value = 0
|
value = 0
|
||||||
else:
|
else:
|
||||||
raise error.PyAsn1Error('Unexpected Boolean payload: %s' % byte)
|
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
|
# TODO: prohibit non-canonical encoding
|
||||||
BitStringDecoder = decoder.BitStringDecoder
|
BitStringDecoder = decoder.BitStringDecoder
|
||||||
@ -63,15 +63,17 @@ class Decoder(decoder.Decoder):
|
|||||||
|
|
||||||
#: Turns CER octet stream into an ASN.1 object.
|
#: 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
|
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
|
||||||
#: may be a scalar or an arbitrary nested structure.
|
#: may be a scalar or an arbitrary nested structure.
|
||||||
#:
|
#:
|
||||||
#: Parameters
|
#: Parameters
|
||||||
#: ----------
|
#: ----------
|
||||||
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
#: 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
|
#: 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
|
#: 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
|
#: being decoded, *asn1Spec* may or may not be required. Most common reason for
|
||||||
@ -85,6 +87,28 @@ class Decoder(decoder.Decoder):
|
|||||||
#:
|
#:
|
||||||
#: Raises
|
#: Raises
|
||||||
#: ------
|
#: ------
|
||||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
#: :py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
#: On decoding errors
|
#: 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)
|
decode = Decoder(tagMap, decoder.typeMap)
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from pyasn1.type import univ
|
from pyasn1 import error
|
||||||
from pyasn1.type import useful
|
|
||||||
from pyasn1.codec.ber import encoder
|
from pyasn1.codec.ber import encoder
|
||||||
from pyasn1.compat.octets import str2octs, null
|
from pyasn1.compat.octets import str2octs, null
|
||||||
from pyasn1 import error
|
from pyasn1.type import univ
|
||||||
|
from pyasn1.type import useful
|
||||||
|
|
||||||
__all__ = ['encode']
|
__all__ = ['encode']
|
||||||
|
|
||||||
|
|
||||||
class BooleanEncoder(encoder.IntegerEncoder):
|
class BooleanEncoder(encoder.IntegerEncoder):
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
if value == 0:
|
if value == 0:
|
||||||
substrate = (0,)
|
substrate = (0,)
|
||||||
else:
|
else:
|
||||||
@ -38,7 +38,7 @@ class TimeEncoderMixIn(object):
|
|||||||
minLength = 12
|
minLength = 12
|
||||||
maxLength = 19
|
maxLength = 19
|
||||||
|
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
# Encoding constraints:
|
# Encoding constraints:
|
||||||
# - minutes are mandatory, seconds are optional
|
# - minutes are mandatory, seconds are optional
|
||||||
# - subseconds must NOT be zero
|
# - subseconds must NOT be zero
|
||||||
@ -46,6 +46,9 @@ class TimeEncoderMixIn(object):
|
|||||||
# - time in UTC (Z)
|
# - time in UTC (Z)
|
||||||
# - only dot is allowed for fractions
|
# - only dot is allowed for fractions
|
||||||
|
|
||||||
|
if asn1Spec is not None:
|
||||||
|
value = asn1Spec.clone(value)
|
||||||
|
|
||||||
octets = value.asOctets()
|
octets = value.asOctets()
|
||||||
|
|
||||||
if not self.minLength < len(octets) < self.maxLength:
|
if not self.minLength < len(octets) < self.maxLength:
|
||||||
@ -63,7 +66,7 @@ class TimeEncoderMixIn(object):
|
|||||||
options.update(maxChunkSize=1000)
|
options.update(maxChunkSize=1000)
|
||||||
|
|
||||||
return encoder.OctetStringEncoder.encodeValue(
|
return encoder.OctetStringEncoder.encodeValue(
|
||||||
self, value, encodeFun, **options
|
self, value, asn1Spec, encodeFun, **options
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -77,88 +80,140 @@ class UTCTimeEncoder(TimeEncoderMixIn, encoder.OctetStringEncoder):
|
|||||||
maxLength = 14
|
maxLength = 14
|
||||||
|
|
||||||
|
|
||||||
class SetOfEncoder(encoder.SequenceOfEncoder):
|
class SetEncoder(encoder.SequenceEncoder):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sortComponents(components):
|
def _componentSortKey(componentAndType):
|
||||||
# sort by tags regardless of the Choice value (static sort)
|
"""Sort SET components by tag
|
||||||
return sorted(components, key=lambda x: isinstance(x, univ.Choice) and x.minTagSet or x.tagSet)
|
|
||||||
|
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
Sort regardless of the Choice value (static sort)
|
||||||
value.verifySizeSpec()
|
"""
|
||||||
substrate = null
|
component, asn1Spec = componentAndType
|
||||||
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
|
|
||||||
|
|
||||||
comps.append(value[idx])
|
if asn1Spec is None:
|
||||||
compsMap[id(value[idx])] = namedTypes and namedTypes[idx].isOptional
|
asn1Spec = component
|
||||||
|
|
||||||
for comp in self._sortComponents(comps):
|
if asn1Spec.typeId == univ.Choice.typeId and not asn1Spec.tagSet:
|
||||||
options.update(ifNotEmpty=compsMap[id(comp)])
|
if asn1Spec.tagSet:
|
||||||
substrate += encodeFun(comp, **options)
|
return asn1Spec.tagSet
|
||||||
|
else:
|
||||||
|
return asn1Spec.componentType.minTagSet
|
||||||
else:
|
else:
|
||||||
components = [encodeFun(x, **options) for x in value]
|
return asn1Spec.tagSet
|
||||||
|
|
||||||
# sort by serialized and padded components
|
def encodeValue(self, value, asn1Spec, encodeFun, **options):
|
||||||
if len(components) > 1:
|
|
||||||
zero = str2octs('\x00')
|
substrate = null
|
||||||
maxLen = max(map(len, components))
|
|
||||||
paddedComponents = [
|
comps = []
|
||||||
(x.ljust(maxLen, zero), x) for x in components
|
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
|
return substrate, True, True
|
||||||
|
|
||||||
|
|
||||||
class SequenceEncoder(encoder.SequenceEncoder):
|
class SequenceEncoder(encoder.SequenceEncoder):
|
||||||
def encodeValue(self, value, encodeFun, **options):
|
omitEmptyOptionals = True
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class SequenceOfEncoder(encoder.SequenceOfEncoder):
|
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
|
substrate = null
|
||||||
idx = len(value)
|
|
||||||
|
|
||||||
if options.get('ifNotEmpty', False) and not idx:
|
for idx, component in enumerate(value):
|
||||||
return substrate, True, True
|
substrate += encodeFun(value[idx], asn1Spec, **options)
|
||||||
|
|
||||||
value.verifySizeSpec()
|
|
||||||
while idx > 0:
|
|
||||||
idx -= 1
|
|
||||||
substrate = encodeFun(value[idx], **options) + substrate
|
|
||||||
return substrate, True, True
|
return substrate, True, True
|
||||||
|
|
||||||
|
|
||||||
@ -180,7 +235,7 @@ typeMap.update({
|
|||||||
useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(),
|
useful.GeneralizedTime.typeId: GeneralizedTimeEncoder(),
|
||||||
useful.UTCTime.typeId: UTCTimeEncoder(),
|
useful.UTCTime.typeId: UTCTimeEncoder(),
|
||||||
# Sequence & Set have same tags as SequenceOf & SetOf
|
# Sequence & Set have same tags as SequenceOf & SetOf
|
||||||
univ.Set.typeId: SetOfEncoder(),
|
univ.Set.typeId: SetEncoder(),
|
||||||
univ.SetOf.typeId: SetOfEncoder(),
|
univ.SetOf.typeId: SetOfEncoder(),
|
||||||
univ.Sequence.typeId: SequenceEncoder(),
|
univ.Sequence.typeId: SequenceEncoder(),
|
||||||
univ.SequenceOf.typeId: SequenceOfEncoder()
|
univ.SequenceOf.typeId: SequenceOfEncoder()
|
||||||
@ -198,24 +253,44 @@ class Encoder(encoder.Encoder):
|
|||||||
#:
|
#:
|
||||||
#: Parameters
|
#: Parameters
|
||||||
#: ----------
|
#: ----------
|
||||||
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||||
#: A pyasn1 object to encode
|
#: 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`
|
#: Keyword Args
|
||||||
#: If `False`, produces indefinite length encoding
|
#: ------------
|
||||||
#:
|
#: asn1Spec:
|
||||||
#: maxChunkSize: :py:class:`int`
|
#: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
|
||||||
#: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
|
|
||||||
#:
|
#:
|
||||||
#: Returns
|
#: Returns
|
||||||
#: -------
|
#: -------
|
||||||
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
#: : :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
|
#: Raises
|
||||||
#: ------
|
#: ------
|
||||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
#: :py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
#: On encoding errors
|
#: 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)
|
encode = Encoder(tagMap, typeMap)
|
||||||
|
|
||||||
# EncoderFactory queries class instance and builds a map of tags -> encoders
|
# EncoderFactory queries class instance and builds a map of tags -> encoders
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from pyasn1.type import univ
|
|
||||||
from pyasn1.codec.cer import decoder
|
from pyasn1.codec.cer import decoder
|
||||||
|
from pyasn1.type import univ
|
||||||
|
|
||||||
__all__ = ['decode']
|
__all__ = ['decode']
|
||||||
|
|
||||||
@ -43,15 +43,17 @@ class Decoder(decoder.Decoder):
|
|||||||
|
|
||||||
#: Turns DER octet stream into an ASN.1 object.
|
#: 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
|
#: (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative) which
|
||||||
#: may be a scalar or an arbitrary nested structure.
|
#: may be a scalar or an arbitrary nested structure.
|
||||||
#:
|
#:
|
||||||
#: Parameters
|
#: Parameters
|
||||||
#: ----------
|
#: ----------
|
||||||
#: substrate: :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
#: 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
|
#: 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
|
#: 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
|
#: being decoded, *asn1Spec* may or may not be required. Most common reason for
|
||||||
@ -65,6 +67,28 @@ class Decoder(decoder.Decoder):
|
|||||||
#:
|
#:
|
||||||
#: Raises
|
#: Raises
|
||||||
#: ------
|
#: ------
|
||||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
#: :py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
#: On decoding errors
|
#: 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)
|
decode = Decoder(tagMap, typeMap)
|
||||||
|
@ -1,32 +1,57 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from pyasn1.type import univ
|
from pyasn1 import error
|
||||||
from pyasn1.codec.cer import encoder
|
from pyasn1.codec.cer import encoder
|
||||||
|
from pyasn1.type import univ
|
||||||
|
|
||||||
__all__ = ['encode']
|
__all__ = ['encode']
|
||||||
|
|
||||||
|
|
||||||
class SetOfEncoder(encoder.SetOfEncoder):
|
class SetEncoder(encoder.SetEncoder):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _sortComponents(components):
|
def _componentSortKey(componentAndType):
|
||||||
# sort by tags depending on the actual Choice value (dynamic sort)
|
"""Sort SET components by tag
|
||||||
return sorted(components, key=lambda x: isinstance(x, univ.Choice) and x.getComponent().tagSet or x.tagSet)
|
|
||||||
|
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 = encoder.tagMap.copy()
|
||||||
tagMap.update({
|
tagMap.update({
|
||||||
# Set & SetOf have same tags
|
# Set & SetOf have same tags
|
||||||
univ.SetOf.tagSet: SetOfEncoder()
|
univ.Set.tagSet: SetEncoder()
|
||||||
})
|
})
|
||||||
|
|
||||||
typeMap = encoder.typeMap.copy()
|
typeMap = encoder.typeMap.copy()
|
||||||
typeMap.update({
|
typeMap.update({
|
||||||
# Set & SetOf have same tags
|
# Set & SetOf have same tags
|
||||||
univ.Set.typeId: SetOfEncoder(),
|
univ.Set.typeId: SetEncoder()
|
||||||
univ.SetOf.typeId: SetOfEncoder()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -41,22 +66,42 @@ class Encoder(encoder.Encoder):
|
|||||||
#:
|
#:
|
||||||
#: Parameters
|
#: Parameters
|
||||||
#: ----------
|
#: ----------
|
||||||
# value: any pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
#: value: either a Python or pyasn1 object (e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative)
|
||||||
#: A pyasn1 object to encode
|
#: 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`
|
#: Keyword Args
|
||||||
#: If `False`, produces indefinite length encoding
|
#: ------------
|
||||||
#:
|
#: asn1Spec:
|
||||||
#: maxChunkSize: :py:class:`int`
|
#: Optional ASN.1 schema or value object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
|
||||||
#: Maximum chunk size in chunked encoding mode (0 denotes unlimited chunk size)
|
|
||||||
#:
|
#:
|
||||||
#: Returns
|
#: Returns
|
||||||
#: -------
|
#: -------
|
||||||
#: : :py:class:`bytes` (Python 3) or :py:class:`str` (Python 2)
|
#: : :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
|
#: Raises
|
||||||
#: ------
|
#: ------
|
||||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
#: :py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
#: On encoding errors
|
#: 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)
|
encode = Encoder(tagMap, typeMap)
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from pyasn1.type import base, univ, char, useful, tag
|
from pyasn1 import debug
|
||||||
from pyasn1 import debug, error
|
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']
|
__all__ = ['decode']
|
||||||
|
|
||||||
@ -177,6 +182,8 @@ class Decoder(object):
|
|||||||
#: pyObject: :py:class:`object`
|
#: pyObject: :py:class:`object`
|
||||||
#: A scalar or nested Python objects
|
#: A scalar or nested Python objects
|
||||||
#:
|
#:
|
||||||
|
#: Keyword Args
|
||||||
|
#: ------------
|
||||||
#: asn1Spec: any pyasn1 type object e.g. :py:class:`~pyasn1.type.base.PyAsn1Item` derivative
|
#: 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
|
#: 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
|
#: for successful interpretation of Python objects mapping into their ASN.1
|
||||||
@ -189,6 +196,19 @@ class Decoder(object):
|
|||||||
#:
|
#:
|
||||||
#: Raises
|
#: Raises
|
||||||
#: ------
|
#: ------
|
||||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
#: :py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
#: On decoding errors
|
#: 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)
|
decode = Decoder(tagMap, typeMap)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
try:
|
try:
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
@ -10,8 +10,13 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
OrderedDict = dict
|
OrderedDict = dict
|
||||||
|
|
||||||
from pyasn1.type import base, univ, tag, char, useful
|
from pyasn1 import debug
|
||||||
from pyasn1 import debug, error
|
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']
|
__all__ = ['encode']
|
||||||
|
|
||||||
@ -43,7 +48,7 @@ class OctetStringEncoder(AbstractItemEncoder):
|
|||||||
|
|
||||||
class TextStringEncoder(AbstractItemEncoder):
|
class TextStringEncoder(AbstractItemEncoder):
|
||||||
def encode(self, value, encodeFun, **options):
|
def encode(self, value, encodeFun, **options):
|
||||||
return value.prettyPrint()
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
class NullEncoder(AbstractItemEncoder):
|
class NullEncoder(AbstractItemEncoder):
|
||||||
@ -207,6 +212,18 @@ class Encoder(object):
|
|||||||
#:
|
#:
|
||||||
#: Raises
|
#: Raises
|
||||||
#: ------
|
#: ------
|
||||||
#: : :py:class:`pyasn1.error.PyAsn1Error`
|
#: :py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
#: On encoding errors
|
#: 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)
|
encode = Encoder(tagMap, typeMap)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from sys import version_info
|
from sys import version_info
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from sys import version_info
|
from sys import version_info
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from sys import version_info
|
|
||||||
from datetime import datetime
|
|
||||||
import time
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from sys import version_info
|
||||||
|
|
||||||
__all__ = ['strptime']
|
__all__ = ['strptime']
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
implementation = platform.python_implementation()
|
implementation = platform.python_implementation()
|
||||||
|
|
||||||
except (ImportError, AttributeError):
|
except (ImportError, AttributeError):
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from sys import version_info
|
from sys import version_info
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from sys import version_info
|
from sys import version_info
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
import logging
|
import logging
|
||||||
from pyasn1.compat.octets import octs2ints
|
|
||||||
from pyasn1 import error
|
|
||||||
from pyasn1 import __version__
|
from pyasn1 import __version__
|
||||||
|
from pyasn1 import error
|
||||||
|
from pyasn1.compat.octets import octs2ints
|
||||||
|
|
||||||
__all__ = ['Debug', 'setLogger', 'hexdump']
|
__all__ = ['Debug', 'setLogger', 'hexdump']
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ flagDecoder = 0x0002
|
|||||||
flagAll = 0xffff
|
flagAll = 0xffff
|
||||||
|
|
||||||
flagMap = {
|
flagMap = {
|
||||||
|
'none': flagNone,
|
||||||
'encoder': flagEncoder,
|
'encoder': flagEncoder,
|
||||||
'decoder': flagDecoder,
|
'decoder': flagDecoder,
|
||||||
'all': flagAll
|
'all': flagAll
|
||||||
|
@ -1,18 +1,29 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
class PyAsn1Error(Exception):
|
class PyAsn1Error(Exception):
|
||||||
pass
|
"""Create pyasn1 exception object
|
||||||
|
|
||||||
|
The `PyAsn1Error` exception represents generic, usually fatal, error.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ValueConstraintError(PyAsn1Error):
|
class ValueConstraintError(PyAsn1Error):
|
||||||
pass
|
"""Create pyasn1 exception object
|
||||||
|
|
||||||
|
The `ValueConstraintError` exception indicates an ASN.1 value
|
||||||
|
constraint violation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class SubstrateUnderrunError(PyAsn1Error):
|
class SubstrateUnderrunError(PyAsn1Error):
|
||||||
pass
|
"""Create pyasn1 exception object
|
||||||
|
|
||||||
|
The `SubstrateUnderrunError` exception indicates insufficient serialised
|
||||||
|
data on input of a deserialisation routine.
|
||||||
|
"""
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
import sys
|
import sys
|
||||||
from pyasn1.type import constraint, tagmap, tag
|
|
||||||
from pyasn1.compat import calling
|
|
||||||
from pyasn1 import error
|
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']
|
__all__ = ['Asn1Item', 'Asn1ItemBase', 'AbstractSimpleAsn1Item', 'AbstractConstructedAsn1Item']
|
||||||
|
|
||||||
@ -52,6 +55,9 @@ class Asn1ItemBase(Asn1Item):
|
|||||||
|
|
||||||
self.__dict__[name] = value
|
self.__dict__[name] = value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.prettyPrint()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def readOnly(self):
|
def readOnly(self):
|
||||||
return self._readOnly
|
return self._readOnly
|
||||||
@ -75,7 +81,7 @@ class Asn1ItemBase(Asn1Item):
|
|||||||
(:py:mod:`~pyasn1.type.constraint`) are examined when carrying
|
(:py:mod:`~pyasn1.type.constraint`) are examined when carrying
|
||||||
out ASN.1 types comparison.
|
out ASN.1 types comparison.
|
||||||
|
|
||||||
No Python inheritance relationship between PyASN1 objects is considered.
|
Python class inheritance relationship is NOT considered.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
@ -94,18 +100,17 @@ class Asn1ItemBase(Asn1Item):
|
|||||||
|
|
||||||
def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
|
def isSuperTypeOf(self, other, matchTags=True, matchConstraints=True):
|
||||||
"""Examine |ASN.1| type for subtype relationship with other ASN.1 type.
|
"""Examine |ASN.1| type for subtype relationship with other ASN.1 type.
|
||||||
|
|
||||||
ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
|
ASN.1 tags (:py:mod:`~pyasn1.type.tag`) and constraints
|
||||||
(:py:mod:`~pyasn1.type.constraint`) are examined when carrying
|
(:py:mod:`~pyasn1.type.constraint`) are examined when carrying
|
||||||
out ASN.1 types comparison.
|
out ASN.1 types comparison.
|
||||||
|
|
||||||
No Python inheritance relationship between PyASN1 objects is considered.
|
Python class inheritance relationship is NOT considered.
|
||||||
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
other: a pyasn1 type object
|
other: a pyasn1 type object
|
||||||
Class instance representing ASN.1 type.
|
Class instance representing ASN.1 type.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
@ -120,10 +125,13 @@ class Asn1ItemBase(Asn1Item):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def isNoValue(*values):
|
def isNoValue(*values):
|
||||||
for value in values:
|
for value in values:
|
||||||
if value is not None and value is not noValue:
|
if value is not noValue:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def prettyPrint(self, scope=0):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
# backward compatibility
|
# backward compatibility
|
||||||
|
|
||||||
def getTagSet(self):
|
def getTagSet(self):
|
||||||
@ -145,15 +153,42 @@ class Asn1ItemBase(Asn1Item):
|
|||||||
class NoValue(object):
|
class NoValue(object):
|
||||||
"""Create a singleton instance of NoValue class.
|
"""Create a singleton instance of NoValue class.
|
||||||
|
|
||||||
NoValue object can be used as an initializer on PyASN1 type class
|
The *NoValue* sentinel object represents an instance of ASN.1 schema
|
||||||
instantiation to represent ASN.1 type rather than ASN.1 data value.
|
object as opposed to ASN.1 value object.
|
||||||
|
|
||||||
No operations other than type comparison can be performed on
|
Only ASN.1 schema-related operations can be performed on ASN.1
|
||||||
a PyASN1 type object.
|
schema objects.
|
||||||
|
|
||||||
|
Warning
|
||||||
|
-------
|
||||||
|
Any operation attempted on the *noValue* object will raise the
|
||||||
|
*PyAsn1Error* exception.
|
||||||
"""
|
"""
|
||||||
skipMethods = ('__getattribute__', '__getattr__', '__setattr__', '__delattr__',
|
skipMethods = set(
|
||||||
'__class__', '__init__', '__del__', '__new__', '__repr__',
|
('__slots__',
|
||||||
'__qualname__', '__objclass__', 'im_class', '__sizeof__')
|
# 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
|
_instance = None
|
||||||
|
|
||||||
@ -161,7 +196,7 @@ class NoValue(object):
|
|||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
def getPlug(name):
|
def getPlug(name):
|
||||||
def plug(self, *args, **kw):
|
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
|
return plug
|
||||||
|
|
||||||
op_names = [name
|
op_names = [name
|
||||||
@ -181,11 +216,13 @@ class NoValue(object):
|
|||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
if attr in self.skipMethods:
|
if attr in self.skipMethods:
|
||||||
raise AttributeError('attribute %s not present' % attr)
|
raise AttributeError('Attribute %s not present' % attr)
|
||||||
raise error.PyAsn1Error('No value for "%s"' % attr)
|
|
||||||
|
raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % attr)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s()' % self.__class__.__name__
|
return '<%s object at 0x%x>' % (self.__class__.__name__, id(self))
|
||||||
|
|
||||||
|
|
||||||
noValue = NoValue()
|
noValue = NoValue()
|
||||||
|
|
||||||
@ -197,7 +234,7 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
|
|||||||
|
|
||||||
def __init__(self, value=noValue, **kwargs):
|
def __init__(self, value=noValue, **kwargs):
|
||||||
Asn1ItemBase.__init__(self, **kwargs)
|
Asn1ItemBase.__init__(self, **kwargs)
|
||||||
if value is noValue or value is None:
|
if value is noValue:
|
||||||
value = self.defaultValue
|
value = self.defaultValue
|
||||||
else:
|
else:
|
||||||
value = self.prettyIn(value)
|
value = self.prettyIn(value)
|
||||||
@ -211,17 +248,21 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
|
|||||||
self._value = value
|
self._value = value
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
representation = []
|
representation = '%s %s object at 0x%x' % (
|
||||||
if self._value is not self.defaultValue:
|
self.__class__.__name__, self.isValue and 'value' or 'schema', id(self)
|
||||||
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))
|
|
||||||
|
|
||||||
def __str__(self):
|
for attr, value in self.readOnly.items():
|
||||||
return str(self._value)
|
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):
|
def __eq__(self, other):
|
||||||
return self is other and True or self._value == other
|
return self is other and True or self._value == other
|
||||||
@ -253,53 +294,50 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def isValue(self):
|
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
|
If *isValue* is `False` then this object represents just ASN.1 schema.
|
||||||
initialized.
|
|
||||||
|
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
|
Returns
|
||||||
-------
|
-------
|
||||||
: :class:`bool`
|
: :class:`bool`
|
||||||
:class:`True` if object represents ASN.1 value and type,
|
:class:`False` if object represents just ASN.1 schema.
|
||||||
:class:`False` if object represents just ASN.1 type.
|
:class:`True` if object represents ASN.1 schema and can be used as a normal value.
|
||||||
|
|
||||||
Note
|
Note
|
||||||
----
|
----
|
||||||
There is an important distinction between PyASN1 type and value objects.
|
There is an important distinction between PyASN1 schema and value objects.
|
||||||
The PyASN1 type objects can only participate in ASN.1 type
|
The PyASN1 schema objects can only participate in ASN.1 schema-related
|
||||||
operations (subtyping, comparison etc) and serve as a
|
operations (e.g. defining or testing the structure of the data). Most
|
||||||
blueprint for serialization codecs to resolve ambiguous types.
|
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
|
The PyASN1 value objects can **additionally** participate in many operations
|
||||||
of built-in Python operations.
|
involving regular Python objects (e.g. arithmetic, comprehension etc).
|
||||||
"""
|
"""
|
||||||
return self._value is not noValue
|
return self._value is not noValue
|
||||||
|
|
||||||
def clone(self, value=noValue, **kwargs):
|
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
|
The `clone()` method accepts the same set arguments as |ASN.1|
|
||||||
properties of the |ASN.1| object.
|
class takes on instantiation except that all arguments
|
||||||
|
of the `clone()` method are optional.
|
||||||
|
|
||||||
Parameters
|
Whatever arguments are supplied, they are used to create a copy
|
||||||
----------
|
of `self` taking precedence over the ones used to instantiate `self`.
|
||||||
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.
|
|
||||||
|
|
||||||
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
|
Note
|
||||||
Object representing ASN.1 tag(s) to use in new object instead of inheriting from the caller
|
----
|
||||||
|
Due to the immutable nature of the |ASN.1| object, if no arguments
|
||||||
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
are supplied, no new |ASN.1| object will be created and `self` will
|
||||||
Object representing ASN.1 subtype constraint(s) to use in new object instead of inheriting from the caller
|
be returned instead.
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
:
|
|
||||||
new instance of |ASN.1| type/value
|
|
||||||
"""
|
"""
|
||||||
if value is noValue or value is None:
|
if value is noValue:
|
||||||
if not kwargs:
|
if not kwargs:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -311,37 +349,53 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
|
|||||||
return self.__class__(value, **initilaizers)
|
return self.__class__(value, **initilaizers)
|
||||||
|
|
||||||
def subtype(self, value=noValue, **kwargs):
|
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
|
The subtype relationship between ASN.1 types has no correlation with
|
||||||
properties of the |ASN.1| object.
|
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
|
The `subtype()` method accepts the same set arguments as |ASN.1|
|
||||||
----------
|
class takes on instantiation except that all parameters
|
||||||
value: :class:`tuple`, :class:`str` or |ASN.1| object
|
of the `subtype()` method are optional.
|
||||||
Initialization value to pass to new ASN.1 object instead of
|
|
||||||
inheriting one from the caller.
|
|
||||||
|
|
||||||
implicitTag: :py:class:`~pyasn1.type.tag.Tag`
|
With the exception of the arguments described below, the rest of
|
||||||
Implicitly apply given ASN.1 tag object to caller's
|
supplied arguments they are used to create a copy of `self` taking
|
||||||
:py:class:`~pyasn1.type.tag.TagSet`, then use the result as
|
precedence over the ones used to instantiate `self`.
|
||||||
new object's ASN.1 tag(s).
|
|
||||||
|
|
||||||
explicitTag: :py:class:`~pyasn1.type.tag.Tag`
|
The following arguments to `subtype()` create a ASN.1 subtype out of
|
||||||
Explicitly apply given ASN.1 tag object to caller's
|
|ASN.1| type:
|
||||||
: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`
|
Other Parameters
|
||||||
Add ASN.1 constraints object to one of the caller, then
|
----------------
|
||||||
use the result as new object's ASN.1 constraints.
|
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
|
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 instance of |ASN.1| type/value
|
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:
|
if not kwargs:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -369,21 +423,7 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
|
|||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
def prettyPrint(self, scope=0):
|
def prettyPrint(self, scope=0):
|
||||||
"""Provide human-friendly printable object representation.
|
return self.prettyOut(self._value)
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
def prettyPrintType(self, scope=0):
|
def prettyPrintType(self, scope=0):
|
||||||
@ -408,22 +448,6 @@ class AbstractSimpleAsn1Item(Asn1ItemBase):
|
|||||||
# of types for Sequence/Set/Choice.
|
# 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):
|
class AbstractConstructedAsn1Item(Asn1ItemBase):
|
||||||
|
|
||||||
@ -446,20 +470,18 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
|
|||||||
self._componentValues = []
|
self._componentValues = []
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
representation = []
|
representation = '%s %s object at 0x%x' % (
|
||||||
if self.componentType is not self.__class__.componentType:
|
self.__class__.__name__, self.isValue and 'value' or 'schema', id(self)
|
||||||
representation.append('componentType=%r' % (self.componentType,))
|
)
|
||||||
if self.tagSet is not self.__class__.tagSet:
|
|
||||||
representation.append('tagSet=%r' % (self.tagSet,))
|
for attr, value in self.readOnly.items():
|
||||||
if self.subtypeSpec is not self.__class__.subtypeSpec:
|
if value is not noValue:
|
||||||
representation.append('subtypeSpec=%r' % (self.subtypeSpec,))
|
representation += ' %s=%r' % (attr, value)
|
||||||
representation = '%s(%s)' % (self.__class__.__name__, ', '.join(representation))
|
|
||||||
if self._componentValues:
|
if self.isValue and self._componentValues:
|
||||||
for idx, component in enumerate(self._componentValues):
|
representation += ' payload [%s]' % ', '.join([repr(x) for x in self._componentValues])
|
||||||
if component is None or component is noValue:
|
|
||||||
continue
|
return '<%s>' % representation
|
||||||
representation += '.setComponentByPosition(%d, %s)' % (idx, repr(component))
|
|
||||||
return representation
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self is other and True or self._componentValues == other
|
return self is other and True or self._componentValues == other
|
||||||
@ -486,31 +508,35 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
|
|||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
return self._componentValues and True or False
|
return self._componentValues and True or False
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._componentValues)
|
||||||
|
|
||||||
def _cloneComponentValues(self, myClone, cloneValueFlag):
|
def _cloneComponentValues(self, myClone, cloneValueFlag):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def clone(self, **kwargs):
|
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
|
The `clone()` method accepts the same set arguments as |ASN.1|
|
||||||
properties of the |ASN.1| object.
|
class takes on instantiation except that all arguments
|
||||||
|
of the `clone()` method are optional.
|
||||||
|
|
||||||
Parameters
|
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 non-default ASN.1 tag(s)
|
|
||||||
|
|
||||||
subtypeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
Possible values of `self` are never copied over thus `clone()` can
|
||||||
Object representing non-default ASN.1 subtype constraint(s)
|
only create a new schema object.
|
||||||
|
|
||||||
sizeSpec: :py:class:`~pyasn1.type.constraint.ConstraintsIntersection`
|
|
||||||
Object representing non-default ASN.1 size constraint(s)
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
:
|
:
|
||||||
new instance of |ASN.1| type/value
|
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)
|
cloneValueFlag = kwargs.pop('cloneValueFlag', False)
|
||||||
|
|
||||||
@ -525,27 +551,46 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
|
|||||||
return clone
|
return clone
|
||||||
|
|
||||||
def subtype(self, **kwargs):
|
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
|
The `subtype()` method accepts the same set arguments as |ASN.1|
|
||||||
properties of the |ASN.1| object.
|
class takes on instantiation except that all parameters
|
||||||
|
of the `subtype()` method are optional.
|
||||||
|
|
||||||
Parameters
|
With the exception of the arguments described below, the rest of
|
||||||
----------
|
supplied arguments they are used to create a copy of `self` taking
|
||||||
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
|
precedence over the ones used to instantiate `self`.
|
||||||
Object representing non-default ASN.1 tag(s)
|
|
||||||
|
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`
|
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
|
Returns
|
||||||
-------
|
-------
|
||||||
:
|
:
|
||||||
new instance of |ASN.1| type/value
|
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()
|
initializers = self.readOnly.copy()
|
||||||
@ -586,9 +631,6 @@ class AbstractConstructedAsn1Item(Asn1ItemBase):
|
|||||||
self[k] = kwargs[k]
|
self[k] = kwargs[k]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self._componentValues)
|
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self._componentValues = []
|
self._componentValues = []
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
import sys
|
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',
|
__all__ = ['NumericString', 'PrintableString', 'TeletexString', 'T61String', 'VideotexString',
|
||||||
'IA5String', 'GraphicString', 'VisibleString', 'ISO646String',
|
'IA5String', 'GraphicString', 'VisibleString', 'ISO646String',
|
||||||
@ -18,16 +19,16 @@ noValue = univ.noValue
|
|||||||
|
|
||||||
|
|
||||||
class AbstractCharacterString(univ.OctetString):
|
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`.
|
|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.
|
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
|
value: :class:`unicode`, :class:`str`, :class:`bytes` or |ASN.1| object
|
||||||
unicode object (Python 2) or string (Python 3), alternatively string
|
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.
|
unicode string (note `encoding` parameter) or |ASN.1| class instance.
|
||||||
|
|
||||||
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
|
tagSet: :py:class:`~pyasn1.type.tag.TagSet`
|
||||||
@ -43,14 +44,16 @@ class AbstractCharacterString(univ.OctetString):
|
|||||||
|
|
||||||
Raises
|
Raises
|
||||||
------
|
------
|
||||||
: :py:class:`pyasn1.error.PyAsn1Error`
|
:py:class:`~pyasn1.error.PyAsn1Error`
|
||||||
On constraint violation or bad initializer.
|
On constraint violation or bad initializer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if sys.version_info[0] <= 2:
|
if sys.version_info[0] <= 2:
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
try:
|
try:
|
||||||
|
# `str` is Py2 text representation
|
||||||
return self._value.encode(self.encoding)
|
return self._value.encode(self.encoding)
|
||||||
|
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
raise error.PyAsn1Error(
|
raise error.PyAsn1Error(
|
||||||
"Can't encode string '%s' with codec %s" % (self._value, self.encoding)
|
"Can't encode string '%s' with codec %s" % (self._value, self.encoding)
|
||||||
@ -85,6 +88,7 @@ class AbstractCharacterString(univ.OctetString):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
# `unicode` is Py3 text representation
|
||||||
return str(self._value)
|
return str(self._value)
|
||||||
|
|
||||||
def __bytes__(self):
|
def __bytes__(self):
|
||||||
@ -119,82 +123,25 @@ class AbstractCharacterString(univ.OctetString):
|
|||||||
def asNumbers(self, padding=True):
|
def asNumbers(self, padding=True):
|
||||||
return tuple(bytes(self))
|
return tuple(bytes(self))
|
||||||
|
|
||||||
|
#
|
||||||
|
# See OctetString.prettyPrint() for the explanation
|
||||||
|
#
|
||||||
|
|
||||||
def prettyOut(self, value):
|
def prettyOut(self, value):
|
||||||
return 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):
|
def __reversed__(self):
|
||||||
return reversed(self._value)
|
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):
|
class NumericString(AbstractCharacterString):
|
||||||
__doc__ = AbstractCharacterString.__doc__
|
__doc__ = AbstractCharacterString.__doc__
|
||||||
|
@ -1,26 +1,23 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# Original concept and code by Mike C. Fletcher.
|
# Original concept and code by Mike C. Fletcher.
|
||||||
#
|
#
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pyasn1.type import error
|
from pyasn1.type import error
|
||||||
|
|
||||||
__all__ = ['SingleValueConstraint', 'ContainedSubtypeConstraint', 'ValueRangeConstraint',
|
__all__ = ['SingleValueConstraint', 'ContainedSubtypeConstraint',
|
||||||
'ValueSizeConstraint', 'PermittedAlphabetConstraint', 'InnerTypeConstraint',
|
'ValueRangeConstraint', 'ValueSizeConstraint',
|
||||||
'ConstraintsExclusion', 'ConstraintsIntersection', 'ConstraintsUnion']
|
'PermittedAlphabetConstraint', 'InnerTypeConstraint',
|
||||||
|
'ConstraintsExclusion', 'ConstraintsIntersection',
|
||||||
|
'ConstraintsUnion']
|
||||||
|
|
||||||
|
|
||||||
class AbstractConstraint(object):
|
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):
|
def __init__(self, *values):
|
||||||
self._valueMap = set()
|
self._valueMap = set()
|
||||||
@ -40,10 +37,12 @@ class AbstractConstraint(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(%s)' % (
|
representation = '%s object at 0x%x' % (self.__class__.__name__, id(self))
|
||||||
self.__class__.__name__,
|
|
||||||
', '.join([repr(x) for x in self._values])
|
if self._values:
|
||||||
)
|
representation += ' consts %s' % ', '.join([repr(x) for x in self._values])
|
||||||
|
|
||||||
|
return '<%s>' % representation
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self is other and True or self._values == other
|
return self is other and True or self._values == other
|
||||||
@ -96,9 +95,39 @@ class AbstractConstraint(object):
|
|||||||
otherConstraint == self or
|
otherConstraint == self or
|
||||||
otherConstraint in self._valueMap)
|
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):
|
def _setValues(self, values):
|
||||||
self._values = values
|
self._values = values
|
||||||
self._set = set(values)
|
self._set = set(values)
|
||||||
@ -109,16 +138,85 @@ class SingleValueConstraint(AbstractConstraint):
|
|||||||
|
|
||||||
|
|
||||||
class ContainedSubtypeConstraint(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):
|
def _testValue(self, value, idx):
|
||||||
for c in self._values:
|
for constraint in self._values:
|
||||||
c(value, idx)
|
if isinstance(constraint, AbstractConstraint):
|
||||||
|
constraint(value, idx)
|
||||||
|
elif value not in self._set:
|
||||||
|
raise error.ValueConstraintError(value)
|
||||||
|
|
||||||
|
|
||||||
class ValueRangeConstraint(AbstractConstraint):
|
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):
|
def _testValue(self, value, idx):
|
||||||
if value < self.start or value > self.stop:
|
if value < self.start or value > self.stop:
|
||||||
raise error.ValueConstraintError(value)
|
raise error.ValueConstraintError(value)
|
||||||
@ -140,8 +238,59 @@ class ValueRangeConstraint(AbstractConstraint):
|
|||||||
|
|
||||||
|
|
||||||
class ValueSizeConstraint(ValueRangeConstraint):
|
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):
|
def _testValue(self, value, idx):
|
||||||
valueSize = len(value)
|
valueSize = len(value)
|
||||||
if valueSize < self.start or valueSize > self.stop:
|
if valueSize < self.start or valueSize > self.stop:
|
||||||
@ -149,6 +298,40 @@ class ValueSizeConstraint(ValueRangeConstraint):
|
|||||||
|
|
||||||
|
|
||||||
class PermittedAlphabetConstraint(SingleValueConstraint):
|
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):
|
def _setValues(self, values):
|
||||||
self._values = values
|
self._values = values
|
||||||
self._set = set(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
|
# This is a bit kludgy, meaning two op modes within a single constraint
|
||||||
class InnerTypeConstraint(AbstractConstraint):
|
class InnerTypeConstraint(AbstractConstraint):
|
||||||
"""Value must satisfy type and presense constraints"""
|
"""Value must satisfy the type and presence constraints"""
|
||||||
|
|
||||||
def _testValue(self, value, idx):
|
def _testValue(self, value, idx):
|
||||||
if self.__singleTypeConstraint:
|
if self.__singleTypeConstraint:
|
||||||
@ -184,11 +367,50 @@ class InnerTypeConstraint(AbstractConstraint):
|
|||||||
AbstractConstraint._setValues(self, values)
|
AbstractConstraint._setValues(self, values)
|
||||||
|
|
||||||
|
|
||||||
# Boolean ops on constraints
|
# Logic operations on constraints
|
||||||
|
|
||||||
class ConstraintsExclusion(AbstractConstraint):
|
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):
|
def _testValue(self, value, idx):
|
||||||
try:
|
try:
|
||||||
self._values[0](value, idx)
|
self._values[0](value, idx)
|
||||||
@ -200,11 +422,11 @@ class ConstraintsExclusion(AbstractConstraint):
|
|||||||
def _setValues(self, values):
|
def _setValues(self, values):
|
||||||
if len(values) != 1:
|
if len(values) != 1:
|
||||||
raise error.PyAsn1Error('Single constraint expected')
|
raise error.PyAsn1Error('Single constraint expected')
|
||||||
|
|
||||||
AbstractConstraint._setValues(self, values)
|
AbstractConstraint._setValues(self, values)
|
||||||
|
|
||||||
|
|
||||||
class AbstractConstraintSet(AbstractConstraint):
|
class AbstractConstraintSet(AbstractConstraint):
|
||||||
"""Value must not satisfy the single constraint"""
|
|
||||||
|
|
||||||
def __getitem__(self, idx):
|
def __getitem__(self, idx):
|
||||||
return self._values[idx]
|
return self._values[idx]
|
||||||
@ -232,16 +454,88 @@ class AbstractConstraintSet(AbstractConstraint):
|
|||||||
|
|
||||||
|
|
||||||
class ConstraintsIntersection(AbstractConstraintSet):
|
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):
|
def _testValue(self, value, idx):
|
||||||
for constraint in self._values:
|
for constraint in self._values:
|
||||||
constraint(value, idx)
|
constraint(value, idx)
|
||||||
|
|
||||||
|
|
||||||
class ConstraintsUnion(AbstractConstraintSet):
|
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):
|
def _testValue(self, value, idx):
|
||||||
for constraint in self._values:
|
for constraint in self._values:
|
||||||
try:
|
try:
|
||||||
@ -250,9 +544,13 @@ class ConstraintsUnion(AbstractConstraintSet):
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
raise error.ValueConstraintError(
|
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
|
# add tests for type check
|
||||||
|
# implement other constraint types
|
||||||
|
# make constraint validation easy to skip
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from pyasn1.error import PyAsn1Error
|
from pyasn1.error import PyAsn1Error
|
||||||
|
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
import sys
|
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):
|
class NamedType(object):
|
||||||
@ -30,13 +39,19 @@ class NamedType(object):
|
|||||||
isOptional = False
|
isOptional = False
|
||||||
isDefaulted = False
|
isDefaulted = False
|
||||||
|
|
||||||
def __init__(self, name, asn1Object):
|
def __init__(self, name, asn1Object, openType=None):
|
||||||
self.__name = name
|
self.__name = name
|
||||||
self.__type = asn1Object
|
self.__type = asn1Object
|
||||||
self.__nameAndType = name, asn1Object
|
self.__nameAndType = name, asn1Object
|
||||||
|
self.__openType = openType
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
def __eq__(self, other):
|
||||||
return self.__nameAndType == other
|
return self.__nameAndType == other
|
||||||
@ -68,11 +83,15 @@ class NamedType(object):
|
|||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.__name
|
return self.__name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def asn1Object(self):
|
def asn1Object(self):
|
||||||
return self.__type
|
return self.__type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def openType(self):
|
||||||
|
return self.__openType
|
||||||
|
|
||||||
# Backward compatibility
|
# Backward compatibility
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
@ -105,6 +124,31 @@ class NamedTypes(object):
|
|||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
*namedTypes: :class:`~pyasn1.type.namedtype.NamedType`
|
*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):
|
def __init__(self, *namedTypes, **kwargs):
|
||||||
self.__namedTypes = namedTypes
|
self.__namedTypes = namedTypes
|
||||||
@ -115,8 +159,11 @@ class NamedTypes(object):
|
|||||||
self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {}
|
self.__ambiguousTypes = 'terminal' not in kwargs and self.__computeAmbiguousTypes() or {}
|
||||||
self.__uniqueTagMap = self.__computeTagMaps(unique=True)
|
self.__uniqueTagMap = self.__computeTagMaps(unique=True)
|
||||||
self.__nonUniqueTagMap = self.__computeTagMaps(unique=False)
|
self.__nonUniqueTagMap = self.__computeTagMaps(unique=False)
|
||||||
self.__hasOptionalOrDefault = bool([True for namedType in self.__namedTypes
|
self.__hasOptionalOrDefault = any([True for namedType in self.__namedTypes
|
||||||
if namedType.isDefaulted or namedType.isOptional])
|
if namedType.isDefaulted or namedType.isOptional])
|
||||||
|
self.__hasOpenTypes = any([True for namedType in self.__namedTypes
|
||||||
|
if namedType.openType])
|
||||||
|
|
||||||
self.__requiredComponents = frozenset(
|
self.__requiredComponents = frozenset(
|
||||||
[idx for idx, nt in enumerate(self.__namedTypes) if not nt.isOptional and not nt.isDefaulted]
|
[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])
|
self.__items = tuple([(namedType.name, namedType.asn1Object) for namedType in self.__namedTypes])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(%s)' % (
|
representation = ', '.join(['%r' % x for x in self.__namedTypes])
|
||||||
self.__class__.__name__, ', '.join([repr(x) for x in self.__namedTypes])
|
return '<%s object at 0x%x types %s>' % (self.__class__.__name__, id(self), representation)
|
||||||
)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.__namedTypes == other
|
return self.__namedTypes == other
|
||||||
@ -331,7 +377,7 @@ class NamedTypes(object):
|
|||||||
def getTagMapNearPosition(self, idx):
|
def getTagMapNearPosition(self, idx):
|
||||||
"""Return ASN.1 types that are allowed at or past given field position.
|
"""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
|
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
|
such objects it may be important to know which types can possibly be
|
||||||
present at any given position in the field sets.
|
present at any given position in the field sets.
|
||||||
@ -360,7 +406,7 @@ class NamedTypes(object):
|
|||||||
def getPositionNearType(self, tagSet, idx):
|
def getPositionNearType(self, tagSet, idx):
|
||||||
"""Return the closest field position where given ASN.1 type is allowed.
|
"""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
|
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,
|
such objects it may be important to know at which field position, in field set,
|
||||||
given *tagSet* is allowed at or past *idx* position.
|
given *tagSet* is allowed at or past *idx* position.
|
||||||
@ -410,7 +456,7 @@ class NamedTypes(object):
|
|||||||
def minTagSet(self):
|
def minTagSet(self):
|
||||||
"""Return the minimal TagSet among ASN.1 type in callee *NamedTypes*.
|
"""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
|
arranged based on their numerical tag value. The *minTagSet* property
|
||||||
returns that.
|
returns that.
|
||||||
|
|
||||||
@ -452,7 +498,6 @@ class NamedTypes(object):
|
|||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
OuterType ::= CHOICE {
|
OuterType ::= CHOICE {
|
||||||
@ -477,7 +522,6 @@ class NamedTypes(object):
|
|||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
OuterType ::= CHOICE {
|
OuterType ::= CHOICE {
|
||||||
@ -502,9 +546,13 @@ class NamedTypes(object):
|
|||||||
def hasOptionalOrDefault(self):
|
def hasOptionalOrDefault(self):
|
||||||
return self.__hasOptionalOrDefault
|
return self.__hasOptionalOrDefault
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hasOpenTypes(self):
|
||||||
|
return self.__hasOpenTypes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def namedTypes(self):
|
def namedTypes(self):
|
||||||
return iter(self.__namedTypes)
|
return tuple(self.__namedTypes)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def requiredComponents(self):
|
def requiredComponents(self):
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# ASN.1 named integers
|
# ASN.1 named integers
|
||||||
#
|
#
|
||||||
@ -23,26 +23,34 @@ class NamedValues(object):
|
|||||||
|
|
||||||
Parameters
|
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`
|
name: :py:class:`str`
|
||||||
Value name
|
Value label
|
||||||
|
|
||||||
value: :py:class:`int`
|
value: :py:class:`int`
|
||||||
A numerical value
|
Numeric value
|
||||||
|
|
||||||
|
Keyword Args
|
||||||
|
------------
|
||||||
|
name: :py:class:`str`
|
||||||
|
Value label
|
||||||
|
|
||||||
|
value: :py:class:`int`
|
||||||
|
Numeric value
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
--------
|
--------
|
||||||
|
|
||||||
>>> nv = namedval.NamedValues('a', 'b', ('c', 0), d=1)
|
.. code-block:: pycon
|
||||||
>>> nv
|
|
||||||
>>> {'c': 0, 'd': 1, 'a': 2, 'b': 3}
|
>>> nv = NamedValues('a', 'b', ('c', 0), d=1)
|
||||||
>>> nv[0]
|
>>> nv
|
||||||
'c'
|
>>> {'c': 0, 'd': 1, 'a': 2, 'b': 3}
|
||||||
>>> nv['a']
|
>>> nv[0]
|
||||||
2
|
'c'
|
||||||
|
>>> nv['a']
|
||||||
|
2
|
||||||
"""
|
"""
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.__names = {}
|
self.__names = {}
|
||||||
@ -96,10 +104,12 @@ class NamedValues(object):
|
|||||||
number += 1
|
number += 1
|
||||||
|
|
||||||
def __repr__(self):
|
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):
|
if len(representation) > 64:
|
||||||
return str(self.items())
|
representation = representation[:32] + '...' + representation[-32:]
|
||||||
|
|
||||||
|
return '<%s object 0x%x enums %s>' % (self.__class__.__name__, id(self), representation)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return dict(self) == other
|
return dict(self) == other
|
||||||
|
75
src/pyasn1/type/opentype.py
Normal file
75
src/pyasn1/type/opentype.py
Normal 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)
|
@ -1,15 +1,15 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from pyasn1 import error
|
from pyasn1 import error
|
||||||
|
|
||||||
__all__ = ['tagClassUniversal', 'tagClassApplication', 'tagClassContext',
|
__all__ = ['tagClassUniversal', 'tagClassApplication', 'tagClassContext',
|
||||||
'tagClassPrivate', 'tagFormatSimple', 'tagFormatConstructed',
|
'tagClassPrivate', 'tagFormatSimple', 'tagFormatConstructed',
|
||||||
'tagCategoryImplicit', 'tagCategoryExplicit', 'tagCategoryUntagged',
|
'tagCategoryImplicit', 'tagCategoryExplicit',
|
||||||
'Tag', 'TagSet']
|
'tagCategoryUntagged', 'Tag', 'TagSet']
|
||||||
|
|
||||||
#: Identifier for ASN.1 class UNIVERSAL
|
#: Identifier for ASN.1 class UNIVERSAL
|
||||||
tagClassUniversal = 0x00
|
tagClassUniversal = 0x00
|
||||||
@ -63,13 +63,9 @@ class Tag(object):
|
|||||||
self.__tagClassId = tagClass, tagId
|
self.__tagClassId = tagClass, tagId
|
||||||
self.__hash = hash(self.__tagClassId)
|
self.__hash = hash(self.__tagClassId)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return '[%s:%s:%s]' % (self.__tagClass, self.__tagFormat, self.__tagId)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(tagClass=%s, tagFormat=%s, tagId=%s)' % (
|
representation = '[%s:%s:%s]' % (self.__tagClass, self.__tagFormat, self.__tagId)
|
||||||
(self.__class__.__name__, self.__tagClass, self.__tagFormat, self.__tagId)
|
return '<%s object at 0x%x tag %s>' % (self.__class__.__name__, id(self), representation)
|
||||||
)
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.__tagClassId == other
|
return self.__tagClassId == other
|
||||||
@ -168,6 +164,23 @@ class TagSet(object):
|
|||||||
|
|
||||||
*superTags: :class:`~pyasn1.type.tag.Tag`
|
*superTags: :class:`~pyasn1.type.tag.Tag`
|
||||||
Additional *Tag* objects taking part in subtyping.
|
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):
|
def __init__(self, baseTag=(), *superTags):
|
||||||
self.__baseTag = baseTag
|
self.__baseTag = baseTag
|
||||||
@ -178,13 +191,15 @@ class TagSet(object):
|
|||||||
self.__lenOfSuperTags = len(superTags)
|
self.__lenOfSuperTags = len(superTags)
|
||||||
self.__hash = hash(self.__superTagsClassId)
|
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):
|
def __repr__(self):
|
||||||
return '%s(%s)' % (
|
representation = '-'.join(['%s:%s:%s' % (x.tagClass, x.tagFormat, x.tagId)
|
||||||
self.__class__.__name__, '(), ' + ', '.join([repr(x) for x in self.__superTags])
|
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):
|
def __add__(self, superTag):
|
||||||
return self.__class__(self.__baseTag, *self.__superTags + (superTag,))
|
return self.__class__(self.__baseTag, *self.__superTags + (superTag,))
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
from pyasn1 import error
|
from pyasn1 import error
|
||||||
|
|
||||||
@ -56,24 +56,18 @@ class TagMap(object):
|
|||||||
return iter(self.__presentTypes)
|
return iter(self.__presentTypes)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
s = self.__class__.__name__ + '('
|
representation = '%s object at 0x%x' % (self.__class__.__name__, id(self))
|
||||||
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 + ')'
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
s = self.__class__.__name__ + ': '
|
|
||||||
if self.__presentTypes:
|
if self.__presentTypes:
|
||||||
s += 'presentTypes: %s, ' % ', '.join([x.prettyPrintType() for x in self.__presentTypes.values()])
|
representation += ' present %s' % repr(self.__presentTypes)
|
||||||
|
|
||||||
if self.__skipTypes:
|
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:
|
if self.__defaultType is not None:
|
||||||
s += 'defaultType: %s, ' % self.__defaultType.prettyPrintType()
|
representation += ' default %s' % repr(self.__defaultType)
|
||||||
return s
|
|
||||||
|
return '<%s>' % representation
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def presentTypes(self):
|
def presentTypes(self):
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,17 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1 software.
|
# This file is part of pyasn1 software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
import datetime
|
import datetime
|
||||||
from pyasn1.type import univ, char, tag
|
|
||||||
from pyasn1.compat import string, dateandtime
|
|
||||||
from pyasn1 import error
|
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']
|
__all__ = ['ObjectDescriptor', 'GeneralizedTime', 'UTCTime']
|
||||||
|
|
||||||
@ -61,7 +65,7 @@ class TimeMixIn(object):
|
|||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
:
|
:
|
||||||
new instance of :py:class:`datetime.datetime` object
|
new instance of :py:class:`datetime.datetime` object
|
||||||
"""
|
"""
|
||||||
text = str(self)
|
text = str(self)
|
||||||
if text.endswith('Z'):
|
if text.endswith('Z'):
|
||||||
@ -100,7 +104,7 @@ class TimeMixIn(object):
|
|||||||
text, _, ms = string.partition(text, ',')
|
text, _, ms = string.partition(text, ',')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ms = int(ms) * 10000
|
ms = int(ms) * 1000
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise error.PyAsn1Error('bad sub-second time specification %s' % self)
|
raise error.PyAsn1Error('bad sub-second time specification %s' % self)
|
||||||
@ -127,10 +131,10 @@ class TimeMixIn(object):
|
|||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
dt : :py:class:`datetime.datetime` object
|
dt: :py:class:`datetime.datetime` object
|
||||||
The `datetime.datetime` object to initialize the |ASN.1| object from
|
The `datetime.datetime` object to initialize the |ASN.1| object
|
||||||
|
from
|
||||||
|
|
||||||
Returns
|
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')
|
text = dt.strftime(cls._yearsDigits == 4 and '%Y%m%d%H%M%S' or '%y%m%d%H%M%S')
|
||||||
if cls._hasSubsecond:
|
if cls._hasSubsecond:
|
||||||
text += '.%d' % (dt.microsecond // 10000)
|
text += '.%d' % (dt.microsecond // 1000)
|
||||||
|
|
||||||
if dt.utcoffset():
|
if dt.utcoffset():
|
||||||
seconds = dt.utcoffset().seconds
|
seconds = dt.utcoffset().seconds
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
# http://www.python.org/dev/peps/pep-0396/
|
# http://www.python.org/dev/peps/pep-0396/
|
||||||
__version__ = '0.1.4'
|
__version__ = '0.2.2'
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
import base64
|
import base64
|
||||||
import sys
|
import sys
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# SNMPv1 message syntax
|
# SNMPv1 message syntax
|
||||||
#
|
#
|
||||||
@ -12,7 +12,10 @@
|
|||||||
# Sample captures from:
|
# Sample captures from:
|
||||||
# http://wiki.wireshark.org/SampleCaptures/
|
# 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):
|
class ObjectName(univ.ObjectIdentifier):
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# SNMPv1 message syntax
|
# SNMPv1 message syntax
|
||||||
#
|
#
|
||||||
@ -12,7 +12,11 @@
|
|||||||
# Sample captures from:
|
# Sample captures from:
|
||||||
# http://wiki.wireshark.org/SampleCaptures/
|
# 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
|
from pyasn1_modules import rfc1155
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# SNMPv2c message syntax
|
# SNMPv2c message syntax
|
||||||
#
|
#
|
||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc1901.txt
|
# 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):
|
class Message(univ.Sequence):
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# SNMPv2c message syntax
|
# SNMPv2c message syntax
|
||||||
#
|
#
|
||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc1902.txt
|
# 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):
|
class Integer(univ.Integer):
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# SNMPv2c PDU syntax
|
# SNMPv2c PDU syntax
|
||||||
#
|
#
|
||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc1905.txt
|
# 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
|
from pyasn1_modules import rfc1902
|
||||||
|
|
||||||
max_bindings = rfc1902.Integer(2147483647)
|
max_bindings = rfc1902.Integer(2147483647)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# LDAP message syntax
|
# LDAP message syntax
|
||||||
#
|
#
|
||||||
@ -12,7 +12,11 @@
|
|||||||
# Sample captures from:
|
# Sample captures from:
|
||||||
# http://wiki.wireshark.org/SampleCaptures/
|
# 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)
|
maxInt = univ.Integer(2147483647)
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# PKCS#10 syntax
|
# PKCS#10 syntax
|
||||||
#
|
#
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# PKCS#7 message syntax
|
# PKCS#7 message syntax
|
||||||
#
|
#
|
||||||
@ -25,7 +25,8 @@ class Attribute(univ.Sequence):
|
|||||||
class AttributeValueAssertion(univ.Sequence):
|
class AttributeValueAssertion(univ.Sequence):
|
||||||
componentType = namedtype.NamedTypes(
|
componentType = namedtype.NamedTypes(
|
||||||
namedtype.NamedType('attributeType', AttributeType()),
|
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
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
contentTypeMap = {}
|
||||||
|
|
||||||
|
|
||||||
class EncryptedContentInfo(univ.Sequence):
|
class EncryptedContentInfo(univ.Sequence):
|
||||||
componentType = namedtype.NamedTypes(
|
componentType = namedtype.NamedTypes(
|
||||||
namedtype.NamedType('contentType', ContentType()),
|
namedtype.NamedType('contentType', ContentType()),
|
||||||
namedtype.NamedType('contentEncryptionAlgorithm', ContentEncryptionAlgorithmIdentifier()),
|
namedtype.NamedType('contentEncryptionAlgorithm', ContentEncryptionAlgorithmIdentifier()),
|
||||||
namedtype.OptionalNamedType('encryptedContent', EncryptedContent().subtype(
|
namedtype.OptionalNamedType(
|
||||||
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)))
|
'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):
|
class ContentInfo(univ.Sequence):
|
||||||
componentType = namedtype.NamedTypes(
|
componentType = namedtype.NamedTypes(
|
||||||
namedtype.NamedType('contentType', ContentType()),
|
namedtype.NamedType('contentType', ContentType()),
|
||||||
namedtype.OptionalNamedType('content', univ.Any().subtype(
|
namedtype.OptionalNamedType(
|
||||||
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)))
|
'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):
|
class Data(univ.OctetString):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
_contentTypeMapUpdate = {
|
||||||
|
data: Data(),
|
||||||
|
signedData: SignedData(),
|
||||||
|
envelopedData: EnvelopedData(),
|
||||||
|
signedAndEnvelopedData: SignedAndEnvelopedData(),
|
||||||
|
digestedData: DigestedData(),
|
||||||
|
encryptedData: EncryptedData()
|
||||||
|
}
|
||||||
|
|
||||||
|
contentTypeMap.update(_contentTypeMapUpdate)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# PKCS#1 syntax
|
# PKCS#1 syntax
|
||||||
#
|
#
|
||||||
@ -11,7 +11,10 @@
|
|||||||
#
|
#
|
||||||
# Sample captures could be obtained with "openssl genrsa" command
|
# 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
|
from pyasn1_modules.rfc2459 import AlgorithmIdentifier
|
||||||
|
|
||||||
pkcs_1 = univ.ObjectIdentifier('1.2.840.113549.1.1')
|
pkcs_1 = univ.ObjectIdentifier('1.2.840.113549.1.1')
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# X.509 message syntax
|
# X.509 message syntax
|
||||||
#
|
#
|
||||||
@ -13,7 +13,14 @@
|
|||||||
# Sample captures from:
|
# Sample captures from:
|
||||||
# http://wiki.wireshark.org/SampleCaptures/
|
# 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')
|
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')
|
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')
|
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):
|
class DirectoryString(univ.Choice):
|
||||||
componentType = namedtype.NamedTypes(
|
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
|
# Algorithm OIDs and parameter structures
|
||||||
|
|
||||||
@ -972,11 +841,6 @@ class BasicConstraints(univ.Sequence):
|
|||||||
id_ce_subjectDirectoryAttributes = univ.ObjectIdentifier('2.5.29.9')
|
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):
|
class EDIPartyName(univ.Sequence):
|
||||||
componentType = namedtype.NamedTypes(
|
componentType = namedtype.NamedTypes(
|
||||||
namedtype.OptionalNamedType('nameAssigner', DirectoryString().subtype(
|
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')
|
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):
|
class BaseDistance(univ.Integer):
|
||||||
subtypeSpec = univ.Integer.subtypeSpec + constraint.ValueRangeConstraint(0, MAX)
|
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')
|
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')
|
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')
|
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):
|
class DisplayText(univ.Choice):
|
||||||
componentType = namedtype.NamedTypes(
|
componentType = namedtype.NamedTypes(
|
||||||
namedtype.NamedType('visibleString',
|
namedtype.NamedType('visibleString',
|
||||||
@ -1232,6 +988,110 @@ class SubjectKeyIdentifier(KeyIdentifier):
|
|||||||
pass
|
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):
|
class AuthorityKeyIdentifier(univ.Sequence):
|
||||||
componentType = namedtype.NamedTypes(
|
componentType = namedtype.NamedTypes(
|
||||||
namedtype.OptionalNamedType('keyIdentifier', KeyIdentifier().subtype(
|
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):
|
class CertificateIssuer(GeneralNames):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
id_ce_subjectAltName = univ.ObjectIdentifier('2.5.29.17')
|
|
||||||
|
|
||||||
|
|
||||||
class SubjectAltName(GeneralNames):
|
class SubjectAltName(GeneralNames):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
id_ce_issuerAltName = univ.ObjectIdentifier('2.5.29.18')
|
|
||||||
|
|
||||||
|
|
||||||
class IssuerAltName(GeneralNames):
|
class IssuerAltName(GeneralNames):
|
||||||
pass
|
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
|
# map of AttributeType -> AttributeValue
|
||||||
|
|
||||||
certificateAttributesMap = {
|
_certificateAttributesMapUpdate = {
|
||||||
id_at_name: X520name(),
|
id_at_name: X520name(),
|
||||||
id_at_surname: X520name(),
|
id_at_surname: X520name(),
|
||||||
id_at_givenName: X520name(),
|
id_at_givenName: X520name(),
|
||||||
@ -1283,14 +1302,18 @@ certificateAttributesMap = {
|
|||||||
emailAddress: Pkcs9email(),
|
emailAddress: Pkcs9email(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
certificateAttributesMap.update(_certificateAttributesMapUpdate)
|
||||||
|
|
||||||
|
|
||||||
# map of Certificate Extension OIDs to Extensions
|
# map of Certificate Extension OIDs to Extensions
|
||||||
|
|
||||||
certificateExtensionsMap = {
|
_certificateExtensionsMapUpdate = {
|
||||||
id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier(),
|
id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier(),
|
||||||
id_ce_subjectKeyIdentifier: SubjectKeyIdentifier(),
|
id_ce_subjectKeyIdentifier: SubjectKeyIdentifier(),
|
||||||
id_ce_keyUsage: KeyUsage(),
|
id_ce_keyUsage: KeyUsage(),
|
||||||
id_ce_privateKeyUsagePeriod: PrivateKeyUsagePeriod(),
|
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_policyMappings: PolicyMappings(),
|
||||||
id_ce_subjectAltName: SubjectAltName(),
|
id_ce_subjectAltName: SubjectAltName(),
|
||||||
id_ce_issuerAltName: IssuerAltName(),
|
id_ce_issuerAltName: IssuerAltName(),
|
||||||
@ -1309,3 +1332,6 @@ certificateExtensionsMap = {
|
|||||||
id_ce_invalidityDate: useful.GeneralizedTime(),
|
id_ce_invalidityDate: useful.GeneralizedTime(),
|
||||||
id_ce_certificateIssuer: GeneralNames(),
|
id_ce_certificateIssuer: GeneralNames(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
certificateExtensionsMap.update(_certificateExtensionsMapUpdate)
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# X.509 certificate Request Message Format (CRMF) syntax
|
# X.509 certificate Request Message Format (CRMF) syntax
|
||||||
#
|
#
|
||||||
@ -11,8 +11,8 @@
|
|||||||
#
|
#
|
||||||
# Sample captures could be obtained with OpenSSL
|
# Sample captures could be obtained with OpenSSL
|
||||||
#
|
#
|
||||||
from pyasn1_modules.rfc2459 import *
|
|
||||||
from pyasn1_modules import rfc2315
|
from pyasn1_modules import rfc2315
|
||||||
|
from pyasn1_modules.rfc2459 import *
|
||||||
|
|
||||||
MAX = float('inf')
|
MAX = float('inf')
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# OCSP request/response syntax
|
# OCSP request/response syntax
|
||||||
#
|
#
|
||||||
@ -21,7 +21,12 @@
|
|||||||
# * dates are left as strings in GeneralizedTime format -- datetime.datetime
|
# * dates are left as strings in GeneralizedTime format -- datetime.datetime
|
||||||
# would be nicer
|
# 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
|
from pyasn1_modules import rfc2459
|
||||||
|
|
||||||
|
|
||||||
@ -124,9 +129,9 @@ class KeyHash(univ.OctetString):
|
|||||||
class ResponderID(univ.Choice):
|
class ResponderID(univ.Choice):
|
||||||
componentType = namedtype.NamedTypes(
|
componentType = namedtype.NamedTypes(
|
||||||
namedtype.NamedType('byName',
|
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',
|
namedtype.NamedType('byKey',
|
||||||
KeyHash().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)))
|
KeyHash().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
124
src/pyasn1_modules/rfc2986.py
Normal file
124
src/pyasn1_modules/rfc2986.py
Normal 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())
|
||||||
|
)
|
@ -2,11 +2,13 @@
|
|||||||
# This file is part of pyasn1-modules.
|
# This file is part of pyasn1-modules.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2017, Danielle Madeley <danielle@madeley.id.au>
|
# 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
|
# 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):
|
def _OID(*components):
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Created by Stanisław Pitucha with asn1ate tool.
|
# Created by Stanisław Pitucha with asn1ate tool.
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# Internet X.509 Public Key Infrastructure Certificate and Certificate
|
# Internet X.509 Public Key Infrastructure Certificate and Certificate
|
||||||
# Revocation List (CRL) Profile
|
# Revocation List (CRL) Profile
|
||||||
@ -12,7 +12,13 @@
|
|||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc3280.txt
|
# 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')
|
MAX = float('inf')
|
||||||
|
|
||||||
|
@ -3,20 +3,20 @@
|
|||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Created by Stanisław Pitucha with asn1ate tool.
|
# Created by Stanisław Pitucha with asn1ate tool.
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# An Internet Attribute Certificate Profile for Authorization
|
# An Internet Attribute Certificate Profile for Authorization
|
||||||
#
|
#
|
||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc3281.txt
|
# http://www.ietf.org/rfc/rfc3281.txt
|
||||||
#
|
#
|
||||||
from pyasn1.type import univ
|
|
||||||
from pyasn1.type import char
|
from pyasn1.type import char
|
||||||
|
from pyasn1.type import constraint
|
||||||
from pyasn1.type import namedtype
|
from pyasn1.type import namedtype
|
||||||
from pyasn1.type import namedval
|
from pyasn1.type import namedval
|
||||||
from pyasn1.type import tag
|
from pyasn1.type import tag
|
||||||
from pyasn1.type import constraint
|
from pyasn1.type import univ
|
||||||
from pyasn1.type import useful
|
from pyasn1.type import useful
|
||||||
|
|
||||||
from pyasn1_modules import rfc3280
|
from pyasn1_modules import rfc3280
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# SNMPv3 message syntax
|
# SNMPv3 message syntax
|
||||||
#
|
#
|
||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc3412.txt
|
# 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
|
from pyasn1_modules import rfc1905
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# SNMPv3 message syntax
|
# SNMPv3 message syntax
|
||||||
#
|
#
|
||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc3414.txt
|
# 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):
|
class UsmSecurityParameters(univ.Sequence):
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# PKCS#1 syntax
|
# PKCS#1 syntax
|
||||||
#
|
#
|
||||||
@ -11,7 +11,9 @@
|
|||||||
#
|
#
|
||||||
# Sample captures could be obtained with "openssl genrsa" command
|
# 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 *
|
from pyasn1_modules.rfc2437 import *
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,15 +3,20 @@
|
|||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Created by Stanisław Pitucha with asn1ate tool.
|
# Created by Stanisław Pitucha with asn1ate tool.
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# Cryptographic Message Syntax (CMS)
|
# Cryptographic Message Syntax (CMS)
|
||||||
#
|
#
|
||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc3852.txt
|
# 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 rfc3280
|
||||||
from pyasn1_modules import rfc3281
|
from pyasn1_modules import rfc3281
|
||||||
|
@ -1,15 +1,24 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# Certificate Management Protocol structures as per RFC4210
|
# Certificate Management Protocol structures as per RFC4210
|
||||||
#
|
#
|
||||||
# Based on Alex Railean's work
|
# Based on Alex Railean's work
|
||||||
#
|
#
|
||||||
from pyasn1.type import tag, namedtype, namedval, univ, constraint, char, useful
|
from pyasn1.type import char
|
||||||
from pyasn1_modules import rfc2459, rfc2511, rfc2314
|
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')
|
MAX = float('inf')
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Created by Stanisław Pitucha with asn1ate tool.
|
# Created by Stanisław Pitucha with asn1ate tool.
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# Internet X.509 Public Key Infrastructure Certificate Request
|
# Internet X.509 Public Key Infrastructure Certificate Request
|
||||||
# Message Format (CRMF)
|
# Message Format (CRMF)
|
||||||
@ -12,7 +12,12 @@
|
|||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc4211.txt
|
# 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 rfc3280
|
||||||
from pyasn1_modules import rfc3852
|
from pyasn1_modules import rfc3852
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# PKCS#8 syntax
|
# PKCS#8 syntax
|
||||||
#
|
#
|
||||||
@ -11,8 +11,8 @@
|
|||||||
#
|
#
|
||||||
# Sample captures could be obtained with "openssl pkcs8 -topk8" command
|
# Sample captures could be obtained with "openssl pkcs8 -topk8" command
|
||||||
#
|
#
|
||||||
from pyasn1_modules.rfc2459 import *
|
|
||||||
from pyasn1_modules import rfc2251
|
from pyasn1_modules import rfc2251
|
||||||
|
from pyasn1_modules.rfc2459 import *
|
||||||
|
|
||||||
|
|
||||||
class KeyEncryptionAlgorithms(AlgorithmIdentifier):
|
class KeyEncryptionAlgorithms(AlgorithmIdentifier):
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Created by Stanisław Pitucha with asn1ate tool.
|
# Created by Stanisław Pitucha with asn1ate tool.
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# Internet X.509 Public Key Infrastructure Certificate and Certificate
|
# Internet X.509 Public Key Infrastructure Certificate and Certificate
|
||||||
# Revocation List (CRL) Profile
|
# Revocation List (CRL) Profile
|
||||||
@ -12,16 +12,18 @@
|
|||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc5280.txt
|
# http://www.ietf.org/rfc/rfc5280.txt
|
||||||
#
|
#
|
||||||
from pyasn1.type import univ
|
|
||||||
from pyasn1.type import char
|
from pyasn1.type import char
|
||||||
|
from pyasn1.type import constraint
|
||||||
from pyasn1.type import namedtype
|
from pyasn1.type import namedtype
|
||||||
from pyasn1.type import namedval
|
from pyasn1.type import namedval
|
||||||
|
from pyasn1.type import opentype
|
||||||
from pyasn1.type import tag
|
from pyasn1.type import tag
|
||||||
from pyasn1.type import constraint
|
from pyasn1.type import univ
|
||||||
from pyasn1.type import useful
|
from pyasn1.type import useful
|
||||||
|
|
||||||
MAX = float('inf')
|
MAX = float('inf')
|
||||||
|
|
||||||
|
|
||||||
def _buildOid(*components):
|
def _buildOid(*components):
|
||||||
output = []
|
output = []
|
||||||
for x in tuple(components):
|
for x in tuple(components):
|
||||||
@ -279,13 +281,10 @@ class CertificateSerialNumber(univ.Integer):
|
|||||||
|
|
||||||
|
|
||||||
class AlgorithmIdentifier(univ.Sequence):
|
class AlgorithmIdentifier(univ.Sequence):
|
||||||
pass
|
componentType = namedtype.NamedTypes(
|
||||||
|
namedtype.NamedType('algorithm', univ.ObjectIdentifier()),
|
||||||
|
namedtype.OptionalNamedType('parameters', univ.Any())
|
||||||
AlgorithmIdentifier.componentType = namedtype.NamedTypes(
|
)
|
||||||
namedtype.NamedType('algorithm', univ.ObjectIdentifier()),
|
|
||||||
namedtype.OptionalNamedType('parameters', univ.Any())
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Time(univ.Choice):
|
class Time(univ.Choice):
|
||||||
@ -302,14 +301,17 @@ class AttributeValue(univ.Any):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
certificateAttributesMap = {}
|
||||||
|
|
||||||
|
|
||||||
class AttributeTypeAndValue(univ.Sequence):
|
class AttributeTypeAndValue(univ.Sequence):
|
||||||
pass
|
componentType = namedtype.NamedTypes(
|
||||||
|
namedtype.NamedType('type', AttributeType()),
|
||||||
|
namedtype.NamedType(
|
||||||
AttributeTypeAndValue.componentType = namedtype.NamedTypes(
|
'value', AttributeValue(),
|
||||||
namedtype.NamedType('type', AttributeType()),
|
openType=opentype.OpenType('type', certificateAttributesMap)
|
||||||
namedtype.NamedType('value', AttributeValue())
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class RelativeDistinguishedName(univ.SetOf):
|
class RelativeDistinguishedName(univ.SetOf):
|
||||||
@ -379,18 +381,21 @@ class PhysicalDeliveryOfficeName(PDSParameter):
|
|||||||
|
|
||||||
ub_extension_attributes = univ.Integer(256)
|
ub_extension_attributes = univ.Integer(256)
|
||||||
|
|
||||||
|
certificateExtensionsMap = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ExtensionAttribute(univ.Sequence):
|
class ExtensionAttribute(univ.Sequence):
|
||||||
pass
|
componentType = namedtype.NamedTypes(
|
||||||
|
namedtype.NamedType(
|
||||||
|
'extension-attribute-type',
|
||||||
ExtensionAttribute.componentType = namedtype.NamedTypes(
|
univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, ub_extension_attributes)).subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
||||||
namedtype.NamedType('extension-attribute-type', univ.Integer().subtype(
|
namedtype.NamedType(
|
||||||
subtypeSpec=constraint.ValueRangeConstraint(0, ub_extension_attributes)).subtype(
|
'extension-attribute-value',
|
||||||
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)),
|
||||||
namedtype.NamedType('extension-attribute-value',
|
openType=opentype.OpenType('type', certificateExtensionsMap))
|
||||||
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)))
|
)
|
||||||
)
|
|
||||||
|
|
||||||
id_qt = _buildOid(id_pkix, 2)
|
id_qt = _buildOid(id_pkix, 2)
|
||||||
|
|
||||||
@ -737,13 +742,12 @@ X520SerialNumber.subtypeSpec = constraint.ValueSizeConstraint(1, ub_serial_numbe
|
|||||||
|
|
||||||
|
|
||||||
class Attribute(univ.Sequence):
|
class Attribute(univ.Sequence):
|
||||||
pass
|
componentType = namedtype.NamedTypes(
|
||||||
|
namedtype.NamedType('type', AttributeType()),
|
||||||
|
namedtype.NamedType('values',
|
||||||
Attribute.componentType = namedtype.NamedTypes(
|
univ.SetOf(componentType=AttributeValue()),
|
||||||
namedtype.NamedType('type', AttributeType()),
|
openType=opentype.OpenType('type', certificateAttributesMap))
|
||||||
namedtype.NamedType('values', univ.SetOf(componentType=AttributeValue()))
|
)
|
||||||
)
|
|
||||||
|
|
||||||
ub_common_name = univ.Integer(64)
|
ub_common_name = univ.Integer(64)
|
||||||
|
|
||||||
@ -1066,14 +1070,20 @@ PrivateKeyUsagePeriod.componentType = namedtype.NamedTypes(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
anotherNameMap = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class AnotherName(univ.Sequence):
|
class AnotherName(univ.Sequence):
|
||||||
pass
|
componentType = namedtype.NamedTypes(
|
||||||
|
namedtype.NamedType('type-id', univ.ObjectIdentifier()),
|
||||||
|
namedtype.NamedType(
|
||||||
AnotherName.componentType = namedtype.NamedTypes(
|
'value',
|
||||||
namedtype.NamedType('type-id', univ.ObjectIdentifier()),
|
univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)),
|
||||||
namedtype.NamedType('value', univ.Any().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))
|
openType=opentype.OpenType('type-id', anotherNameMap)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class EDIPartyName(univ.Sequence):
|
class EDIPartyName(univ.Sequence):
|
||||||
@ -1311,14 +1321,19 @@ class PolicyQualifierId(univ.ObjectIdentifier):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
policyQualifierInfoMap = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class PolicyQualifierInfo(univ.Sequence):
|
class PolicyQualifierInfo(univ.Sequence):
|
||||||
pass
|
componentType = namedtype.NamedTypes(
|
||||||
|
namedtype.NamedType('policyQualifierId', PolicyQualifierId()),
|
||||||
|
namedtype.NamedType(
|
||||||
PolicyQualifierInfo.componentType = namedtype.NamedTypes(
|
'qualifier', univ.Any(),
|
||||||
namedtype.NamedType('policyQualifierId', PolicyQualifierId()),
|
openType=opentype.OpenType('policyQualifierId', policyQualifierInfoMap)
|
||||||
namedtype.NamedType('qualifier', univ.Any())
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CertPolicyId(univ.ObjectIdentifier):
|
class CertPolicyId(univ.ObjectIdentifier):
|
||||||
@ -1549,7 +1564,7 @@ id_ce_inhibitAnyPolicy = _buildOid(id_ce, 54)
|
|||||||
|
|
||||||
# map of AttributeType -> AttributeValue
|
# map of AttributeType -> AttributeValue
|
||||||
|
|
||||||
certificateAttributesMap = {
|
_certificateAttributesMapUpdate = {
|
||||||
id_at_name: X520name(),
|
id_at_name: X520name(),
|
||||||
id_at_surname: X520name(),
|
id_at_surname: X520name(),
|
||||||
id_at_givenName: X520name(),
|
id_at_givenName: X520name(),
|
||||||
@ -1569,9 +1584,12 @@ certificateAttributesMap = {
|
|||||||
id_emailAddress: EmailAddress(),
|
id_emailAddress: EmailAddress(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
certificateAttributesMap.update(_certificateAttributesMapUpdate)
|
||||||
|
|
||||||
|
|
||||||
# map of Certificate Extension OIDs to Extensions
|
# map of Certificate Extension OIDs to Extensions
|
||||||
|
|
||||||
certificateExtensionsMap = {
|
_certificateExtensionsMap = {
|
||||||
id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier(),
|
id_ce_authorityKeyIdentifier: AuthorityKeyIdentifier(),
|
||||||
id_ce_subjectKeyIdentifier: SubjectKeyIdentifier(),
|
id_ce_subjectKeyIdentifier: SubjectKeyIdentifier(),
|
||||||
id_ce_keyUsage: KeyUsage(),
|
id_ce_keyUsage: KeyUsage(),
|
||||||
@ -1595,3 +1613,5 @@ certificateExtensionsMap = {
|
|||||||
id_ce_invalidityDate: useful.GeneralizedTime(),
|
id_ce_invalidityDate: useful.GeneralizedTime(),
|
||||||
id_ce_certificateIssuer: GeneralNames(),
|
id_ce_certificateIssuer: GeneralNames(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
certificateExtensionsMap.update(_certificateExtensionsMap)
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Created by Stanisław Pitucha with asn1ate tool.
|
# Created by Stanisław Pitucha with asn1ate tool.
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# Cryptographic Message Syntax (CMS)
|
# Cryptographic Message Syntax (CMS)
|
||||||
#
|
#
|
||||||
|
@ -3,15 +3,21 @@
|
|||||||
# This file is part of pyasn1-modules software.
|
# This file is part of pyasn1-modules software.
|
||||||
#
|
#
|
||||||
# Created by Stanisław Pitucha with asn1ate tool.
|
# Created by Stanisław Pitucha with asn1ate tool.
|
||||||
# Copyright (c) 2005-2017, Ilya Etingof <etingof@gmail.com>
|
# Copyright (c) 2005-2018, Ilya Etingof <etingof@gmail.com>
|
||||||
# License: http://pyasn1.sf.net/license.html
|
# License: http://snmplabs.com/pyasn1/license.html
|
||||||
#
|
#
|
||||||
# Certificate Management over CMS (CMC) Updates
|
# Certificate Management over CMS (CMC) Updates
|
||||||
#
|
#
|
||||||
# ASN.1 source from:
|
# ASN.1 source from:
|
||||||
# http://www.ietf.org/rfc/rfc6402.txt
|
# 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 rfc4211
|
||||||
from pyasn1_modules import rfc5280
|
from pyasn1_modules import rfc5280
|
||||||
|
Reference in New Issue
Block a user