Package dkim :: Module asn1
[hide private]
[frames] | no frames]

Source Code for Module dkim.asn1

  1  # This software is provided 'as-is', without any express or implied 
  2  # warranty.  In no event will the author be held liable for any damages 
  3  # arising from the use of this software. 
  4  # 
  5  # Permission is granted to anyone to use this software for any purpose, 
  6  # including commercial applications, and to alter it and redistribute it 
  7  # freely, subject to the following restrictions: 
  8  # 
  9  # 1. The origin of this software must not be misrepresented; you must not 
 10  #    claim that you wrote the original software. If you use this software 
 11  #    in a product, an acknowledgment in the product documentation would be 
 12  #    appreciated but is not required. 
 13  # 2. Altered source versions must be plainly marked as such, and must not be 
 14  #    misrepresented as being the original software. 
 15  # 3. This notice may not be removed or altered from any source distribution. 
 16  # 
 17  # Copyright (c) 2008 Greg Hewgill http://hewgill.com 
 18  # 
 19  # This has been modified from the original software. 
 20  # Copyright (c) 2011 William Grant <me@williamgrant.id.au> 
 21   
 22  __all__ = [ 
 23      'asn1_build', 
 24      'asn1_parse', 
 25      'ASN1FormatError', 
 26      'BIT_STRING', 
 27      'INTEGER', 
 28      'SEQUENCE', 
 29      'OBJECT_IDENTIFIER', 
 30      'OCTET_STRING', 
 31      'NULL', 
 32      ] 
 33   
 34  INTEGER = 0x02 
 35  BIT_STRING = 0x03 
 36  OCTET_STRING = 0x04 
 37  NULL = 0x05 
 38  OBJECT_IDENTIFIER = 0x06 
 39  SEQUENCE = 0x30 
 40   
 41   
42 -class ASN1FormatError(Exception):
43 pass
44 45
46 -def asn1_parse(template, data):
47 """Parse a data structure according to an ASN.1 template. 48 49 @param template: tuples comprising the ASN.1 template 50 @param data: byte string data to parse 51 @return: decoded structure 52 """ 53 data = bytearray(data) 54 r = [] 55 i = 0 56 try: 57 for t in template: 58 tag = data[i] 59 i += 1 60 if tag == t[0]: 61 length = data[i] 62 i += 1 63 if length & 0x80: 64 n = length & 0x7f 65 length = 0 66 for j in range(n): 67 length = (length << 8) | data[i] 68 i += 1 69 if tag == INTEGER: 70 n = 0 71 for j in range(length): 72 n = (n << 8) | data[i] 73 i += 1 74 r.append(n) 75 elif tag == BIT_STRING: 76 r.append(data[i:i+length]) 77 i += length 78 elif tag == NULL: 79 assert length == 0 80 r.append(None) 81 elif tag == OBJECT_IDENTIFIER: 82 r.append(data[i:i+length]) 83 i += length 84 elif tag == SEQUENCE: 85 r.append(asn1_parse(t[1], data[i:i+length])) 86 i += length 87 else: 88 raise ASN1FormatError( 89 "Unexpected tag in template: %02x" % tag) 90 else: 91 raise ASN1FormatError( 92 "Unexpected tag (got %02x, expecting %02x)" % (tag, t[0])) 93 return r 94 except IndexError: 95 raise ASN1FormatError("Data truncated at byte %d"%i)
96 97
98 -def asn1_length(n):
99 """Return a string representing a field length in ASN.1 format. 100 101 @param n: integer field length 102 @return: ASN.1 field length 103 """ 104 assert n >= 0 105 if n < 0x7f: 106 return bytearray([n]) 107 r = bytearray() 108 while n > 0: 109 r.insert(n & 0xff) 110 n >>= 8 111 return r
112 113
114 -def asn1_encode(type, data):
115 length = asn1_length(len(data)) 116 length.insert(0, type) 117 length.extend(data) 118 return length
119 120
121 -def asn1_build(node):
122 """Build a DER-encoded ASN.1 data structure. 123 124 @param node: (type, data) tuples comprising the ASN.1 structure 125 @return: DER-encoded ASN.1 byte string 126 """ 127 if node[0] == OCTET_STRING: 128 return asn1_encode(OCTET_STRING, node[1]) 129 if node[0] == NULL: 130 assert node[1] is None 131 return asn1_encode(NULL, b'') 132 elif node[0] == OBJECT_IDENTIFIER: 133 return asn1_encode(OBJECT_IDENTIFIER, node[1]) 134 elif node[0] == SEQUENCE: 135 r = bytearray() 136 for x in node[1]: 137 r += asn1_build(x) 138 return asn1_encode(SEQUENCE, r) 139 else: 140 raise ASN1FormatError("Unexpected tag in template: %02x" % node[0])
141