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