4
4
# made available under the MIT license. Consult the file "LICENSE" that is
5
5
# distributed together with this file for the exact licensing terms.
6
6
#
7
- # Python-ASN1 is copyright (c) 2007-2016 by the Python-ASN1 authors. See the
7
+ # Python-ASN1 is copyright (c) 2007-2025 by the Python-ASN1 authors. See the
8
8
# file "AUTHORS" for a complete overview.
9
9
10
10
"""
24
24
from builtins import str
25
25
from contextlib import contextmanager
26
26
from enum import IntEnum
27
- from numbers import Number
28
27
29
28
__version__ = "2.7.1"
30
29
@@ -60,31 +59,40 @@ class Classes(IntEnum):
60
59
61
60
62
61
Tag = collections .namedtuple ('Tag' , 'nr typ cls' )
63
- """A named tuple to represent ASN.1 tags as returned by `Decoder.peek()` and
64
- `Decoder.read()`."""
62
+ """
63
+ A named tuple to represent ASN.1 tags as returned by `Decoder.peek()` and
64
+ `Decoder.read()`.
65
+ """
65
66
66
67
67
68
class Error (Exception ):
68
- """ASN.11 encoding or decoding error."""
69
+ """
70
+ ASN.11 encoding or decoding error.
71
+ """
69
72
70
73
71
74
class Encoder (object ):
72
- """ASN.1 encoder. Uses DER encoding.
75
+ """
76
+ ASN.1 encoder. Uses DER encoding.
73
77
"""
74
78
75
79
def __init__ (self ): # type: () -> None
76
- """Constructor."""
80
+ """
81
+ Constructor.
82
+ """
77
83
self .m_stack = None
78
84
79
85
def start (self ): # type: () -> None
80
- """This method instructs the encoder to start encoding a new ASN.1
86
+ """
87
+ This method instructs the encoder to start encoding a new ASN.1
81
88
output. This method may be called at any time to reset the encoder,
82
89
and resets the current output (if any).
83
90
"""
84
91
self .m_stack = [[]]
85
92
86
93
def enter (self , nr , cls = None ): # type: (int, int) -> None
87
- """This method starts the construction of a constructed type.
94
+ """
95
+ This method starts the construction of a constructed type.
88
96
89
97
Args:
90
98
nr (int): The desired ASN.1 type. Use ``Numbers`` enumeration.
@@ -107,7 +115,8 @@ def enter(self, nr, cls=None): # type: (int, int) -> None
107
115
self .m_stack .append ([])
108
116
109
117
def leave (self ): # type: () -> None
110
- """This method completes the construction of a constructed type and
118
+ """
119
+ This method completes the construction of a constructed type and
111
120
writes the encoded representation to the output buffer.
112
121
"""
113
122
if self .m_stack is None :
@@ -121,7 +130,8 @@ def leave(self): # type: () -> None
121
130
122
131
@contextmanager
123
132
def construct (self , nr , cls = None ): # type: (int, int) -> None
124
- """This method - context manager calls enter and leave methods,
133
+ """
134
+ This method - context manager calls enter and leave methods,
125
135
for better code mapping.
126
136
127
137
Usage:
@@ -160,7 +170,8 @@ def construct(self, nr, cls=None): # type: (int, int) -> None
160
170
self .leave ()
161
171
162
172
def write (self , value , nr = None , typ = None , cls = None ): # type: (object, int, int, int) -> None
163
- """This method encodes one ASN.1 tag and writes it to the output buffer.
173
+ """
174
+ This method encodes one ASN.1 tag and writes it to the output buffer.
164
175
165
176
Note:
166
177
Normally, ``value`` will be the only parameter to this method.
@@ -224,7 +235,8 @@ def write(self, value, nr=None, typ=None, cls=None): # type: (object, int, int,
224
235
self ._emit (value )
225
236
226
237
def output (self ): # type: () -> bytes
227
- """This method returns the encoded ASN.1 data as plain Python ``bytes``.
238
+ """
239
+ This method returns the encoded ASN.1 data as plain Python ``bytes``.
228
240
This method can be called multiple times, also during encoding.
229
241
In the latter case the data that has been encoded so far is
230
242
returned.
@@ -403,15 +415,18 @@ def _encode_object_identifier(self, oid): # type: (str) -> bytes
403
415
404
416
405
417
class Decoder (object ):
406
- """ASN.1 decoder. Understands BER (and DER which is a subset)."""
418
+ """
419
+ ASN.1 decoder. Understands BER (and DER which is a subset).
420
+ """
407
421
408
422
def __init__ (self ): # type: () -> None
409
423
"""Constructor."""
410
424
self .m_stack = None
411
425
self .m_tag = None
412
426
413
427
def start (self , data ): # type: (bytes) -> None
414
- """This method instructs the decoder to start decoding the ASN.1 input
428
+ """
429
+ This method instructs the decoder to start decoding the ASN.1 input
415
430
``data``, which must be a passed in as plain Python bytes.
416
431
This method may be called at any time to start a new decoding job.
417
432
If this method is called while currently decoding another input, that
@@ -436,7 +451,8 @@ def start(self, data): # type: (bytes) -> None
436
451
self .m_tag = None
437
452
438
453
def peek (self ): # type: () -> Tag
439
- """This method returns the current ASN.1 tag (i.e. the tag that a
454
+ """
455
+ This method returns the current ASN.1 tag (i.e. the tag that a
440
456
subsequent `Decoder.read()` call would return) without updating the
441
457
decoding offset. In case no more data is available from the input,
442
458
this method returns ``None`` to signal end-of-file.
@@ -466,7 +482,8 @@ def peek(self): # type: () -> Tag
466
482
return self .m_tag
467
483
468
484
def read (self , tagnr = None ): # type: (Number) -> (Tag, any)
469
- """This method decodes one ASN.1 tag from the input and returns it as a
485
+ """
486
+ This method decodes one ASN.1 tag from the input and returns it as a
470
487
``(tag, value)`` tuple. ``tag`` is a 3-tuple ``(nr, typ, cls)``,
471
488
while ``value`` is a Python object representing the ASN.1 value.
472
489
The offset in the input is increased so that the next `Decoder.read()`
@@ -492,15 +509,17 @@ def read(self, tagnr=None): # type: (Number) -> (Tag, any)
492
509
return tag , value
493
510
494
511
def eof (self ): # type: () -> bool
495
- """Return True if we are at the end of input.
512
+ """
513
+ Return True if we are at the end of input.
496
514
497
515
Returns:
498
516
bool: True if all input has been decoded, and False otherwise.
499
517
"""
500
518
return self ._end_of_input ()
501
519
502
520
def enter (self ): # type: () -> None
503
- """This method enters the constructed type that is at the current
521
+ """
522
+ This method enters the constructed type that is at the current
504
523
decoding offset.
505
524
506
525
Note:
@@ -521,7 +540,8 @@ def enter(self): # type: () -> None
521
540
self .m_tag = None
522
541
523
542
def leave (self ): # type: () -> None
524
- """This method leaves the last constructed type that was
543
+ """
544
+ This method leaves the last constructed type that was
525
545
`Decoder.enter()`-ed.
526
546
527
547
Note:
@@ -539,7 +559,9 @@ def leave(self): # type: () -> None
539
559
self .m_tag = None
540
560
541
561
def _read_tag (self ): # type: () -> Tag
542
- """Read a tag from the input."""
562
+ """
563
+ Read a tag from the input.
564
+ """
543
565
byte = self ._read_byte ()
544
566
cls = byte & 0xc0
545
567
typ = byte & 0x20
@@ -554,7 +576,9 @@ def _read_tag(self): # type: () -> Tag
554
576
return Tag (nr = nr , typ = typ , cls = cls )
555
577
556
578
def _read_length (self ): # type: () -> int
557
- """Read a length from the input."""
579
+ """
580
+ Read a length from the input.
581
+ """
558
582
byte = self ._read_byte ()
559
583
if byte & 0x80 :
560
584
count = byte & 0x7f
@@ -573,7 +597,9 @@ def _read_length(self): # type: () -> int
573
597
return length
574
598
575
599
def _read_value (self , cls , nr , length ): # type: (int, int, int) -> any
576
- """Read a value from the input."""
600
+ """
601
+ Read a value from the input.
602
+ """
577
603
bytes_data = self ._read_bytes (length )
578
604
if cls != Classes .Universal :
579
605
value = bytes_data
@@ -598,7 +624,9 @@ def _read_value(self, cls, nr, length): # type: (int, int, int) -> any
598
624
return value
599
625
600
626
def _read_byte (self ): # type: () -> int
601
- """Return the next input byte, or raise an error on end-of-input."""
627
+ """
628
+ Return the next input byte, or raise an error on end-of-input.
629
+ """
602
630
index , input_data = self .m_stack [- 1 ]
603
631
try :
604
632
byte = input_data [index ]
@@ -608,8 +636,10 @@ def _read_byte(self): # type: () -> int
608
636
return byte
609
637
610
638
def _read_bytes (self , count ): # type: (int) -> bytes
611
- """Return the next ``count`` bytes of input. Raise error on
612
- end-of-input."""
639
+ """
640
+ Return the next ``count`` bytes of input. Raise error on
641
+ end-of-input.
642
+ """
613
643
index , input_data = self .m_stack [- 1 ]
614
644
bytes_data = input_data [index :index + count ]
615
645
if len (bytes_data ) != count :
@@ -618,14 +648,18 @@ def _read_bytes(self, count): # type: (int) -> bytes
618
648
return bytes_data
619
649
620
650
def _end_of_input (self ): # type: () -> bool
621
- """Return True if we are at the end of input."""
651
+ """
652
+ Return True if we are at the end of input.
653
+ """
622
654
index , input_data = self .m_stack [- 1 ]
623
655
assert not index > len (input_data )
624
656
return index == len (input_data )
625
657
626
658
@staticmethod
627
659
def _decode_boolean (bytes_data ): # type: (bytes) -> bool
628
- """Decode a boolean value."""
660
+ """
661
+ Decode a boolean value.
662
+ """
629
663
if len (bytes_data ) != 1 :
630
664
raise Error ('ASN1 syntax error' )
631
665
if bytes_data [0 ] == 0 :
@@ -634,7 +668,9 @@ def _decode_boolean(bytes_data): # type: (bytes) -> bool
634
668
635
669
@staticmethod
636
670
def _decode_integer (bytes_data ): # type: (bytes) -> int
637
- """Decode an integer value."""
671
+ """
672
+ Decode an integer value.
673
+ """
638
674
values = [int (b ) for b in bytes_data ]
639
675
# check if the integer is normalized
640
676
if len (values ) > 1 and (values [0 ] == 0xff and values [1 ] & 0x80 or values [0 ] == 0x00 and not (values [1 ] & 0x80 )):
@@ -663,19 +699,25 @@ def _decode_integer(bytes_data): # type: (bytes) -> int
663
699
664
700
@staticmethod
665
701
def _decode_octet_string (bytes_data ): # type: (bytes) -> bytes
666
- """Decode an octet string."""
702
+ """
703
+ Decode an octet string.
704
+ """
667
705
return bytes_data
668
706
669
707
@staticmethod
670
708
def _decode_null (bytes_data ): # type: (bytes) -> any
671
- """Decode a Null value."""
709
+ """
710
+ Decode a Null value.
711
+ """
672
712
if len (bytes_data ) != 0 :
673
713
raise Error ('ASN1 syntax error' )
674
714
return None
675
715
676
716
@staticmethod
677
717
def _decode_object_identifier (bytes_data ): # type: (bytes) -> str
678
- """Decode an object identifier."""
718
+ """
719
+ Decode an object identifier.
720
+ """
679
721
result = []
680
722
value = 0
681
723
for i in range (len (bytes_data )):
@@ -697,12 +739,16 @@ def _decode_object_identifier(bytes_data): # type: (bytes) -> str
697
739
698
740
@staticmethod
699
741
def _decode_printable_string (bytes_data ): # type: (bytes) -> str
700
- """Decode a printable string."""
742
+ """
743
+ Decode a printable string.
744
+ """
701
745
return bytes_data .decode ('utf-8' )
702
746
703
747
@staticmethod
704
748
def _decode_bitstring (bytes_data ): # type: (bytes) -> str
705
- """Decode a bitstring."""
749
+ """
750
+ Decode a bitstring.
751
+ """
706
752
if len (bytes_data ) == 0 :
707
753
raise Error ('ASN1 syntax error' )
708
754
0 commit comments