root / snf-cyclades-app / synnefo / userdata / asn1.py @ 4911365b
History | View | Annotate | Download (5 kB)
1 | 8bf3a249 | Kostas Papadimitriou | # ===================================================================
|
---|---|---|---|
2 | 8bf3a249 | Kostas Papadimitriou | # The contents of this file are dedicated to the public domain. To
|
3 | 8bf3a249 | Kostas Papadimitriou | # the extent that dedication to the public domain is not available,
|
4 | 8bf3a249 | Kostas Papadimitriou | # everyone is granted a worldwide, perpetual, royalty-free,
|
5 | 8bf3a249 | Kostas Papadimitriou | # non-exclusive license to exercise all rights associated with the
|
6 | 8bf3a249 | Kostas Papadimitriou | # contents of this file for any purpose whatsoever.
|
7 | 8bf3a249 | Kostas Papadimitriou | # No rights are reserved.
|
8 | 8bf3a249 | Kostas Papadimitriou | #
|
9 | 8bf3a249 | Kostas Papadimitriou | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
10 | 8bf3a249 | Kostas Papadimitriou | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
11 | 8bf3a249 | Kostas Papadimitriou | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
12 | 8bf3a249 | Kostas Papadimitriou | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
13 | 8bf3a249 | Kostas Papadimitriou | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
14 | 8bf3a249 | Kostas Papadimitriou | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
15 | 8bf3a249 | Kostas Papadimitriou | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
16 | 8bf3a249 | Kostas Papadimitriou | # SOFTWARE.
|
17 | 8bf3a249 | Kostas Papadimitriou | # ===================================================================
|
18 | 8bf3a249 | Kostas Papadimitriou | |
19 | 8bf3a249 | Kostas Papadimitriou | from Crypto.Util.number import long_to_bytes, bytes_to_long |
20 | 8bf3a249 | Kostas Papadimitriou | |
21 | 8bf3a249 | Kostas Papadimitriou | __all__ = [ 'DerObject', 'DerInteger', 'DerSequence' ] |
22 | 8bf3a249 | Kostas Papadimitriou | |
23 | 8bf3a249 | Kostas Papadimitriou | class DerObject: |
24 | 8bf3a249 | Kostas Papadimitriou | typeTags = { 'SEQUENCE':'\x30', 'BIT STRING':'\x03', 'INTEGER':'\x02' } |
25 | 8bf3a249 | Kostas Papadimitriou | |
26 | 8bf3a249 | Kostas Papadimitriou | def __init__(self, ASN1Type=None): |
27 | 8bf3a249 | Kostas Papadimitriou | self.typeTag = self.typeTags.get(ASN1Type, ASN1Type) |
28 | 8bf3a249 | Kostas Papadimitriou | self.payload = '' |
29 | 8bf3a249 | Kostas Papadimitriou | |
30 | 8bf3a249 | Kostas Papadimitriou | def _lengthOctets(self, payloadLen): |
31 | 8bf3a249 | Kostas Papadimitriou | '''
|
32 | 8bf3a249 | Kostas Papadimitriou | Return an octet string that is suitable for the BER/DER
|
33 | 8bf3a249 | Kostas Papadimitriou | length element if the relevant payload is of the given
|
34 | 8bf3a249 | Kostas Papadimitriou | size (in bytes).
|
35 | 8bf3a249 | Kostas Papadimitriou | '''
|
36 | 8bf3a249 | Kostas Papadimitriou | if payloadLen>127: |
37 | 8bf3a249 | Kostas Papadimitriou | encoding = long_to_bytes(payloadLen) |
38 | 8bf3a249 | Kostas Papadimitriou | return chr(len(encoding)+128) + encoding |
39 | 8bf3a249 | Kostas Papadimitriou | return chr(payloadLen) |
40 | 8bf3a249 | Kostas Papadimitriou | |
41 | 8bf3a249 | Kostas Papadimitriou | def encode(self): |
42 | 8bf3a249 | Kostas Papadimitriou | return self.typeTag + self._lengthOctets(len(self.payload)) + self.payload |
43 | 8bf3a249 | Kostas Papadimitriou | |
44 | 8bf3a249 | Kostas Papadimitriou | def _decodeLen(self, idx, str): |
45 | 8bf3a249 | Kostas Papadimitriou | '''
|
46 | 8bf3a249 | Kostas Papadimitriou | Given a string and an index to a DER LV,
|
47 | 8bf3a249 | Kostas Papadimitriou | this function returns a tuple with the length of V
|
48 | 8bf3a249 | Kostas Papadimitriou | and an index to the first byte of it.
|
49 | 8bf3a249 | Kostas Papadimitriou | '''
|
50 | 8bf3a249 | Kostas Papadimitriou | length = ord(str[idx]) |
51 | 8bf3a249 | Kostas Papadimitriou | if length<=127: |
52 | 8bf3a249 | Kostas Papadimitriou | return (length,idx+1) |
53 | 8bf3a249 | Kostas Papadimitriou | else:
|
54 | 8bf3a249 | Kostas Papadimitriou | payloadLength = bytes_to_long(str[idx+1:idx+1+(length & 0x7F)]) |
55 | 8bf3a249 | Kostas Papadimitriou | if payloadLength<=127: |
56 | 8bf3a249 | Kostas Papadimitriou | raise ValueError("Not a DER length tag.") |
57 | 8bf3a249 | Kostas Papadimitriou | return (payloadLength, idx+1+(length & 0x7F)) |
58 | 8bf3a249 | Kostas Papadimitriou | |
59 | 8bf3a249 | Kostas Papadimitriou | def decode(self, input, noLeftOvers=0): |
60 | 8bf3a249 | Kostas Papadimitriou | try:
|
61 | 8bf3a249 | Kostas Papadimitriou | self.typeTag = input[0] |
62 | 8bf3a249 | Kostas Papadimitriou | if (ord(self.typeTag) & 0x1F)==0x1F: |
63 | 8bf3a249 | Kostas Papadimitriou | raise ValueError("Unsupported DER tag") |
64 | 8bf3a249 | Kostas Papadimitriou | (length,idx) = self._decodeLen(1,input) |
65 | 8bf3a249 | Kostas Papadimitriou | if noLeftOvers and len(input) != (idx+length): |
66 | 8bf3a249 | Kostas Papadimitriou | raise ValueError("Not a DER structure") |
67 | 8bf3a249 | Kostas Papadimitriou | self.payload = input[idx:idx+length] |
68 | 8bf3a249 | Kostas Papadimitriou | except IndexError: |
69 | 8bf3a249 | Kostas Papadimitriou | raise ValueError("Not a valid DER SEQUENCE.") |
70 | 8bf3a249 | Kostas Papadimitriou | return idx+length
|
71 | 8bf3a249 | Kostas Papadimitriou | |
72 | 8bf3a249 | Kostas Papadimitriou | class DerInteger(DerObject): |
73 | 8bf3a249 | Kostas Papadimitriou | def __init__(self, value = 0): |
74 | 8bf3a249 | Kostas Papadimitriou | DerObject.__init__(self, 'INTEGER') |
75 | 8bf3a249 | Kostas Papadimitriou | self.value = value
|
76 | 8bf3a249 | Kostas Papadimitriou | |
77 | 8bf3a249 | Kostas Papadimitriou | def encode(self): |
78 | 8bf3a249 | Kostas Papadimitriou | self.payload = long_to_bytes(self.value) |
79 | 8bf3a249 | Kostas Papadimitriou | if ord(self.payload[0])>127: |
80 | 8bf3a249 | Kostas Papadimitriou | self.payload = '\x00' + self.payload |
81 | 8bf3a249 | Kostas Papadimitriou | return DerObject.encode(self) |
82 | 8bf3a249 | Kostas Papadimitriou | |
83 | 8bf3a249 | Kostas Papadimitriou | def decode(self, input, noLeftOvers=0): |
84 | 8bf3a249 | Kostas Papadimitriou | tlvLength = DerObject.decode(self, input,noLeftOvers) |
85 | 8bf3a249 | Kostas Papadimitriou | if ord(self.payload[0])>127: |
86 | 8bf3a249 | Kostas Papadimitriou | raise ValueError ("Negative INTEGER.") |
87 | 8bf3a249 | Kostas Papadimitriou | self.value = bytes_to_long(self.payload) |
88 | 8bf3a249 | Kostas Papadimitriou | return tlvLength
|
89 | 8bf3a249 | Kostas Papadimitriou | |
90 | 8bf3a249 | Kostas Papadimitriou | class DerSequence(DerObject): |
91 | 8bf3a249 | Kostas Papadimitriou | def __init__(self): |
92 | 8bf3a249 | Kostas Papadimitriou | DerObject.__init__(self, 'SEQUENCE') |
93 | 8bf3a249 | Kostas Papadimitriou | self._seq = []
|
94 | 8bf3a249 | Kostas Papadimitriou | def __delitem__(self, n): |
95 | 8bf3a249 | Kostas Papadimitriou | del self._seq[n] |
96 | 8bf3a249 | Kostas Papadimitriou | def __getitem__(self, n): |
97 | 8bf3a249 | Kostas Papadimitriou | return self._seq[n] |
98 | 8bf3a249 | Kostas Papadimitriou | def __setitem__(self, key, value): |
99 | 8bf3a249 | Kostas Papadimitriou | self._seq[key] = value
|
100 | 8bf3a249 | Kostas Papadimitriou | def __setslice__(self,i,j,sequence): |
101 | 8bf3a249 | Kostas Papadimitriou | self._seq[i:j] = sequence
|
102 | 8bf3a249 | Kostas Papadimitriou | def __delslice__(self,i,j): |
103 | 8bf3a249 | Kostas Papadimitriou | del self._seq[i:j] |
104 | 8bf3a249 | Kostas Papadimitriou | def __getslice__(self, i, j): |
105 | 8bf3a249 | Kostas Papadimitriou | return self._seq[max(0, i):max(0, j)] |
106 | 8bf3a249 | Kostas Papadimitriou | def __len__(self): |
107 | 8bf3a249 | Kostas Papadimitriou | return len(self._seq) |
108 | 8bf3a249 | Kostas Papadimitriou | def append(self, item): |
109 | 8bf3a249 | Kostas Papadimitriou | return self._seq.append(item) |
110 | 8bf3a249 | Kostas Papadimitriou | |
111 | 8bf3a249 | Kostas Papadimitriou | def hasOnlyInts(self): |
112 | 8bf3a249 | Kostas Papadimitriou | if not self._seq: return 0 |
113 | 8bf3a249 | Kostas Papadimitriou | test = 0
|
114 | 8bf3a249 | Kostas Papadimitriou | for item in self._seq: |
115 | 8bf3a249 | Kostas Papadimitriou | try:
|
116 | 8bf3a249 | Kostas Papadimitriou | test += item |
117 | 8bf3a249 | Kostas Papadimitriou | except TypeError: |
118 | 8bf3a249 | Kostas Papadimitriou | return 0 |
119 | 8bf3a249 | Kostas Papadimitriou | return 1 |
120 | 8bf3a249 | Kostas Papadimitriou | |
121 | 8bf3a249 | Kostas Papadimitriou | def encode(self): |
122 | 8bf3a249 | Kostas Papadimitriou | '''
|
123 | 8bf3a249 | Kostas Papadimitriou | Return the DER encoding for the ASN.1 SEQUENCE containing
|
124 | 8bf3a249 | Kostas Papadimitriou | the non-negative integers and longs added to this object.
|
125 | 8bf3a249 | Kostas Papadimitriou | '''
|
126 | 8bf3a249 | Kostas Papadimitriou | self.payload = '' |
127 | 8bf3a249 | Kostas Papadimitriou | for item in self._seq: |
128 | 8bf3a249 | Kostas Papadimitriou | try:
|
129 | 8bf3a249 | Kostas Papadimitriou | self.payload += item
|
130 | 8bf3a249 | Kostas Papadimitriou | except:
|
131 | 8bf3a249 | Kostas Papadimitriou | try:
|
132 | 8bf3a249 | Kostas Papadimitriou | self.payload += DerInteger(item).encode()
|
133 | 8bf3a249 | Kostas Papadimitriou | except:
|
134 | 8bf3a249 | Kostas Papadimitriou | raise ValueError("Trying to DER encode an unknown object") |
135 | 8bf3a249 | Kostas Papadimitriou | return DerObject.encode(self) |
136 | 8bf3a249 | Kostas Papadimitriou | |
137 | 8bf3a249 | Kostas Papadimitriou | def decode(self, input,noLeftOvers=0): |
138 | 8bf3a249 | Kostas Papadimitriou | '''
|
139 | 8bf3a249 | Kostas Papadimitriou | This function decodes the given string into a sequence of
|
140 | 8bf3a249 | Kostas Papadimitriou | ASN.1 objects. Yet, we only know about unsigned INTEGERs.
|
141 | 8bf3a249 | Kostas Papadimitriou | Any other type is stored as its rough TLV. In the latter
|
142 | 8bf3a249 | Kostas Papadimitriou | case, the correctectness of the TLV is not checked.
|
143 | 8bf3a249 | Kostas Papadimitriou | '''
|
144 | 8bf3a249 | Kostas Papadimitriou | self._seq = []
|
145 | 8bf3a249 | Kostas Papadimitriou | try:
|
146 | 8bf3a249 | Kostas Papadimitriou | tlvLength = DerObject.decode(self, input,noLeftOvers) |
147 | 8bf3a249 | Kostas Papadimitriou | if self.typeTag!=self.typeTags['SEQUENCE']: |
148 | 8bf3a249 | Kostas Papadimitriou | raise ValueError("Not a DER SEQUENCE.") |
149 | 8bf3a249 | Kostas Papadimitriou | # Scan one TLV at once
|
150 | 8bf3a249 | Kostas Papadimitriou | idx = 0
|
151 | 8bf3a249 | Kostas Papadimitriou | while idx<len(self.payload): |
152 | 8bf3a249 | Kostas Papadimitriou | typeTag = self.payload[idx]
|
153 | 8bf3a249 | Kostas Papadimitriou | if typeTag==self.typeTags['INTEGER']: |
154 | 8bf3a249 | Kostas Papadimitriou | newInteger = DerInteger() |
155 | 8bf3a249 | Kostas Papadimitriou | idx += newInteger.decode(self.payload[idx:])
|
156 | 8bf3a249 | Kostas Papadimitriou | self._seq.append(newInteger.value)
|
157 | 8bf3a249 | Kostas Papadimitriou | else:
|
158 | 8bf3a249 | Kostas Papadimitriou | itemLen,itemIdx = self._decodeLen(idx+1,self.payload) |
159 | 8bf3a249 | Kostas Papadimitriou | self._seq.append(self.payload[idx:itemIdx+itemLen]) |
160 | 8bf3a249 | Kostas Papadimitriou | idx = itemIdx + itemLen |
161 | 8bf3a249 | Kostas Papadimitriou | except IndexError: |
162 | 8bf3a249 | Kostas Papadimitriou | raise ValueError("Not a valid DER SEQUENCE.") |
163 | 8bf3a249 | Kostas Papadimitriou | return tlvLength
|