def _parse(self, contents): self._rawdata = contents self._tlvdata = TLV_utils.unpack(contents) tmp = TLV_utils.tlv_find_tag(self._tlvdata, 0xEA, num_results = 1) if len(tmp) == 0: raise ValueError, "Can't parse information file, tag 0xEA not found" tmp = TLV_utils.tlv_find_tag(tmp, 0x85, num_results = 1) if len(tmp) == 0: raise ValueError, "Can't parse information file, tag 0x85 not found" self._mainblob = tmp[0][2] tmp = self._mainblob some_id, tmp = tmp[:4], tmp[4:] ascii_field_len = ord(tmp[0]) tmp = tmp[1:] ascii_field, tmp = tmp[:ascii_field_len], tmp[ascii_field_len:] self._maindata = ascii_field.split(" ") if len(tmp) > 0: if tmp[0] == "\x01": tmp = tmp[1:] birthdate_bin, tmp = tmp[:4], tmp[4:] birthdate = binascii.b2a_hex(birthdate_bin) self._birthdate = datetime.date( int(birthdate[0:4]), int(birthdate[4:6]), int(birthdate[6:8]) ) if len(tmp) > 0: print "Warning: unparsed data trailing: %r" % tmp
def _parse(self, contents): self._rawdata = contents self._tlvdata = TLV_utils.unpack(contents) tmp = TLV_utils.tlv_find_tag(self._tlvdata, 0xEA, num_results=1) if len(tmp) == 0: raise ValueError, "Can't parse information file, tag 0xEA not found" tmp = TLV_utils.tlv_find_tag(tmp, 0x85, num_results=1) if len(tmp) == 0: raise ValueError, "Can't parse information file, tag 0x85 not found" self._mainblob = tmp[0][2] tmp = self._mainblob some_id, tmp = tmp[:4], tmp[4:] ascii_field_len = ord(tmp[0]) tmp = tmp[1:] ascii_field, tmp = tmp[:ascii_field_len], tmp[ascii_field_len:] self._maindata = ascii_field.split(" ") if len(tmp) > 0: if tmp[0] == "\x01": tmp = tmp[1:] birthdate_bin, tmp = tmp[:4], tmp[4:] birthdate = binascii.b2a_hex(birthdate_bin) self._birthdate = datetime.date(int(birthdate[0:4]), int(birthdate[4:6]), int(birthdate[6:8])) if len(tmp) > 0: print "Warning: unparsed data trailing: %r" % tmp
def set_passport(self, passport): self.passport = passport for sources, transform, destinations in self.PROPERTY_TRANSFORMATIONS: values = [getattr(passport, src) for src in sources] transformed = transform(passport, values) for index, dst in enumerate(destinations): widget = self.main_window_xml.get_widget(dst) if not self.format_strings.has_key(dst): self.format_strings[dst] = widget.get_label() widget.set_label( self.format_strings[dst] % transformed[index] ) data = [] if hasattr(passport, "dg2_cbeff") and passport.dg2_cbeff is not None: for biometric in passport.dg2_cbeff.biometrics: data = data + [(a,b,"Encoded Face") for (a,b) in biometric.get_images()] for dg, tag, type in ( ("dg5", 0x5F40, "Displayed Portrait"), ("dg7", 0x5F43, "Displayed Signature or Usual Mark") ): if hasattr(passport, "%s_tlv" % dg): structure = getattr(passport, "%s_tlv" % dg) if structure is not None: hits = TLV_utils.tlv_find_tag(structure, tag) for t,l,v in hits: data.append( ("jpg",v,type) ) self._set_images(data)
def __init__(self, structure, top_tag = 0x7F60): "Create a new CBEFF instance from a nested TLV structure (as returned by TLV_utils.unpack)." self.biometrics = [] self.unknown_biometrics = [] blocks = TLV_utils.tlv_find_tag(structure, top_tag) for block in blocks: self.addbiometric(block[2])
def __init__(self, structure, top_tag=0x7F60): "Create a new CBEFF instance from a nested TLV structure (as returned by TLV_utils.unpack)." self.biometrics = [] self.unknown_biometrics = [] blocks = TLV_utils.tlv_find_tag(structure, top_tag) for block in blocks: self.addbiometric(block[2])
def parse_DG1(self, contents): structure = TLV_utils.unpack(contents) try: mrz = TLV_utils.tlv_find_tag(structure, 0x5F1F, 1)[0][2] except IndexError: raise PassportParseError, "Could not find MRZ information in DG1" # Length of an MRZ line is either 30+5 or 31+5 or 39+5, depending on document type. (LDS technical report 2004, section 16.1) mrz_data = (mrz[:len(mrz)/2], mrz[len(mrz)/2:]) self.dg1_mrz = mrz_data self._parse_mrz(mrz_data)
def parse_DG1(self, contents): structure = TLV_utils.unpack(contents) try: mrz = TLV_utils.tlv_find_tag(structure, 0x5F1F, 1)[0][2] except IndexError: raise PassportParseError, "Could not find MRZ information in DG1" # Length of an MRZ line is either 30+5 or 31+5 or 39+5, depending on document type. (LDS technical report 2004, section 16.1) mrz_data = (mrz[:len(mrz) / 2], mrz[len(mrz) / 2:]) self.dg1_mrz = mrz_data self._parse_mrz(mrz_data)
def cmd_passive_auth(self, verbose=1): "Perform passive authentication" hashes = {} result = "" i = 0 for name in ("DG1", "DG2", "SOD"): fid = None for n, f in self.INTERESTING_FILES: if n == name: fid = f break if fid is None: return i += 1 result = self.open_file(fid, 0x0c) if self.check_sw(result.sw): contents, sw = self.read_binary_file() #self.last_result = R_APDU(contents + self.last_sw) if name != "SOD": hashes[i] = crypto_utils.hash("SHA", contents) else: result = self.verify_cms(contents[4:]) #print hexdump(result) #print "DG1: %s" % hexdump(hashes[i]) #print "DG2: %s" % hexdump(hashes[2]) res = TLV_utils.tlv_find_tag(TLV_utils.unpack(result), 0x04) if len(res) == 0: print "failed to verify EF.SOD" return else: print "verified EF.SOD" i = 0 for tag, length, hash in res: i += 1 if hexdump(hashes[i]) == hexdump(hash): print "DG%d hash verified: %s" % (i, binascii.b2a_hex(hash)) else: print "DG%d hash failed:" % i print "was: %s" % binascii.b2a_hex(hashes[i]) print "expected: %s" % binascii.b2a_hex(hash) return
def cmd_passive_auth(self, verbose=1): "Perform passive authentication" hashes = {} result = "" i = 0 for name in ("DG1", "DG2", "SOD"): fid = None for n, f in self.INTERESTING_FILES: if n == name: fid = f break if fid is None: return i += 1 result = self.open_file(fid, 0x0c) if self.check_sw(result.sw): contents, sw = self.read_binary_file() #self.last_result = R_APDU(contents + self.last_sw) if name != "SOD": hashes[i] = crypto_utils.hash("SHA", contents) else: result = self.verify_cms(contents[4:]) #print hexdump(result) #print "DG1: %s" % hexdump(hashes[i]) #print "DG2: %s" % hexdump(hashes[2]) res = TLV_utils.tlv_find_tag(TLV_utils.unpack(result), 0x04) if len(res) == 0: print "failed to verify EF.SOD" return else: print "verified EF.SOD" i = 0 for tag, length, hash in res: i += 1 if hexdump(hashes[i]) == hexdump(hash): print "DG%d hash verified: %s" % (i, binascii.b2a_hex(hash)) else: print "DG%d hash failed:" % i print "was: %s" % binascii.b2a_hex(hashes[i]) print "expected: %s" % binascii.b2a_hex(hash) return
def verify_cms(self, data): """Verify a pkcs7 SMIME message""" from M2Crypto import SMIME, X509, BIO import base64, TLV_utils, os data3 = "-----BEGIN PKCS7-----\n" data3 += base64.encodestring(data) data3 += "-----END PKCS7-----" #print data3 p7_bio = BIO.MemoryBuffer(data3) # Instantiate an SMIME object. s = SMIME.SMIME() # TODO: ugly hack for M2Crypto body = TLV_utils.tlv_find_tag(TLV_utils.unpack(data), 0xA0, 1)[0][2] thecert = TLV_utils.tlv_find_tag(body, 0xA0, 2)[1][2] cert_bio = BIO.MemoryBuffer(TLV_utils.pack(thecert)) # Load the signer's cert. x509 = X509.load_cert_bio(cert_bio, format=0) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) country = str(x509.get_issuer()).split('/')[1][2:] #print country cacert = country + "-cacert.der" #print cacert msgErr = "couldn't parse certificate to determine URL for CACert, search the intertubes," msg = "download CACert (convert to DER if necessary) and save it as \n\"%s\"" % cacert if not os.path.isfile(cacert): try: v = x509.get_ext("certificatePolicies").get_value() start = v.find("CPS: ") if start != -1: url = v[start + 5:-1] print "visit %s" % url, msg else: print msgErr, msg except Exception: print msgErr, msg return "" # Load the signer's CA cert. st = X509.X509_Store() #st.load_info('main') x509CA = X509.load_cert(cacert, format=0) st.add_x509(x509CA) s.set_x509_store(st) # Load the data, verify it. #p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) p7 = SMIME.load_pkcs7_bio(p7_bio) v = s.verify(p7) return v
def verify_cms(self, data): """Verify a pkcs7 SMIME message""" from M2Crypto import SMIME, X509, BIO import base64, TLV_utils, os data3 = "-----BEGIN PKCS7-----\n" data3 += base64.encodestring(data) data3 += "-----END PKCS7-----" #print data3 p7_bio = BIO.MemoryBuffer(data3) # Instantiate an SMIME object. s = SMIME.SMIME() # TODO: ugly hack for M2Crypto body = TLV_utils.tlv_find_tag(TLV_utils.unpack(data), 0xA0, 1)[0][2] thecert = TLV_utils.tlv_find_tag(body, 0xA0, 2)[1][2] cert_bio = BIO.MemoryBuffer(TLV_utils.pack(thecert)) # Load the signer's cert. x509 = X509.load_cert_bio(cert_bio, format=0) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) country = str(x509.get_issuer()).split('/')[1][2:] #print country cacert = country + "-cacert.der" #print cacert msgErr = "couldn't parse certificate to determine URL for CACert, search the intertubes," msg = "download CACert (convert to DER if necessary) and save it as \n\"%s\"" % cacert if not os.path.isfile(cacert): try: v = x509.get_ext("certificatePolicies").get_value() start = v.find("CPS: ") if start != -1: url = v[start + 5:-1] print "visit %s" % url, msg else: print msgErr, msg except Exception: print msgErr, msg return "" # Load the signer's CA cert. st = X509.X509_Store() #st.load_info('main') x509CA = X509.load_cert(cacert, format=0) st.add_x509(x509CA) s.set_x509_store(st) # Load the data, verify it. #p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) p7 = SMIME.load_pkcs7_bio(p7_bio) v = s.verify(p7) return v