1import logging 2import math 3 4math_ceil = math.ceil 5math_log = math.log 6 7from pypacker.structcbs import pack_B 8 9logger = logging.getLogger("pypacker") 10from_bytes = int.from_bytes 11 12""" 13Basic format: 14Type | Length | Content 15> Type 16class | P/C | Tag num | More | Tag num 17 18https://en.wikipedia.org/wiki/X.690#DER_encoding 19""" 20 21 22def encode_length_definitive(num): 23 if num < 0x80: 24 return pack_B(num) 25 else: 26 len_len_inbytes = math_ceil( math_log(num + 1, 256) ) 27 28 if len_len_inbytes > 0x7F: 29 logger.warning("Number too big for encoding") 30 31 len_bytesencoded = num.to_bytes(len_len_inbytes, "big") 32 return pack_B(0x80 + len_len_inbytes) + len_bytesencoded 33 34def decode_length_definitive(bts): 35 """ 36 bts -- [len_shortlong:1->127] where bits of len_shortlong = ABBB BBBB [CCCCCCCC]. 37 Should be 127 bytes (exact length unknown before calling) 38 return -- lengts of length, length 39 """ 40 vlen = bts[0] 41 # Defnite form: short or long 42 is_lenshort = (vlen & 0x80) == 0 43 # Length of length-bytes 44 len_len = 1 45 46 if not is_lenshort: 47 # The long form consist of 1 initial octet followed by 1 or more subsequent octets, 48 # containing the length. In the initial octet, bit 8 is 1, and bits 1-7 (excluding 49 # the values 0 and 127) encode the number of octets that follow. 50 #logger.debug("Got long format!") 51 len_octets = vlen & 0x7F 52 lenbts = bts[1: 1 + len_octets] 53 #logger.debug("len in bytes: %s" % lenbts) 54 vlen = from_bytes(lenbts, byteorder="big", signed=False) 55 #logger.debug("length longform, bytes: %r (%d) = %d" % (lenbts, len_octets, vlen)) 56 len_len += len_octets 57 return len_len, vlen 58 59def _get_der_tlv(der_bts): 60 """ 61 return -- idlen, lenlen, vlen, is_primitive 62 """ 63 off = 0 64 tagstart = off 65 is_primitive = (der_bts[off] & 0x20) == 0 66 # High tag number form 67 # If the tag number is too large for the 5-bit tag field, it has to be encoded in further octets. 68 if (der_bts[off] & 0x1F) == 0x1F: 69 #logger.warning("Got high tag form") 70 # is_hightag = True 71 off += 1 72 73 while (der_bts[off] & 0x80) != 0: 74 off += 1 75 off += 1 76 lenstart = off 77 lenlen, vlen = decode_length_definitive(der_bts[lenstart: lenstart + 127]) 78 off += lenlen 79 valuestart = off 80 81 return lenstart - tagstart, valuestart - lenstart, vlen, is_primitive 82 83class LinkedTLVList(list): 84 def __init__(self, val): 85 self._parent_list = None 86 super().__init__(val) 87 88 def set_parent(self, parent_list): 89 self._parent_list = parent_list 90 91 def get_parent(self): 92 return self._parent_list 93 94 def append(self, tlv_list): 95 tlv_list.set_parent(self) 96 super().append(tlv_list) 97 98 def is_primitive(self): 99 # tlv -> (a, b, c), on non-primitive types c will be come a list 100 return len(self) == 3 and type(self[2]) is bytes 101 102 def get_value_raw(self): 103 if len(self) == 3: 104 if self.is_primitive(): 105 return self[2] 106 else: 107 return b"".join(v.bin() for v in self[2]) 108 elif len(self) == 1: 109 # Assume list in list 110 return self[0].bin() 111 else: 112 raise Exception("%s" % self) 113 114 def bin(self): 115 if len(self) == 3: 116 if self.is_primitive(): 117 return self[0] + self[1] + self[2] 118 else: 119 type_len = self[0] + self[1] 120 value = b"".join(v.bin() for v in self[2]) 121 return type_len + value 122 elif len(self) == 1: 123 # Assume list in list 124 return self[0].bin() 125 else: 126 raise Exception("%s" % self) 127 128 def update_len_uptoroot(self): 129 self[1] = encode_length_definitive(self.get_value_bin()) 130 self.get_parent().update_len_uptoroot() 131 132 def __setitem__(self, idx, val): 133 if not is_primitive(): 134 raise Exception("Can't change non-primitive values!") 135 136 # Update lengths if primitive value changed 137 update_needed = self.is_primitive() and idx == 2 and len(val) != len(self[2]) 138 super().__setitem__(idx, val) 139 140 if update_needed: 141 logger.debug("Update of length needed") 142 self.update_len_uptoroot() 143 144 """ 145 def __getitem__(self, idx): 146 val_ret = super().__getitem__(idx) 147 148 return LinkedTLVList(val_ret) if type(val_ret) == list else val_ret 149 """ 150 151def decode_der(der_bts, rw_cb=None): 152 off = 0 153 end = len(der_bts) 154 result = LinkedTLVList([]) 155 156 while off < end: 157 taglen, lenlen, vlen, prim = _get_der_tlv(der_bts[off:]) 158 der_sub = der_bts[off + taglen + lenlen: off + taglen + lenlen + vlen] 159 160 if not prim: 161 der_sub = decode_der(der_sub, rw_cb=rw_cb) 162 163 # Results: [tag_bts, lenlen_bts, value_bts] 164 ltlv = LinkedTLVList([ 165 der_bts[off: off + taglen], 166 der_bts[off + taglen: off + taglen + lenlen], 167 der_sub] 168 ) 169 #print(ltlv) 170 result.append(ltlv) 171 off += (taglen + lenlen + vlen) 172 173 rw_cb(result) 174 175 return result 176 177""" 178>>> X.509 179 180Certificate ::= SEQUENCE { 181 tbsCertificate TBSCertificate, 182 signatureAlgorithm AlgorithmIdentifier, 183 signatureValue BIT STRING } 1843082 06eb - SEQUENCE with length 0x06eb 185 186TBSCertificate ::= SEQUENCE { 187 version [0] EXPLICIT Version DEFAULT v1, 188 serialNumber CertificateSerialNumber, 189 signature AlgorithmIdentifier, 190 issuer Name, 191 validity Validity, 192 subject Name, 193 subjectPublicKeyInfo SubjectPublicKeyInfo, 194 issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, 195 -- If present, version MUST be v2 or v3 196 subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, 197 -- If present, version MUST be v2 or v3 198 extensions [3] EXPLICIT Extensions OPTIONAL 199 -- If present, version MUST be v3 200} 201""" 202 203X509_ID_COMMONNAME = b"U\x04\x03" 204X509_ID_COUNTRYNAME = b"U\x04\x06" 205X509_ID_LOCALITYNAME = b"U\x04\x07" 206X509_ID_STATEORPROVINCENAME = b"U\x04\x08" 207X509_ID_ORGANIZATIONNAME = b"U\x04\n" 208X509_ID_ORGANIZATIONUNITNAME = b"U\x04\x0b" 209 210""" 211http://www.oid-info.com/ 212 2132.5.4.0 - id-at-objectClass 2142.5.4.1 - id-at-aliasedEntryName 2152.5.4.2 - id-at-knowldgeinformation 2162.5.4.3 - id-at-commonName 2172.5.4.4 - id-at-surname 2182.5.4.5 - id-at-serialNumber 2192.5.4.6 - id-at-countryName 2202.5.4.7 - id-at-localityName 2212.5.4.8 - id-at-stateOrProvinceName 2222.5.4.9 - id-at-streetAddress 2232.5.4.10 - id-at-organizationName 2242.5.4.11 - id-at-organizationalUnitName 2252.5.4.12 - id-at-title 2262.5.4.13 - id-at-description 2272.5.4.14 - id-at-searchGuide 2282.5.4.15 - id-at-businessCategory 2292.5.4.16 - id-at-postalAddress 2302.5.4.17 - id-at-postalCode 2312.5.4.18 - id-at-postOfficeBox 2322.5.4.19 - id-at-physicalDeliveryOfficeName 2332.5.4.20 - id-at-telephoneNumber 2342.5.4.21 - id-at-telexNumber 2352.5.4.22 - id-at-teletexTerminalIdentifier 2362.5.4.23 - id-at-facsimileTelephoneNumber 2372.5.4.24 - id-at-x121Address 2382.5.4.25 - id-at-internationalISDNNumber 2392.5.4.26 - id-at-registeredAddress 2402.5.4.27 - id-at-destinationIndicator 2412.5.4.28 - id-at-preferredDeliveryMethod 2422.5.4.29 - id-at-presentationAddress 2432.5.4.30 - id-at-supportedApplicationContext 2442.5.4.31 - id-at-member 2452.5.4.32 - id-at-owner 2462.5.4.33 - id-at-roleOccupant 2472.5.4.34 - id-at-seeAlso 2482.5.4.35 - id-at-userPassword 2492.5.4.36 - id-at-userCertificate 2502.5.4.37 - id-at-cACertificate 2512.5.4.38 - id-at-authorityRevocationList 2522.5.4.39 - id-at-certificateRevocationList 2532.5.4.40 - id-at-crossCertificatePair 2542.5.4.41 - id-at-name 2552.5.4.42 - id-at-givenName 2562.5.4.43 - id-at-initials 2572.5.4.44 - id-at-generationQualifier 2582.5.4.45 - id-at-uniqueIdentifier 2592.5.4.46 - id-at-dnQualifier 2602.5.4.47 - id-at-enhancedSearchGuide 2612.5.4.48 - id-at-protocolInformation 2622.5.4.49 - id-at-distinguishedName 2632.5.4.50 - id-at-uniqueMember 2642.5.4.51 - id-at-houseIdentifier 2652.5.4.52 - id-at-supportedAlgorithms 2662.5.4.53 - id-at-deltaRevocationList 2672.5.4.58 - Attribute Certificate attribute (id-at-attributeCertificate) 2682.5.4.65 - id-at-pseudonym 269 270 2712.5.29.1 - old Authority Key Identifier 2722.5.29.2 - old Primary Key Attributes 2732.5.29.3 - Certificate Policies 2742.5.29.4 - Primary Key Usage Restriction 2752.5.29.9 - Subject Directory Attributes 2762.5.29.14 - Subject Key Identifier 2772.5.29.15 - Key Usage 2782.5.29.16 - Private Key Usage Period 2792.5.29.17 - Subject Alternative Name 2802.5.29.18 - Issuer Alternative Name 2812.5.29.19 - Basic Constraints 2822.5.29.20 - CRL Number 2832.5.29.21 - Reason code 2842.5.29.23 - Hold Instruction Code 2852.5.29.24 - Invalidity Date 2862.5.29.27 - Delta CRL indicator 2872.5.29.28 - Issuing Distribution Point 2882.5.29.29 - Certificate Issuer 2892.5.29.30 - Name Constraints 2902.5.29.31 - CRL Distribution Points 2912.5.29.32 - Certificate Policies 2922.5.29.33 - Policy Mappings 2932.5.29.35 - Authority Key Identifier 2942.5.29.36 - Policy Constraints 2952.5.29.37 - Extended key usage 2962.5.29.46 - FreshestCRL 2972.5.29.54 - X.509 version 3 certificate extension Inhibit Any-policy 298 299""" 300 301