def validatecertificatesignature(self, signed_cert, signing_cert): """Given a cert signed by another cert, validates the signature.""" # First the naive way -- note this does not check expiry / use etc. cert_signing = x509.load_pem_x509_certificate(ssl.DER_cert_to_PEM_cert(der_encoder.encode(signing_cert)).encode(), default_backend()) public_key = cert_signing.public_key() der_cert = der_encoder.encode(signed_cert) cert_signed = x509.load_pem_x509_certificate(ssl.DER_cert_to_PEM_cert(der_cert).encode(), default_backend()) data = cert_signed.tbs_certificate_bytes signature = cert_signed.signature new_api = hasattr(public_key, "verify") if not new_api: verifier = public_key.verifier(signature, padding.PKCS1v15(), cert_signed.signature_hash_algorithm) try: verifier.update(data) verifier.verify() except: raise Asn1Error('1: Validation of cert signature failed.') else: try: verifier = public_key.verify(signature, data, padding.PKCS1v15(), cert_signed.signature_hash_algorithm) # verifier.update(data) # verifier.verify() except: raise Asn1Error('1: Validation of cert signature failed.')
def _write(self, file, header, principal, sessions): self._pack_write(file, '!H', self._FVNO_4) self._write_header_tags(file, header) self._write_principal(file, principal) for s in sessions: self._write_principal(file, s.client) self._write_principal(file, s.service) self._write_key(file, s.key) self._write_time(file, s.auth_time) self._write_time(file, s.start_time) self._write_time(file, s.end_time) self._write_time(file, s.renew_until) self._pack_write(file, 'B', 0 if s.u2u_ticket is None else 1) self._write_ticket_flags(file, s.ticket_flags or 0) self._write_addresses(file, s.addresses or []) self._write_authdata(file, []) ticket = asn1.Ticket() s.ticket.to_asn1(ticket) self._write_data(file, encoder.encode(ticket)) if s.u2u_ticket is not None: u2u_ticket = asn1.Ticket() s.u2u_ticket.to_asn1(u2u_ticket) self._write_data(file, encoder.encode(u2u_ticket)) else: self._write_data(file, "")
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 _encode_extension(oid, critical, value): ext = rfc2459.Extension() ext['extnID'] = univ.ObjectIdentifier(oid) ext['critical'] = univ.Boolean(critical) ext['extnValue'] = univ.Any(encoder.encode(univ.OctetString(value))) ext = encoder.encode(ext) return ext
def getRevokedSerials(crl): serials = [] if None != crl[0]['tbsCertList'] and None != crl[0]['tbsCertList']['revokedCertificates']: print b64encode(encoder.encode(crl[0]['tbsCertList']['issuer'])) for cert in crl[0]['tbsCertList']['revokedCertificates']: serials.append(b64encode(encoder.encode(cert['userCertificate']))) return serials
def _build_signature(key, certreqinfo, network): secret_exponent = encoding.to_long(256, encoding.byte_to_int, key[0][1].asOctets())[0] coin = Key(secret_exponent=secret_exponent, netcode=network) print "building signature for %s address: %s" % (network, coin.address()) pubkeybitstring = (key[0].getComponentByPosition(2), key[0].getComponentByPosition(3)) certreqinfoder = encoder.encode(certreqinfo) hashvalue = SHA256.new(certreqinfoder) dgst = hashvalue.digest() dgstaslong = encoding.to_long(256, encoding.byte_to_int, dgst)[0] order2 = pycoin.ecdsa.generator_secp256k1.order() ## random sign generator = pycoin.ecdsa.generator_secp256k1 rawsig2 = randomsign(generator, secret_exponent, dgstaslong) ## deterministic sign ##rawsig2 = pycoin.ecdsa.sign(pycoin.ecdsa.generator_secp256k1, secret_exponent, dgstaslong) r2, s2 = rawsig2 print "signature: r: %x s: %x" % (r2, s2) if not pycoin.ecdsa.verify(generator, coin.public_pair(), dgstaslong, rawsig2): raise SignatureVerifyException("Generated signature r: %x s: %x does not verify against public key %s" % (r2, s2, public_pair)) signature = ECDSASigValue() signature.setComponentByName('r', r2) signature.setComponentByName('s', s2) dersig = encoder.encode(signature) signaturevalue = "'{0}'H".format(binascii.hexlify(dersig)) bitstring = univ.BitString( value=signaturevalue ) return rfc2314.Signature( bitstring )
def getRSAPublicKey(self): """ Gets an ASN.1-encoded form of this RSA key's public key. """ # Get a RSAPublicKey structure pkinfo = univ.Sequence() rsakey = self.getRSAKey() pkinfo.setComponentByPosition(0, univ.Integer(rsakey.n)) pkinfo.setComponentByPosition(1, univ.Integer(rsakey.e)) # Encode the public key info as a bit string pklong = long(encoder.encode(pkinfo).encode('hex'), 16) pkbitstring = univ.BitString("'00%s'B" % self.toBitString_(pklong)) # Get the rsaEncryption identifier: idrsaencryption = univ.ObjectIdentifier('1.2.840.113549.1.1.1') # Get the AlgorithmIdentifier for rsaEncryption idinfo = univ.Sequence() idinfo.setComponentByPosition(0, idrsaencryption) idinfo.setComponentByPosition(1, univ.Null('')) # Get the SubjectPublicKeyInfo structure publickeyinfo = univ.Sequence() publickeyinfo.setComponentByPosition(0, idinfo) publickeyinfo.setComponentByPosition(1, pkbitstring) # Encode the public key structure publickey = encoder.encode(publickeyinfo) return publickey
def api_sign_certificate(): if request.headers['Content-Type'] == 'application/json': certificate = b64decode(str(request.json.get("certificate"))) bitcoin_address = str(request.json.get("bitcoin_address")) # Get the ACA secret key f = open(ACA_KEY, "r") sk_string = f.read() f.close() sk = RSA.importKey(sk_string) # Get the certificate hash and the asn1 representation of the certificate certificate_hash = certificate_hashing(certificate) signature = sk.sign(certificate_hash, 1)[0] asn1_cert = decoder.decode(certificate, asn1Spec=Certificate())[0] # Attach the signature to the certificate bin_signature = Signature("'%s'H" % ''.join("%02X" % ord(c) for c in long_to_bytes(signature))) asn1_cert.setComponentByName("signatureValue", bin_signature) # Store the certificate der_cert = encoder.encode(asn1_cert) store_certificate(encoder.encode(asn1_cert), bitcoin_address) return b64encode(der_cert)
def getTGT(self, userName, requestPAC=True): clientName = Principal(userName, type=constants.PrincipalNameType.NT_PRINCIPAL.value) asReq = AS_REQ() domain = self.__domain.upper() serverName = Principal('krbtgt/%s' % domain, type=constants.PrincipalNameType.NT_PRINCIPAL.value) pacRequest = KERB_PA_PAC_REQUEST() pacRequest['include-pac'] = requestPAC encodedPacRequest = encoder.encode(pacRequest) asReq['pvno'] = 5 asReq['msg-type'] = int(constants.ApplicationTagNumbers.AS_REQ.value) asReq['padata'] = noValue asReq['padata'][0] = noValue asReq['padata'][0]['padata-type'] = int(constants.PreAuthenticationDataTypes.PA_PAC_REQUEST.value) asReq['padata'][0]['padata-value'] = encodedPacRequest reqBody = seq_set(asReq, 'req-body') opts = list() opts.append(constants.KDCOptions.forwardable.value) opts.append(constants.KDCOptions.renewable.value) opts.append(constants.KDCOptions.proxiable.value) reqBody['kdc-options'] = constants.encodeFlags(opts) seq_set(reqBody, 'sname', serverName.components_to_asn1) seq_set(reqBody, 'cname', clientName.components_to_asn1) if domain == '': raise Exception('Empty Domain not allowed in Kerberos') reqBody['realm'] = domain now = datetime.datetime.utcnow() + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['rtime'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) supportedCiphers = (int(constants.EncryptionTypes.rc4_hmac.value),) seq_set_iter(reqBody, 'etype', supportedCiphers) message = encoder.encode(asReq) try: r = sendReceive(message, domain, self.__kdcHost) except KerberosError, e: if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: # RC4 not available, OK, let's ask for newer types supportedCiphers = (int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value), int(constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value),) seq_set_iter(reqBody, 'etype', supportedCiphers) message = encoder.encode(asReq) r = sendReceive(message, domain, self.__kdcHost) else: raise e
def to_pem(self, pem_format='PKCS8'): if isinstance(self._prepared_key, pyrsa.PrivateKey): der = self._prepared_key.save_pkcs1(format='DER') if pem_format == 'PKCS8': pem = pyrsa_pem.save_pem(PKCS8_RSA_HEADER + der, pem_marker='PRIVATE KEY') elif pem_format == 'PKCS1': pem = pyrsa_pem.save_pem(der, pem_marker='RSA PRIVATE KEY') else: raise ValueError("Invalid pem format specified: %r" % (pem_format,)) else: if pem_format == 'PKCS8': asn_key = AsnPubKey() asn_key.setComponentByName('modulus', self._prepared_key.n) asn_key.setComponentByName('publicExponent', self._prepared_key.e) der = encoder.encode(asn_key) header = PubKeyHeader() header['oid'] = univ.ObjectIdentifier('1.2.840.113549.1.1.1') pub_key = OpenSSLPubKey() pub_key['header'] = header pub_key['key'] = univ.BitString.fromOctetString(der) der = encoder.encode(pub_key) pem = pyrsa_pem.save_pem(der, pem_marker='PUBLIC KEY') elif pem_format == 'PKCS1': der = self._prepared_key.save_pkcs1(format='DER') pem = pyrsa_pem.save_pem(der, pem_marker='RSA PUBLIC KEY') else: raise ValueError("Invalid pem format specified: %r" % (pem_format,)) return pem
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 toDER(self): tbsCertificate = rfc2459.TBSCertificate() tbsCertificate.setComponentByName('version', self.getVersion()) tbsCertificate.setComponentByName('serialNumber', self.getSerialNumber()) tbsCertificate.setComponentByName('signature', self.getSignature()) tbsCertificate.setComponentByName('issuer', self.getIssuer()) tbsCertificate.setComponentByName('validity', self.getValidity()) tbsCertificate.setComponentByName('subject', self.getSubject()) tbsCertificate.setComponentByName('subjectPublicKeyInfo', self.getSubjectPublicKeyInfo()) if self.extensions: extensions = rfc2459.Extensions().subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) count = 0 for extension in self.extensions: extensions.setComponentByPosition(count, extension) count += 1 tbsCertificate.setComponentByName('extensions', extensions) tbsDER = encoder.encode(tbsCertificate) rsaPrivateKey = rsa.PrivateKey(self.issuerRSA_N, self.issuerRSA_E, self.issuerRSA_D, self.issuerRSA_P, self.issuerRSA_Q) signature = rsa.sign(tbsDER, rsaPrivateKey, 'SHA-256') certificate = rfc2459.Certificate() certificate.setComponentByName('tbsCertificate', tbsCertificate) certificate.setComponentByName('signatureAlgorithm', self.getSignatureAlgorithm()) certificate.setComponentByName('signatureValue', byteStringToHexifiedBitString(signature)) return encoder.encode(certificate)
def ExportRsaX509(params): oid = ASN1Sequence(RSA_OID, univ.Null()) key = ASN1Sequence(univ.Integer(params['n']), univ.Integer(params['e'])) binkey = BytesToBin(encoder.encode(key)) pubkey = univ.BitString("'%s'B" % binkey) # needs to be a BIT STRING seq = ASN1Sequence(oid, pubkey) return Base64WSEncode(encoder.encode(seq))
def _parseauthattrs(auth_attrs, required): results = dict.fromkeys(required) for attr in auth_attrs: if (attr['type'] in oids.OID_TO_CLASS and oids.OID_TO_CLASS.get(attr['type']) in required): # There are more than those I require, but I don't know what they are, # and what to do with them. The spec does not talk about them. # One example: # 1.3.6.1.4.1.311.2.1.11 contains as value 1.3.6.1.4.1.311.2.1.21 # SPC_STATEMENT_TYPE_OBJID SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID results[oids.OID_TO_CLASS.get(attr['type'])] = attr['values'] if None in iter(results.values()): raise Asn1Error('Missing mandatory field(s) in auth_attrs.') # making sure that the auth_attrs were processed in correct order # they need to be sorted in ascending order in the SET, when DER encoded # This also makes sure that the tag on Attributes is correct. a = [der_encoder.encode(i) for i in auth_attrs] a.sort() attrs_for_hash = pkcs7.Attributes() for i in range(len(auth_attrs)): d, _ = decoder.decode(a[i], asn1Spec=pkcs7.Attribute()) attrs_for_hash.setComponentByPosition(i, d) encoded_attrs = der_encoder.encode(attrs_for_hash) return results, encoded_attrs
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 make_ap_req_bytes(self, auth_key_usage, subkey=None, checksum=None): now = datetime.datetime.utcnow() authenticator = asn1.Authenticator() authenticator.setComponentByName('authenticator-vno', 5) authenticator.setComponentByName('crealm', self.client.realm) asn1.seq_set(authenticator, 'cname', self.client.components_to_asn1) if checksum is not None: asn1.seq_set_dict(authenticator, 'cksum', checksum) authenticator.setComponentByName('cusec', now.microsecond) authenticator.setComponentByName('ctime', types.KerberosTime.to_asn1(now)) if subkey is not None: asn1.seq_set_dict(authenticator, 'subkey', subkey.to_asn1()) encoder.encode(authenticator) ap_req = asn1.APReq() ap_req.setComponentByName('pvno', 5) ap_req.setComponentByName('msg-type', int(constants.Asn1Tags.ap_req)) asn1.seq_set_flags(ap_req, 'ap-options', constants.APOptions()) asn1.seq_set(ap_req, 'ticket', self.ticket.to_asn1) asn1.seq_set_dict(ap_req, 'authenticator', self.key.encrypted_data( auth_key_usage, encoder.encode(authenticator))) return encoder.encode(ap_req)
def convertPKCS1toPKCS8pubKey(bitsdata): pubkey_pkcs1_b64 = b''.join(bitsdata.split(b'\n')[1:-2]) pubkey_pkcs1, restOfInput = der_decoder.decode( base64.b64decode(pubkey_pkcs1_b64)) bitstring = univ.Sequence() bitstring.setComponentByPosition(0, univ.Integer(pubkey_pkcs1[0])) bitstring.setComponentByPosition(1, univ.Integer(pubkey_pkcs1[1])) bitstring = der_encoder.encode(bitstring) try: bitstring = ''.join( [('00000000' + bin(ord(x))[2:])[-8:] for x in list(bitstring)]) except: bitstring = ''.join( [('00000000' + bin(x)[2:])[-8:] for x in list(bitstring)]) bitstring = univ.BitString("'%s'B" % bitstring) pubkeyid = univ.Sequence() pubkeyid.setComponentByPosition( 0, univ.ObjectIdentifier('1.2.840.113549.1.1.1')) # OID rsaEncryption pubkeyid.setComponentByPosition(1, univ.Null('')) pubkey_seq = univ.Sequence() pubkey_seq.setComponentByPosition(0, pubkeyid) pubkey_seq.setComponentByPosition(1, bitstring) base64.MAXBINSIZE = (64 // 4) * 3 res = b"-----BEGIN PUBLIC KEY-----\n" res += base64.encodestring(der_encoder.encode(pubkey_seq)) res += b"-----END PUBLIC KEY-----\n" return res
def toDER(self): (signatureOID, hashName) = stringToAlgorithmIdentifiers(self.signature) tbsCertificate = rfc2459.TBSCertificate() tbsCertificate.setComponentByName('version', self.getVersion()) tbsCertificate.setComponentByName('serialNumber', self.getSerialNumber()) tbsCertificate.setComponentByName('signature', signatureOID) tbsCertificate.setComponentByName('issuer', self.getIssuer()) tbsCertificate.setComponentByName('validity', self.getValidity()) tbsCertificate.setComponentByName('subject', self.getSubject()) tbsCertificate.setComponentByName('subjectPublicKeyInfo', self.subjectKey.asSubjectPublicKeyInfo()) if self.extensions: extensions = rfc2459.Extensions().subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3)) count = 0 for extension in self.extensions: extensions.setComponentByPosition(count, extension) count += 1 tbsCertificate.setComponentByName('extensions', extensions) certificate = rfc2459.Certificate() certificate.setComponentByName('tbsCertificate', tbsCertificate) certificate.setComponentByName('signatureAlgorithm', signatureOID) tbsDER = encoder.encode(tbsCertificate) certificate.setComponentByName('signatureValue', self.issuerKey.sign(tbsDER, hashName)) return encoder.encode(certificate)
def getChainFingerprint(certChain): fingerprint = hashlib.sha1() secret = hashlib.sha1() for cert in certChain: fingerprint.update(der_encoder.encode(cert)) secret.update(der_encoder.encode(cert[0][0]['serialNumber'])) return fingerprint.hexdigest(), base64.b64encode(secret.digest())
def testDerCodec(self): substrate = pem.readBase64fromText(self.pss_sha512_pem_text) asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) assert not rest assert asn1Object.prettyPrint() assert asn1Object[0] == rfc4055.id_RSASSA_PSS assert der_encoder.encode(asn1Object) == substrate assert substrate == der_encoder.encode(asn1Object)
def export_rsa_to_pkcs8(params): oid = ASN1Sequence(RSA_OID, univ.Null()) key = univ.Sequence().setComponentByPosition(0, univ.Integer(0)) # version for i in range(len(RSA_PARAMS)): key.setComponentByPosition(i + 1, univ.Integer(params[RSA_PARAMS[i]])) octkey = encoder.encode(key) seq = ASN1Sequence(univ.Integer(0), oid, univ.OctetString(octkey)) return encoder.encode(seq)
def testDerCodec(self): substrate = pem.readBase64fromText(self.oaep_full_pem_text) asn1Object, rest = der_decoder.decode(substrate, asn1Spec=self.asn1Spec) assert not rest assert asn1Object.prettyPrint() assert asn1Object[0] == rfc3560.id_RSAES_OAEP assert der_encoder.encode(asn1Object) == substrate assert substrate == der_encoder.encode(asn1Object)
def ExportDsaPkcs8(params): alg_params = univ.Sequence() for i in range(len(DSA_PARAMS)): alg_params.setComponentByPosition(i, univ.Integer(params[DSA_PARAMS[i]])) oid = ASN1Sequence(DSA_OID, alg_params) octkey = encoder.encode(univ.Integer(params['x'])) seq = ASN1Sequence(univ.Integer(0), oid, univ.OctetString(octkey)) return Base64WSEncode(encoder.encode(seq))
def toDER(self): contentInfo = rfc2315.ContentInfo() contentInfo['contentType'] = rfc2315.signedData signedData = rfc2315.SignedData() signedData['version'] = rfc2315.Version(1) digestAlgorithms = rfc2315.DigestAlgorithmIdentifiers() sha1 = rfc2459.AlgorithmIdentifier() sha1['algorithm'] = univ.ObjectIdentifier('1.3.14.3.2.26') sha1['parameters'] = univ.Null() digestAlgorithms[0] = sha1 signedData['digestAlgorithms'] = digestAlgorithms dataContentInfo = rfc2315.ContentInfo() dataContentInfo['contentType'] = rfc2315.data signedData['contentInfo'] = dataContentInfo certificates = rfc2315.ExtendedCertificatesAndCertificates().subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)) extendedCertificateOrCertificate = rfc2315.ExtendedCertificateOrCertificate() certificate = decoder.decode(self.signer.toDER(), asn1Spec=rfc2459.Certificate())[0] extendedCertificateOrCertificate['certificate'] = certificate certificates[0] = extendedCertificateOrCertificate signedData['certificates'] = certificates signerInfos = rfc2315.SignerInfos() signerInfo = rfc2315.SignerInfo() signerInfo['version'] = 1 issuerAndSerialNumber = rfc2315.IssuerAndSerialNumber() issuerAndSerialNumber['issuer'] = self.signer.getIssuer() issuerAndSerialNumber['serialNumber'] = certificate['tbsCertificate']['serialNumber'] signerInfo['issuerAndSerialNumber'] = issuerAndSerialNumber signerInfo['digestAlgorithm'] = sha1 rsa = rfc2459.AlgorithmIdentifier() rsa['algorithm'] = rfc2459.rsaEncryption rsa['parameters'] = univ.Null() authenticatedAttributes = rfc2315.Attributes().subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)) hashAttribute = rfc2315.Attribute() # PKCS#9 messageDigest hashAttribute['type'] = univ.ObjectIdentifier('1.2.840.113549.1.9.4') hashAttribute['values'] = univ.SetOf(rfc2459.AttributeValue()) hashAttribute['values'][0] = univ.OctetString(self.hash) authenticatedAttributes[0] = hashAttribute signerInfo['authenticatedAttributes'] = authenticatedAttributes signerInfo['digestEncryptionAlgorithm'] = rsa signerInfo['encryptedDigest'] = univ.OctetString('signature goes here') signerInfos[0] = signerInfo signedData['signerInfos'] = signerInfos encoded = encoder.encode(signedData) anyTag = univ.Any(encoded).subtype( explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)) contentInfo['content'] = anyTag return encoder.encode(contentInfo)
def new(cls, alias, certs, key, key_format='pkcs8'): """ Helper function to create a new PrivateKeyEntry. :param str alias: The alias for the Private Key Entry :param list certs: An list of certificates, as byte strings. The first one should be the one belonging to the private key, the others the chain (in correct order). :param str key: A byte string containing the private key in the format specified in the key_format parameter (default pkcs8). :param str key_format: The format of the provided private key. Valid options are pkcs8 or rsa_raw. Defaults to pkcs8. :returns: A loaded :class:`PrivateKeyEntry` instance, ready to be placed in a keystore. :raises UnsupportedKeyFormatException: If the key format is unsupported. """ timestamp = int(time.time()) * 1000 cert_chain = [] for cert in certs: cert_chain.append(('X.509', cert)) pke = cls(timestamp = timestamp, alias = alias, cert_chain = cert_chain) if key_format == 'pkcs8': try: private_key_info = asn1_checked_decode(key, asn1Spec=rfc5208.PrivateKeyInfo()) pke._algorithm_oid = private_key_info['privateKeyAlgorithm']['algorithm'].asTuple() pke.pkey = private_key_info['privateKey'].asOctets() pke.pkey_pkcs8 = key except PyAsn1Error as e: raise BadKeyEncodingException("Failed to parse provided key as a PKCS#8 PrivateKeyInfo structure", e) elif key_format == 'rsa_raw': pke._algorithm_oid = RSA_ENCRYPTION_OID # We must encode it to pkcs8 private_key_info = rfc5208.PrivateKeyInfo() private_key_info.setComponentByName('version','v1') a = rfc2459.AlgorithmIdentifier() a.setComponentByName('algorithm', pke._algorithm_oid) a.setComponentByName('parameters', univ.Any(encoder.encode(univ.Null()))) private_key_info.setComponentByName('privateKeyAlgorithm', a) private_key_info.setComponentByName('privateKey', key) pke.pkey_pkcs8 = encoder.encode(private_key_info) pke.pkey = key else: raise UnsupportedKeyFormatException("Key Format '%s' is not supported" % key_format) return pke
def ExportDsaX509(params): alg_params = ASN1Sequence(univ.Integer(params['p']), univ.Integer(params['q']), univ.Integer(params['g'])) oid = ASN1Sequence(DSA_OID, alg_params) binkey = BytesToBin(encoder.encode(univ.Integer(params['y']))) pubkey = univ.BitString("'%s'B" % binkey) # needs to be a BIT STRING seq = ASN1Sequence(oid, pubkey) return Base64WSEncode(encoder.encode(seq))
def toDER(self): (signatureOID, hashAlgorithm) = stringToAlgorithmIdentifiers(self.signature) certificate = rfc2459.Certificate() tbsCertificate = self.getTBSCertificate() certificate.setComponentByName('tbsCertificate', tbsCertificate) certificate.setComponentByName('signatureAlgorithm', signatureOID) tbsDER = encoder.encode(tbsCertificate) certificate.setComponentByName('signatureValue', self.issuerKey.sign(tbsDER, hashAlgorithm)) return encoder.encode(certificate)
def getPubkey(self, privkey): k = gdata.tlslite.utils.keyfactory.parsePEMKey(privkey, private=True) oid = ASN1Sequence(univ.ObjectIdentifier('1.2.840.113549.1.1.1'), univ.Null()) key = ASN1Sequence(univ.Integer(k.n), univ.Integer(k.e)) binkey = BytesToBin(encoder.encode(key)) pubkey = univ.BitString("'%s'B" % binkey) seq = ASN1Sequence(oid, pubkey) pubkeydata = encoder.encode(seq) return pubkeydata
def ValidateCertificateSignature(self, signed_cert, signing_cert): """Given a cert signed by another cert, validates the signature.""" # First the naive way -- note this does not check expiry / use etc. signed_m2 = M2_X509.load_cert_der_string(der_encoder.encode(signed_cert)) signing_m2 = M2_X509.load_cert_der_string(der_encoder.encode(signing_cert)) pubkey = signing_m2.get_pubkey() v = signed_m2.verify(pubkey) if v != 1: self.openssl_error = M2_Err.get_error() raise Asn1Error('1: Validation of cert signature failed.')
def __encode_extension(self, oid, critical, value): # TODO: have another proxy for crypto_x509.Extension which would # provide public_bytes on the top of what python-cryptography has ext = rfc2459.Extension() # TODO: this does not have to be so weird, pyasn1 now has codecs # which are capable of providing python-native types ext['extnID'] = univ.ObjectIdentifier(oid) ext['critical'] = univ.Boolean(critical) ext['extnValue'] = univ.Any(encoder.encode(univ.OctetString(value))) ext = encoder.encode(ext) return ext
def encode_cert_id_base64(self, hkey): return b64encode(der_encoder.encode( self.encode_cert_id_key(hkey))).decode('ascii')
def main(): data_file = sys.argv[1] with file(data_file, 'rb') as objf: fingerprinter = fingerprint.Fingerprinter(objf) is_pecoff = fingerprinter.EvalPecoff() fingerprinter.EvalGeneric() results = fingerprinter.HashIt() print('Generic hashes:') hashes = [x for x in results if x['name'] == 'generic'] if len(hashes) > 1: print('More than one generic finger? Only printing first one.') for hname in sorted(hashes[0].keys()): if hname != 'name': print('%s: %s' % (hname, hashes[0][hname].encode('hex'))) print if not is_pecoff: print('This is not a PE/COFF binary. Exiting.') return print('PE/COFF hashes:') hashes = [x for x in results if x['name'] == 'pecoff'] if len(hashes) > 1: print('More than one PE/COFF finger? Only printing first one.') for hname in sorted(hashes[0].keys()): if hname != 'name' and hname != 'SignedData': print('%s: %s' % (hname, hashes[0][hname].encode('hex'))) print signed_pecoffs = [ x for x in results if x['name'] == 'pecoff' and 'SignedData' in x ] if not signed_pecoffs: print('This PE/COFF binary has no signature. Exiting.') return signed_pecoff = signed_pecoffs[0] signed_datas = signed_pecoff['SignedData'] # There may be multiple of these, if the windows binary was signed multiple # times, e.g. by different entities. Each of them adds a complete SignedData # blob to the binary. # TODO(user): Process all instances signed_data = signed_datas[0] blob = pecoff_blob.PecoffBlob(signed_data) auth = auth_data.AuthData(blob.getCertificateBlob()) content_hasher_name = auth.digest_algorithm().name computed_content_hash = signed_pecoff[content_hasher_name] try: auth.ValidateAsn1() auth.ValidateHashes(computed_content_hash) auth.ValidateSignatures() auth.ValidateCertChains(time.gmtime()) except auth_data.Asn1Error: if auth.openssl_error: print('OpenSSL Errors:\n%s' % auth.openssl_error) raise print('Program: %s, URL: %s' % (auth.program_name, auth.program_url)) if auth.has_countersignature: print('Countersignature is present. Timestamp: %s UTC' % time.asctime(time.gmtime(auth.counter_timestamp))) else: print('Countersignature is not present.') print('Binary is signed with cert issued by:') pprint.pprint(auth.signing_cert_id) print print('Cert chain head issued by:') pprint.pprint(auth.cert_chain_head[2]) print(' Chain not before: %s UTC' % (time.asctime(time.gmtime(auth.cert_chain_head[0])))) print(' Chain not after: %s UTC' % (time.asctime(time.gmtime(auth.cert_chain_head[1])))) print if auth.has_countersignature: print('Countersig chain head issued by:') pprint.pprint(auth.counter_chain_head[2]) print(' Countersig not before: %s UTC' % (time.asctime(time.gmtime(auth.counter_chain_head[0])))) print(' Countersig not after: %s UTC' % (time.asctime(time.gmtime(auth.counter_chain_head[1])))) print print('Certificates') for (issuer, serial), cert in auth.certificates.items(): print(' Issuer: %s' % issuer) print(' Serial: %s' % serial) subject = cert[0][0]['subject'] subject_dn = str(dn.DistinguishedName.TraverseRdn(subject[0])) print(' Subject: %s' % subject_dn) not_before = cert[0][0]['validity']['notBefore'] not_after = cert[0][0]['validity']['notAfter'] not_before_time = not_before.ToPythonEpochTime() not_after_time = not_after.ToPythonEpochTime() print(' Not Before: %s UTC (%s)' % (time.asctime(time.gmtime(not_before_time)), not_before[0])) print(' Not After: %s UTC (%s)' % (time.asctime(time.gmtime(not_after_time)), not_after[0])) bin_cert = der_encoder.encode(cert) print(' MD5: %s' % hashlib.md5(bin_cert).hexdigest()) print(' SHA1: %s' % hashlib.sha1(bin_cert).hexdigest()) print if auth.trailing_data: print('Signature Blob had trailing (unvalidated) data (%d bytes): %s' % (len(auth.trailing_data), auth.trailing_data.encode('hex')))
def _convert_pyasn1_to_openssl_certificate(self, cert): cert_der = der_encoder.encode(cert) cert_openssl = load_certificate(FILETYPE_ASN1, cert_der) return cert_openssl
def _get_name_hash(self, cert): sha1_hash = hashlib.sha1() sha1_hash.update(der_encoder.encode(self._get_subject(cert))) return sha1_hash.hexdigest()
def check_timestamp(tst, certificate, 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, rfc3161.TimeStampToken): tst, substrate = decoder.decode(tst, asn1Spec=rfc3161.TimeStampToken()) if substrate: return False, "extra data after tst" signed_data = tst.content if certificate != "": try: certificate = X509.load_cert_string(certificate, X509.FORMAT_PEM) except: certificate = X509.load_cert_string(certificate, X509.FORMAT_DER) else: return False, "missing certificate" if nonce is not None and int(tst.tst_info['nonce']) != int(nonce): return False, '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 \ str(message_imprint.hashed_message) != digest: return False, 'Message imprint mismatch' # if not len(signed_data['signerInfos']): return False, 'No signature' # We validate only one signature signer_info = signed_data['signerInfos'][0] # check content type if tst.content['contentInfo']['contentType'] != rfc3161.id_ct_TSTInfo: return False, "Signed content type is wrong: %s != %s" % ( tst.content['contentInfo']['contentType'], rfc3161.id_ct_TSTInfo) # check signed data digest content = str(decoder.decode(str(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 = str(decoder.decode(str(authenticated_attribute[1][0]), asn1Spec=univ.OctetString())[0]) if signed_digest != content_digest: return False, '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 pass else: return False, 'No signed digest' else: signed_data = content # check signature signature = signer_info['encryptedDigest'] pub_key = certificate.get_pubkey() pub_key.reset_context(signer_hash_name) pub_key.verify_init() pub_key.verify_update(signed_data) if pub_key.verify_final(str(signature)) != 1: return False, 'Bad signature' return True, ''
def signEncryptTicket(self, kdcRep, encASRepPart, encTicketPart, pacInfos): logging.info('Signing/Encrypting final ticket') # We changed everything we needed to make us special. Now let's repack and calculate checksums validationInfoBlob = pacInfos[PAC_LOGON_INFO] validationInfoAlignment = '\x00' * (((len(validationInfoBlob) + 7) / 8 * 8) - len(validationInfoBlob)) pacClientInfoBlob = pacInfos[PAC_CLIENT_INFO_TYPE] pacClientInfoAlignment = '\x00' * (((len(pacClientInfoBlob) + 7) / 8 * 8) - len(pacClientInfoBlob)) serverChecksum = PAC_SIGNATURE_DATA(pacInfos[PAC_SERVER_CHECKSUM]) serverChecksumBlob = str(pacInfos[PAC_SERVER_CHECKSUM]) serverChecksumAlignment = '\x00' * (((len(serverChecksumBlob) + 7) / 8 * 8) - len(serverChecksumBlob)) privSvrChecksum = PAC_SIGNATURE_DATA(pacInfos[PAC_PRIVSVR_CHECKSUM]) privSvrChecksumBlob = str(pacInfos[PAC_PRIVSVR_CHECKSUM]) privSvrChecksumAlignment = '\x00' * (((len(privSvrChecksumBlob) + 7) / 8 * 8) - len(privSvrChecksumBlob)) # The offset are set from the beginning of the PAC_TYPE # [MS-PAC] 2.4 PAC_INFO_BUFFER offsetData = 8 + len(str(PAC_INFO_BUFFER())) * 4 # Let's build the PAC_INFO_BUFFER for each one of the elements validationInfoIB = PAC_INFO_BUFFER() validationInfoIB['ulType'] = PAC_LOGON_INFO validationInfoIB['cbBufferSize'] = len(validationInfoBlob) validationInfoIB['Offset'] = offsetData offsetData = (offsetData + validationInfoIB['cbBufferSize'] + 7) / 8 * 8 pacClientInfoIB = PAC_INFO_BUFFER() pacClientInfoIB['ulType'] = PAC_CLIENT_INFO_TYPE pacClientInfoIB['cbBufferSize'] = len(pacClientInfoBlob) pacClientInfoIB['Offset'] = offsetData offsetData = (offsetData + pacClientInfoIB['cbBufferSize'] + 7) / 8 * 8 serverChecksumIB = PAC_INFO_BUFFER() serverChecksumIB['ulType'] = PAC_SERVER_CHECKSUM serverChecksumIB['cbBufferSize'] = len(serverChecksumBlob) serverChecksumIB['Offset'] = offsetData offsetData = (offsetData + serverChecksumIB['cbBufferSize'] + 7) / 8 * 8 privSvrChecksumIB = PAC_INFO_BUFFER() privSvrChecksumIB['ulType'] = PAC_PRIVSVR_CHECKSUM privSvrChecksumIB['cbBufferSize'] = len(privSvrChecksumBlob) privSvrChecksumIB['Offset'] = offsetData # offsetData = (offsetData+privSvrChecksumIB['cbBufferSize'] + 7) /8 *8 # Building the PAC_TYPE as specified in [MS-PAC] buffers = str(validationInfoIB) + str(pacClientInfoIB) + str(serverChecksumIB) + str( privSvrChecksumIB) + validationInfoBlob + validationInfoAlignment + str( pacInfos[PAC_CLIENT_INFO_TYPE]) + pacClientInfoAlignment buffersTail = str(serverChecksumBlob) + serverChecksumAlignment + str(privSvrChecksum) + privSvrChecksumAlignment pacType = PACTYPE() pacType['cBuffers'] = 4 pacType['Version'] = 0 pacType['Buffers'] = buffers + buffersTail blobToChecksum = str(pacType) checkSumFunctionServer = _checksum_table[serverChecksum['SignatureType']] if serverChecksum['SignatureType'] == ChecksumTypes.hmac_sha1_96_aes256.value: keyServer = Key(Enctype.AES256, unhexlify(self.__options.aesKey)) elif serverChecksum['SignatureType'] == ChecksumTypes.hmac_sha1_96_aes128.value: keyServer = Key(Enctype.AES128, unhexlify(self.__options.aesKey)) elif serverChecksum['SignatureType'] == ChecksumTypes.hmac_md5.value: keyServer = Key(Enctype.RC4, unhexlify(self.__options.nthash)) else: raise Exception('Invalid Server checksum type 0x%x' % serverChecksum['SignatureType']) checkSumFunctionPriv = _checksum_table[privSvrChecksum['SignatureType']] if privSvrChecksum['SignatureType'] == ChecksumTypes.hmac_sha1_96_aes256.value: keyPriv = Key(Enctype.AES256, unhexlify(self.__options.aesKey)) elif privSvrChecksum['SignatureType'] == ChecksumTypes.hmac_sha1_96_aes128.value: keyPriv = Key(Enctype.AES128, unhexlify(self.__options.aesKey)) elif privSvrChecksum['SignatureType'] == ChecksumTypes.hmac_md5.value: keyPriv = Key(Enctype.RC4, unhexlify(self.__options.nthash)) else: raise Exception('Invalid Priv checksum type 0x%x' % serverChecksum['SignatureType']) serverChecksum['Signature'] = checkSumFunctionServer.checksum(keyServer, KERB_NON_KERB_CKSUM_SALT, blobToChecksum) logging.info('\tPAC_SERVER_CHECKSUM') privSvrChecksum['Signature'] = checkSumFunctionPriv.checksum(keyPriv, KERB_NON_KERB_CKSUM_SALT, serverChecksum['Signature']) logging.info('\tPAC_PRIVSVR_CHECKSUM') buffersTail = str(serverChecksum) + serverChecksumAlignment + str(privSvrChecksum) + privSvrChecksumAlignment pacType['Buffers'] = buffers + buffersTail authorizationData = AuthorizationData() authorizationData[0] = None authorizationData[0]['ad-type'] = AuthorizationDataType.AD_WIN2K_PAC.value authorizationData[0]['ad-data'] = str(pacType) authorizationData = encoder.encode(authorizationData) encTicketPart['authorization-data'][0]['ad-data'] = authorizationData if logging.getLogger().level == logging.DEBUG: logging.debug('Customized EncTicketPart') print encTicketPart.prettyPrint() print ('\n') encodedEncTicketPart = encoder.encode(encTicketPart) cipher = _enctype_table[kdcRep['ticket']['enc-part']['etype']] if cipher.enctype == EncryptionTypes.aes256_cts_hmac_sha1_96.value: key = Key(cipher.enctype, unhexlify(self.__options.aesKey)) elif cipher.enctype == EncryptionTypes.aes128_cts_hmac_sha1_96.value: key = Key(cipher.enctype, unhexlify(self.__options.aesKey)) elif cipher.enctype == EncryptionTypes.rc4_hmac.value: key = Key(cipher.enctype, unhexlify(self.__options.nthash)) else: raise Exception('Unsupported enctype 0x%x' % cipher.enctype) # 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.3) logging.info('\tEncTicketPart') cipherText = cipher.encrypt(key, 2, str(encodedEncTicketPart), None) kdcRep['ticket']['enc-part']['cipher'] = cipherText kdcRep['ticket']['enc-part']['kvno'] = 2 # Lastly.. we have to encrypt the kdcRep['enc-part'] part # with a key we chose. It actually doesn't really matter since nobody uses it (could it be trash?) encodedEncASRepPart = encoder.encode(encASRepPart) # Key Usage 3 # AS-REP encrypted part (includes TGS session key or # application session key), encrypted with the client key # (Section 5.4.2) sessionKey = Key(cipher.enctype, str(encASRepPart['key']['keyvalue'])) logging.info('\tEncASRepPart') cipherText = cipher.encrypt(sessionKey, 3, str(encodedEncASRepPart), None) kdcRep['enc-part']['cipher'] = cipherText kdcRep['enc-part']['etype'] = cipher.enctype kdcRep['enc-part']['kvno'] = 1 if logging.getLogger().level == logging.DEBUG: logging.debug('Final Golden Ticket') print kdcRep.prettyPrint() print ('\n') return encoder.encode(kdcRep), cipher, sessionKey
issuerCert, _ = decoder.decode(pem.readPemBlocksFromFile( sys.stdin, ('-----BEGIN CERTIFICATE-----', '-----END CERTIFICATE-----'))[1], asn1Spec=rfc2459.Certificate()) 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), {'Content-Type': 'application/ocsp-request'}) httpRsp = urllib2.urlopen(httpReq).read() # Process OCSP response ocspRsp, _ = decoder.decode(httpRsp, asn1Spec=rfc2560.OCSPResponse()) producedAt, certId, certStatus, thisUpdate = parseOcspResponse(ocspRsp) print('Certificate ID %s is %s at %s till %s\n' % (certId.getComponentByName('serialNumber'), certStatus, producedAt, thisUpdate))
def process_ocsp_response(self, issuer, cert_id, ocsp_response): try: res = der_decoder.decode(ocsp_response, OCSPResponse())[0] if self.test_mode is not None: ocsp_load_failure = getenv( "SF_TEST_OCSP_FORCE_BAD_OCSP_RESPONSE") if ocsp_load_failure is not None: raise RevocationCheckError("Force fail") except Exception: raise RevocationCheckError(msg='Invalid OCSP Response', errno=ER_INVALID_OCSP_RESPONSE) if res.getComponentByName('responseStatus') != OCSPResponseStatus( 'successful'): raise RevocationCheckError(msg="Invalid Status: {0}".format( res.getComponentByName('response_status')), errno=ER_INVALID_OCSP_RESPONSE) response_bytes = res.getComponentByName('responseBytes') basic_ocsp_response = der_decoder.decode( response_bytes.getComponentByName('response'), BasicOCSPResponse())[0] attached_certs = basic_ocsp_response.getComponentByName('certs') if self._has_certs_in_ocsp_response(attached_certs): logger.debug("Certificate is attached in Basic OCSP Response") cert_der = der_encoder.encode(attached_certs[0]) cert_openssl = load_certificate(FILETYPE_ASN1, cert_der) ocsp_cert = self._convert_openssl_to_pyasn1_certificate( cert_openssl) cur_time = datetime.utcnow().replace(tzinfo=pytz.utc) tbs_certificate = ocsp_cert.getComponentByName('tbsCertificate') """ Signature verification should happen before any kind of validation """ self.verify_signature( ocsp_cert.getComponentByName('signatureAlgorithm'), ocsp_cert.getComponentByName('signatureValue'), issuer, ocsp_cert.getComponentByName('tbsCertificate')) cert_valid, debug_msg = self.check_cert_time_validity( cur_time, tbs_certificate) if not cert_valid: raise RevocationCheckError(msg=debug_msg, errno=ER_INVALID_OCSP_RESPONSE_CODE) else: logger.debug("Certificate is NOT attached in Basic OCSP Response. " "Using issuer's certificate") ocsp_cert = issuer tbs_response_data = basic_ocsp_response.getComponentByName( 'tbsResponseData') logger.debug("Verifying the OCSP response is signed by the issuer.") self.verify_signature( basic_ocsp_response.getComponentByName('signatureAlgorithm'), basic_ocsp_response.getComponentByName('signature'), ocsp_cert, tbs_response_data) single_response = tbs_response_data.getComponentByName('responses')[0] cert_status = single_response.getComponentByName('certStatus') if self.test_mode is not None: test_cert_status = getenv("SF_TEST_OCSP_CERT_STATUS") if test_cert_status == 'revoked': cert_status = 'revoked' elif test_cert_status == 'unknown': cert_status = 'unknown' elif test_cert_status == 'good': cert_status = 'good' try: if cert_status.getName() == 'good': self._process_good_status(single_response, cert_id, ocsp_response) SnowflakeOCSP.OCSP_CACHE.update_cache(self, cert_id, ocsp_response) elif cert_status.getName() == 'revoked': self._process_revoked_status(single_response, cert_id) elif cert_status.getName() == 'unknown': self._process_unknown_status(cert_id) else: debug_msg = "Unknown revocation status was returned. " \ "OCSP response may be malformed: {0}. ".format(cert_status) raise RevocationCheckError(msg=debug_msg, errno=ER_INVALID_OCSP_RESPONSE_CODE) except RevocationCheckError as op_er: if not self.debug_ocsp_failure_url: debug_msg = op_er.msg else: debug_msg = "{0} Consider running curl -o ocsp.der {1}".\ format(op_er.msg, self.debug_ocsp_failure_url) raise RevocationCheckError(msg=debug_msg, errno=op_er.errno)
def get_signed_data(self) -> bytes: return der_encoder.encode(self.dom)
def getKerberosTGT(clientName, password, domain, lmhash, nthash, aesKey='', kdcHost=None, requestPAC=True): asReq = AS_REQ() domain = domain.upper() serverName = Principal('krbtgt/%s' % domain, type=constants.PrincipalNameType.NT_PRINCIPAL.value) pacRequest = KERB_PA_PAC_REQUEST() pacRequest['include-pac'] = requestPAC encodedPacRequest = encoder.encode(pacRequest) asReq['pvno'] = 5 asReq['msg-type'] = int(constants.ApplicationTagNumbers.AS_REQ.value) asReq['padata'] = None asReq['padata'][0] = None asReq['padata'][0]['padata-type'] = int( constants.PreAuthenticationDataTypes.PA_PAC_REQUEST.value) asReq['padata'][0]['padata-value'] = encodedPacRequest reqBody = seq_set(asReq, 'req-body') opts = list() opts.append(constants.KDCOptions.forwardable.value) opts.append(constants.KDCOptions.renewable.value) opts.append(constants.KDCOptions.proxiable.value) reqBody['kdc-options'] = constants.encodeFlags(opts) seq_set(reqBody, 'sname', serverName.components_to_asn1) seq_set(reqBody, 'cname', clientName.components_to_asn1) if domain == '': raise Exception('Empty Domain not allowed in Kerberos') reqBody['realm'] = domain now = datetime.datetime.utcnow() + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['rtime'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) # Yes.. this shouldn't happend but it's inherited from the past if aesKey is None: aesKey = '' if nthash == '': # This is still confusing. I thought KDC_ERR_ETYPE_NOSUPP was enough, # but I found some systems that accepts all ciphers, and trigger an error # when requesting subsequent TGS :(. More research needed. # So, in order to support more than one cypher, I'm setting aes first # since most of the systems would accept it. If we're lucky and # KDC_ERR_ETYPE_NOSUPP is returned, we will later try rc4. if aesKey != '': if len(aesKey) == 64: supportedCiphers = (int( constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value), ) else: supportedCiphers = (int( constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value), ) else: supportedCiphers = (int( constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value), ) else: # We have hashes to try, only way is to request RC4 only supportedCiphers = (int(constants.EncryptionTypes.rc4_hmac.value), ) seq_set_iter(reqBody, 'etype', supportedCiphers) message = encoder.encode(asReq) try: r = sendReceive(message, domain, kdcHost) except KerberosError as e: if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: if supportedCiphers[0] in ( constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value, constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value ) and aesKey is '': supportedCiphers = (int( constants.EncryptionTypes.rc4_hmac.value), ) seq_set_iter(reqBody, 'etype', supportedCiphers) message = encoder.encode(asReq) r = sendReceive(message, domain, kdcHost) else: raise else: raise # This should be the PREAUTH_FAILED packet asRep = decoder.decode(r, asn1Spec=KRB_ERROR())[0] methods = decoder.decode(asRep['e-data'], asn1Spec=METHOD_DATA())[0] salt = b'' encryptionTypesData = dict() for method in methods: if method[ 'padata-type'] == constants.PreAuthenticationDataTypes.PA_ETYPE_INFO2.value: etypes2 = decoder.decode(method['padata-value'], asn1Spec=ETYPE_INFO2())[0] for etype2 in etypes2: if etype2['salt'] is None: salt = '' else: salt = str(etype2['salt']) encryptionTypesData[etype2['etype']] = salt elif method[ 'padata-type'] == constants.PreAuthenticationDataTypes.PA_ETYPE_INFO.value: etypes = decoder.decode(str(method['padata-value']), asn1Spec=ETYPE_INFO())[0] for etype in etypes: if etype['salt'] is None: salt = '' else: salt = str(etype['salt']) encryptionTypesData[etype['etype']] = salt enctype = supportedCiphers[0] if enctype not in encryptionTypesData: raise Exception('No Encryption Data Available!') # Let's build the timestamp timeStamp = PA_ENC_TS_ENC() now = datetime.datetime.utcnow() timeStamp['patimestamp'] = KerberosTime.to_asn1(now) timeStamp['pausec'] = now.microsecond # Encrypt the shyte cipher = _enctype_table[enctype] # Pass the hash/aes key :P if nthash != '': print('here1') key = Key(cipher.enctype, nthash) elif aesKey != '': print('here2') key = Key(cipher.enctype, unhexlify(aesKey)) else: print('here3') key = cipher.string_to_key(password, encryptionTypesData[enctype], None) encodedTimeStamp = encoder.encode(timeStamp) # Key Usage 1 # AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with the # client key (Section 5.2.7.2) encriptedTimeStamp = cipher.encrypt(key, 1, encodedTimeStamp, None) encryptedData = EncryptedData() encryptedData['etype'] = cipher.enctype encryptedData['cipher'] = encriptedTimeStamp encodedEncryptedData = encoder.encode(encryptedData) # Now prepare the new AS_REQ again with the PADATA # ToDo: cannot we reuse the previous one? asReq = AS_REQ() asReq['pvno'] = 5 asReq['msg-type'] = int(constants.ApplicationTagNumbers.AS_REQ.value) asReq['padata'] = None asReq['padata'][0] = None asReq['padata'][0]['padata-type'] = int( constants.PreAuthenticationDataTypes.PA_ENC_TIMESTAMP.value) asReq['padata'][0]['padata-value'] = encodedEncryptedData asReq['padata'][1] = None asReq['padata'][1]['padata-type'] = int( constants.PreAuthenticationDataTypes.PA_PAC_REQUEST.value) asReq['padata'][1]['padata-value'] = encodedPacRequest reqBody = seq_set(asReq, 'req-body') opts = list() opts.append(constants.KDCOptions.forwardable.value) opts.append(constants.KDCOptions.renewable.value) opts.append(constants.KDCOptions.proxiable.value) reqBody['kdc-options'] = constants.encodeFlags(opts) seq_set(reqBody, 'sname', serverName.components_to_asn1) seq_set(reqBody, 'cname', clientName.components_to_asn1) reqBody['realm'] = domain now = datetime.datetime.utcnow() + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['rtime'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) seq_set_iter(reqBody, 'etype', ((int(cipher.enctype), ))) try: tgt = sendReceive(encoder.encode(asReq), domain, kdcHost) except Exception as e: if str(e).find('KDC_ERR_ETYPE_NOSUPP') >= 0: if lmhash is '' and nthash is '' and (aesKey is '' or aesKey is None): from impacket.ntlm import compute_lmhash, compute_nthash lmhash = compute_lmhash(password) nthash = compute_nthash(password) return getKerberosTGT(clientName, password, domain, lmhash, nthash, aesKey, kdcHost, requestPAC) raise # So, we have the TGT, now extract the new session key and finish asRep = decoder.decode(tgt, asn1Spec=AS_REP())[0] cipherText = asRep['enc-part']['cipher'] # Key Usage 3 # AS-REP encrypted part (includes TGS session key or # application session key), encrypted with the client key # (Section 5.4.2) from .crypto import bytify print('cypherText: {}'.format(repr(str(cipherText)))) plainText = cipher.decrypt(key, 3, bytes(cipherText)) encASRepPart = decoder.decode(plainText, asn1Spec=EncASRepPart())[0] # Get the session key and the ticket # We're assuming the cipher for this session key is the same # as the one we used before. # ToDo: change this sessionKey = Key(cipher.enctype, bytes(encASRepPart['key']['keyvalue'])) # ToDo: Check Nonces! return tgt, cipher, key, sessionKey
def fromTGT(self, tgt, 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) decodedTGT = decoder.decode(tgt, asn1Spec=AS_REP())[0] tmpPrincipal = types.Principal() tmpPrincipal.from_asn1(decodedTGT, 'crealm', 'cname') self.principal = Principal() self.principal.fromPrincipal(tmpPrincipal) # Now let's add the credential cipherText = decodedTGT['enc-part']['cipher'] cipher = crypto._enctype_table[decodedTGT['enc-part']['etype']] # Key Usage 3 # AS-REP encrypted part (includes TGS session key or # application session key), encrypted with the client key # (Section 5.4.2) plainText = cipher.decrypt(oldSessionKey, 3, str(cipherText)) encASRepPart = decoder.decode(plainText, asn1Spec=EncASRepPart())[0] credential = Credential() server = types.Principal() server.from_asn1(encASRepPart, '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(encASRepPart['key']['keytype']) credential['key']['keyvalue'] = str(encASRepPart['key']['keyvalue']) credential['key']['keylen'] = len(credential['key']['keyvalue']) credential['time'] = Times() credential['time']['authtime'] = self.toTimeStamp( types.KerberosTime.from_asn1(encASRepPart['authtime'])) credential['time']['starttime'] = self.toTimeStamp( types.KerberosTime.from_asn1(encASRepPart['starttime'])) credential['time']['endtime'] = self.toTimeStamp( types.KerberosTime.from_asn1(encASRepPart['endtime'])) credential['time']['renew_till'] = self.toTimeStamp( types.KerberosTime.from_asn1(encASRepPart['renew-till'])) flags = self.reverseFlags(encASRepPart['flags']) credential['tktflags'] = flags credential['num_address'] = 0 credential.ticket = CountedOctetString() credential.ticket['data'] = encoder.encode(decodedTGT['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 getKerberosType1(username, password, domain, lmhash, nthash, aesKey='', TGT=None, TGS=None, targetName='', kdcHost=None, useCache=True): if TGT is None and TGS is None: if useCache is True: try: ccache = CCache.loadFile(os.getenv('KRB5CCNAME')) except Exception as e: # No cache present pass else: # retrieve user and domain information from CCache file if needed if username == '' and len(ccache.principal.components) > 0: username = ccache.principal.components[0]['data'] if domain == '': domain = ccache.principal.realm['data'] LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME')) principal = 'host/%s@%s' % (targetName.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() # First of all, we need to get a TGT for the user userName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value) while True: if TGT is None: if TGS is None: try: tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT( userName, password, domain, lmhash, nthash, aesKey, kdcHost) except KerberosError as e: if e.getErrorCode( ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: # We might face this if the target does not support AES # So, if that's the case we'll force using RC4 by converting # the password to lm/nt hashes and hope for the best. If that's already # done, byebye. if lmhash is '' and nthash is '' and ( aesKey is '' or aesKey is None ) and TGT is None and TGS is None: from impacket.ntlm import compute_lmhash, compute_nthash LOG.debug( 'Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4') lmhash = compute_lmhash(password) nthash = compute_nthash(password) continue else: raise else: raise else: tgt = TGT['KDC_REP'] cipher = TGT['cipher'] sessionKey = TGT['sessionKey'] # Now that we have the TGT, we should ask for a TGS for cifs if TGS is None: serverName = Principal( 'host/%s' % targetName, type=constants.PrincipalNameType.NT_SRV_INST.value) try: tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS( serverName, domain, kdcHost, tgt, cipher, sessionKey) except KerberosError as e: if e.getErrorCode( ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: # We might face this if the target does not support AES # So, if that's the case we'll force using RC4 by converting # the password to lm/nt hashes and hope for the best. If that's already # done, byebye. if lmhash is '' and nthash is '' and ( aesKey is '' or aesKey is None) and TGT is None and TGS is None: from impacket.ntlm import compute_lmhash, compute_nthash LOG.debug('Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4') lmhash = compute_lmhash(password) nthash = compute_nthash(password) else: raise else: raise else: break else: tgs = TGS['KDC_REP'] cipher = TGS['cipher'] sessionKey = TGS['sessionKey'] break # 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() opts.append(constants.APOptions.mutual_required.value) 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) authenticator['cksum'] = None authenticator['cksum']['cksumtype'] = 0x8003 chkField = CheckSumField() chkField['Lgth'] = 16 chkField[ 'Flags'] = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE #chkField['Flags'] = GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE authenticator['cksum']['checksum'] = chkField.getData() authenticator['seq-number'] = 0 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) return cipher, sessionKey, blob.getData()
def getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey): # Decode the TGT try: decodedTGT = decoder.decode(tgt, asn1Spec=AS_REP())[0] except: decodedTGT = decoder.decode(tgt, asn1Spec=TGS_REP())[0] domain = domain.upper() # 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) 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'] = None 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'] = None tgsReq['padata'][0] = None tgsReq['padata'][0]['padata-type'] = int( constants.PreAuthenticationDataTypes.PA_TGS_REQ.value) tgsReq['padata'][0]['padata-value'] = encodedApReq 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) reqBody['kdc-options'] = constants.encodeFlags(opts) seq_set(reqBody, 'sname', serverName.components_to_asn1) reqBody['realm'] = domain 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(cipher.enctype))) message = encoder.encode(tgsReq) r = sendReceive(message, domain, kdcHost) # Get the session key 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, str(cipherText)) encTGSRepPart = decoder.decode(plainText, asn1Spec=EncTGSRepPart())[0] newSessionKey = Key(encTGSRepPart['key']['keytype'], str(encTGSRepPart['key']['keyvalue'])) # Creating new cipher based on received keytype cipher = _enctype_table[encTGSRepPart['key']['keytype']] # Check we've got what we asked for res = decoder.decode(r, asn1Spec=TGS_REP())[0] spn = Principal() spn.from_asn1(res['ticket'], 'realm', 'sname') if spn.components[0] == serverName.components[0]: # Yes.. bye bye return r, cipher, sessionKey, newSessionKey else: # Let's extract the Ticket, change the domain and keep asking domain = spn.components[1] return getKerberosTGS(serverName, domain, kdcHost, r, cipher, newSessionKey) return r, cipher, sessionKey, newSessionKey
def print_rsa(file_name): file = open(file_name,"r") buffer = file.read() buffer_base = base64.b64encode(buffer) file.close() file = open(file_name + ".pem","w") file.write('-----BEGIN PKCS7-----\n') file.write(buffer_base) file.write('\n-----END PKCS7-----\n') file.close() file = open(file_name + ".pem","r") idx, substrate = pem.readPemBlocksFromFile( file, ('-----BEGIN PKCS7-----', '-----END PKCS7-----') ) file.close() assert substrate, 'bad PKCS7 data on input' contentInfo, rest = decoder.decode(substrate, asn1Spec=rfc2315.ContentInfo()) if rest: substrate = substrate[:-len(rest)] #/home/retme/Desktop/xx/SIGN.RSA #print contentInfo #ContentInfo print(contentInfo.prettyPrint()) buf = contentInfo.getComponentByName('content') assert encoder.encode(contentInfo, defMode=False) == substrate or \ encoder.encode(contentInfo, defMode=True) == substrate, \ 're-encode fails' contentType = contentInfo.getComponentByName('contentType') #print contentInfo #certificates = contentInfo.getComponentByName('certificates') #certificates.prettyPrint() #print certificates 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'), asn1Spec=contentInfoMap[contentType] ) #content.getComponentByName('certificates').setComponentByPosition(1) #print content.getComponentByName('certificates').getComponentByPosition(0).getComponentByName('certificate').getComponentByName('tbsCertificate').getComponentByName('serialNumber') #print content print(content.prettyPrint())
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
class RemoteTimestamper(object): def __init__(self, url, certificate=None, capath=None, cafile=None, username=None, password=None, hashname=None, include_tsa_certificate=False, timeout=10): self.url = url self.certificate = certificate self.capath = capath self.cafile = cafile self.username = username self.password = password self.hashname = hashname or 'sha1' self.include_tsa_certificate = include_tsa_certificate self.timeout = timeout def check_response(self, response, digest, nonce=None): ''' Check validity of a TimeStampResponse ''' tst = response.time_stamp_token return self.check(tst, digest=digest, nonce=nonce) def check(self, tst, data=None, digest=None, nonce=None): return check_timestamp(tst, digest=digest, data=data, nonce=nonce, certificate=self.certificate, hashname=self.hashname) def timestamp(self, data=None, digest=None, include_tsa_certificate=None, nonce=None): return self(data=data, digest=digest, include_tsa_certificate=include_tsa_certificate, nonce=nonce) def __call__(self, data=None, digest=None, include_tsa_certificate=None, nonce=None): algorithm_identifier = rfc2459.AlgorithmIdentifier() algorithm_identifier.setComponentByPosition(0, get_hash_oid(self.hashname)) message_imprint = rfc3161.MessageImprint() message_imprint.setComponentByPosition(0, algorithm_identifier) hashobj = hashlib.new(self.hashname) if data: hashobj.update(data) digest = hashobj.digest() elif digest: assert len(digest) == hashobj.digest_size, 'digest length is wrong' else: raise ValueError('You must pass some data to digest, or the digest') message_imprint.setComponentByPosition(1, digest) request = rfc3161.TimeStampReq() request.setComponentByPosition(0, 'v1') request.setComponentByPosition(1, message_imprint) if nonce is not None: request.setComponentByPosition(3, int(nonce)) request.setComponentByPosition(4, include_tsa_certificate if include_tsa_certificate is not None else self.include_tsa_certificate) binary_request = encoder.encode(request) headers = { 'Content-Type': 'application/timestamp-query' } if self.username != None: base64string = base64.standard_b64encode('%s:%s' % (self.username, self.password)) headers['Authorization'] = "Basic %s" % base64string try: response = requests.post(self.url, data=binary_request, timeout=self.timeout, headers=headers) except request.RequestException, e: raise TimestampingError('Unable to send the request to %r' % self.url, e) tst_response, substrate = decoder.decode(response.content, asn1Spec=rfc3161.TimeStampResp()) if substrate: return False, 'Extra data returned' result, message = self.check_response(tst_response, digest, nonce=nonce) if result: return encoder.encode(tst_response.time_stamp_token), '' else: return False, message
def get_key(cert): # get subjectPublicKey from certificate # SubjectPublicKeyInfo->subjectPublicKey subjectPublicKey = encoder.encode(decoder.decode(cert)[0][0][6][1]) return subjectPublicKey
def createBasicTicket(self): if self.__options.request is True: logging.info('Requesting TGT 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, lmhash, nthash, None, self.__options.dc_ip) kdcRep = decoder.decode(tgt, asn1Spec=AS_REP())[0] # Let's check we have all the neccesary 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'] = None kdcRep['cname']['name-string'][0] = self.__target else: logging.info('Creating basic skeleton ticket and PAC Infos') kdcRep = AS_REP() kdcRep['pvno'] = 5 kdcRep['msg-type'] = ApplicationTagNumbers.AS_REP.value if self.__options.nthash is None: kdcRep['padata'] = None kdcRep['padata'][0] = None kdcRep['padata'][0]['padata-type'] = PreAuthenticationDataTypes.PA_ETYPE_INFO2.value etype2 = ETYPE_INFO2() etype2[0] = None 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'] = None kdcRep['cname']['name-type'] = PrincipalNameType.NT_PRINCIPAL.value kdcRep['cname']['name-string'] = None kdcRep['cname']['name-string'][0] = self.__target kdcRep['ticket'] = None kdcRep['ticket']['tkt-vno'] = ProtocolVersionNumber.pvno.value kdcRep['ticket']['realm'] = self.__domain.upper() kdcRep['ticket']['sname'] = None kdcRep['ticket']['sname']['name-type'] = PrincipalNameType.NT_PRINCIPAL.value kdcRep['ticket']['sname']['name-string'] = None kdcRep['ticket']['sname']['name-string'][0] = 'krbtgt' kdcRep['ticket']['sname']['name-string'][1] = self.__domain.upper() kdcRep['ticket']['enc-part'] = None kdcRep['ticket']['enc-part']['kvno'] = 2 kdcRep['enc-part'] = None 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'] = None pacInfos = self.createBasicPac(kdcRep) return kdcRep, pacInfos
def get_name(cert): # get subject DN from certificate name = encoder.encode(decoder.decode(cert)[0][0][5]) return name
def decode_cert_id_key(self, cert_id): return ( der_encoder.encode(cert_id.getComponentByName('issuerNameHash')), der_encoder.encode(cert_id.getComponentByName('issuerKeyHash')), der_encoder.encode(cert_id.getComponentByName('serialNumber')))
# Copyright (c) 2005-2017, Ilya Etingof <*****@*****.**> # License: http://pyasn1.sf.net/license.html # # Read ASN.1/PEM X.509 CRMF request on stdin, parse into # plain text, then build substrate from it # import sys from pyasn1.codec.der import decoder from pyasn1.codec.der import encoder from pyasn1_modules import pem from pyasn1_modules import rfc2560 if len(sys.argv) != 1: print("""Usage: $ cat ocsp-request.pem | %s""" % sys.argv[0]) sys.exit(-1) ocspReq = rfc2560.OCSPRequest() 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 testOpenTypes(self): class ClientInformation(univ.Sequence): pass ClientInformation.componentType = namedtype.NamedTypes( namedtype.NamedType('clientId', univ.Integer()), namedtype.NamedType('MachineName', char.UTF8String()), namedtype.NamedType('UserName', char.UTF8String()), namedtype.NamedType('ProcessName', char.UTF8String())) class EnrollmentCSP(univ.Sequence): pass EnrollmentCSP.componentType = namedtype.NamedTypes( namedtype.NamedType('KeySpec', univ.Integer()), namedtype.NamedType('Name', char.BMPString()), namedtype.NamedType('Signature', univ.BitString())) openTypeMap = { # attributes univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.3'): char.IA5String(), univ.ObjectIdentifier('1.3.6.1.4.1.311.13.2.2'): EnrollmentCSP(), univ.ObjectIdentifier('1.3.6.1.4.1.311.21.20'): ClientInformation(), # algorithm identifier parameters univ.ObjectIdentifier('1.2.840.113549.1.1.1'): univ.Null(""), univ.ObjectIdentifier('1.2.840.113549.1.1.5'): univ.Null(""), univ.ObjectIdentifier('1.2.840.113549.1.1.11'): univ.Null(""), } openTypeMap.update(rfc5652.cmsAttributesMap) openTypeMap.update(rfc6402.cmcControlAttributesMap) substrate = pem.readBase64fromText(self.pem_text) asn1Object, rest = der_decoder.decode(substrate, asn1Spec=rfc5652.ContentInfo(), decodeOpenTypes=True) self.assertFalse(rest) self.assertTrue(asn1Object.prettyPrint()) self.assertEqual(substrate, der_encoder.encode(asn1Object)) eci = asn1Object['content']['encapContentInfo'] self.assertIn(eci['eContentType'], rfc5652.cmsContentTypesMap) self.assertEqual(rfc6402.id_cct_PKIData, eci['eContentType']) pkid, rest = der_decoder.decode( eci['eContent'], asn1Spec=rfc5652.cmsContentTypesMap[eci['eContentType']], openTypes=openTypeMap, decodeOpenTypes=True) self.assertFalse(rest) self.assertTrue(pkid.prettyPrint()) self.assertEqual(eci['eContent'], der_encoder.encode(pkid)) for req in pkid['reqSequence']: cr = req['tcr']['certificationRequest'] sig_alg = cr['signatureAlgorithm'] self.assertIn(sig_alg['algorithm'], openTypeMap) self.assertEqual(univ.Null(""), sig_alg['parameters']) cri = cr['certificationRequestInfo'] spki_alg = cri['subjectPublicKeyInfo']['algorithm'] self.assertIn(spki_alg['algorithm'], openTypeMap) self.assertEqual(univ.Null(""), spki_alg['parameters']) attrs = cr['certificationRequestInfo']['attributes'] for attr in attrs: self.assertIn(attr['attrType'], openTypeMap) if attr['attrType'] == univ.ObjectIdentifier( '1.3.6.1.4.1.311.13.2.3'): self.assertEqual("6.2.9200.2", attr['attrValues'][0]) else: self.assertTrue(attr['attrValues'][0].hasValue())
def fromTGS(self, tgs, oldSessionKey, sessionKey): self.headers = [] header = Header() header['tag'] = 1 header['taglen'] = 8 header['tagdata'] = b'\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, 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'] = encTGSRepPart['key']['keyvalue'].asOctets() 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'])) # After KB4586793 for CVE-2020-17049 this timestamp may be omitted if encTGSRepPart['renew-till'].hasValue(): 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'] = b'' credential.secondTicket['length'] = 0 self.credentials.append(credential)
from pyasn1_modules import rfc2459, pem from pyasn1.codec.der import encoder, decoder import sys if len(sys.argv) != 1: print("""Usage: $ cat crl.pem | %s""" % sys.argv[0]) sys.exit(-1) asn1Spec = rfc2459.CertificateList() cnt = 0 while 1: 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 = cnt + 1 print('*** %s CRL(s) re/serialized' % cnt)
def dump(self): # 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, bytes.fromhex(self.__lmhash), bytes.fromhex(self.__nthash)) 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.encode() + self.__domain.encode( ) + 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.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 != '' and (isinstance(self.__nthash, bytes) and self.__nthash != b''): key = Key(newCipher.enctype, bytes.fromhex(self.__nthash)) 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, cipherText) self.printPac(plainText)
def decode_ocsp_request(self, ocsp_request): return der_encoder.encode(ocsp_request)
#!/usr/bin/python # # Read ASN.1/PEM X.509 CRMF request 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-request.pem | %s""" % sys.argv[0]) sys.exit(-1) ocspReq = rfc2560.OCSPRequest() 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, defMode=False) == substrate or \ encoder.encode(cr, defMode=True) == substrate, \ 'OCSP request recode fails'
def _get_issuer_hash(self, cert): sha256_hash = hashlib.sha256() sha256_hash.update( der_encoder.encode(self._get_issuer(cert))) return sha256_hash.digest()
def getTGT(self, userName, requestPAC=True): clientName = Principal( userName, type=constants.PrincipalNameType.NT_PRINCIPAL.value) asReq = AS_REQ() domain = self.__domain.upper() serverName = Principal( 'krbtgt/%s' % domain, type=constants.PrincipalNameType.NT_PRINCIPAL.value) pacRequest = KERB_PA_PAC_REQUEST() pacRequest['include-pac'] = requestPAC encodedPacRequest = encoder.encode(pacRequest) asReq['pvno'] = 5 asReq['msg-type'] = int(constants.ApplicationTagNumbers.AS_REQ.value) asReq['padata'] = noValue asReq['padata'][0] = noValue asReq['padata'][0]['padata-type'] = int( constants.PreAuthenticationDataTypes.PA_PAC_REQUEST.value) asReq['padata'][0]['padata-value'] = encodedPacRequest reqBody = seq_set(asReq, 'req-body') opts = list() opts.append(constants.KDCOptions.forwardable.value) opts.append(constants.KDCOptions.renewable.value) opts.append(constants.KDCOptions.proxiable.value) reqBody['kdc-options'] = constants.encodeFlags(opts) seq_set(reqBody, 'sname', serverName.components_to_asn1) seq_set(reqBody, 'cname', clientName.components_to_asn1) if domain == '': raise Exception('Empty Domain not allowed in Kerberos') reqBody['realm'] = domain now = datetime.datetime.utcnow() + datetime.timedelta(days=1) reqBody['till'] = KerberosTime.to_asn1(now) reqBody['rtime'] = KerberosTime.to_asn1(now) reqBody['nonce'] = random.getrandbits(31) supportedCiphers = (int(constants.EncryptionTypes.rc4_hmac.value), ) seq_set_iter(reqBody, 'etype', supportedCiphers) message = encoder.encode(asReq) try: r = sendReceive(message, domain, self.__kdcHost) except KerberosError as e: if e.getErrorCode( ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: # RC4 not available, OK, let's ask for newer types supportedCiphers = ( int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value ), int(constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value ), ) seq_set_iter(reqBody, 'etype', supportedCiphers) message = encoder.encode(asReq) r = sendReceive(message, domain, self.__kdcHost) else: raise e # This should be the PREAUTH_FAILED packet or the actual TGT if the target principal has the # 'Do not require Kerberos preauthentication' set try: asRep = decoder.decode(r, asn1Spec=KRB_ERROR())[0] except: # Most of the times we shouldn't be here, is this a TGT? asRep = decoder.decode(r, asn1Spec=AS_REP())[0] else: # The user doesn't have UF_DONT_REQUIRE_PREAUTH set raise Exception( 'User %s doesn\'t have UF_DONT_REQUIRE_PREAUTH set' % userName) if self.__outputFormat == 'john': # Let's output the TGT enc-part/cipher in John format, in case somebody wants to use it. return '$krb5asrep$%s@%s:%s$%s' % ( clientName, domain, hexlify(asRep['enc-part']['cipher'].asOctets()[:16]).decode(), hexlify(asRep['enc-part']['cipher'].asOctets()[16:]).decode()) else: # Let's output the TGT enc-part/cipher in Hashcat format, in case somebody wants to use it. return '$krb5asrep$%d$%s@%s:%s$%s' % ( asRep['enc-part']['etype'], clientName, domain, hexlify(asRep['enc-part']['cipher'].asOctets()[:16]).decode(), hexlify(asRep['enc-part']['cipher'].asOctets()[16:]).decode())
def registration(self, filename='paysense'): certs, certs_der, cert_hashes, blinded_hashes, btc_addresses,rands = [], [], [], [], [], [] # Create the directories if they don't exist already if not path.exists(self.data_path): mkdir(self.data_path) if not path.exists(self.data_path + "private"): mkdir(self.data_path + "private") try: # Get ACA information aca_cert_text = b64decode(urlopen(ACA + '/get_ca_cert').read()) aca_cert = X509.load_cert_string(aca_cert_text) pk = tbRSA.importKey(aca_cert.get_pubkey().as_der()) # Generate the basic certificates for i in range(CERT_COUNT): pkey, btc_address = self.generate_keys() cert, cert_hash = self.generate_certificate( aca_cert, btc_address, pkey) btc_addresses.append(btc_address) certs.append(cert) cert_hashes.append(cert_hash) # Blind the cert hash rands.append(getrandbits(RAND_SIZE)) blinded_hashes.append(pk.blind(cert_hashes[i], rands[i])) # Contact the ACA and send her the certificate hash to be signed headers = { 'Content-type': 'application/json', 'Accept': 'text/plain' } data = {'cert_hashes': b64encode(str(blinded_hashes)), 'step': 1} response = post(ACA + "/sign_in", data=dumps(data), headers=headers) # If response is OK if response.status_code is 200: p = int(b64decode(response.content)) # Prepare the data to be sent to the ACA for i in range(len(certs)): if i != p: certs_der.append(encoder.encode(certs[i])) else: # The data in the chosen position is deleted and not sent to the ACA certs_der.append(None) r = rands[i] rands[i] = 0 # Send the data to the ACA data = { 'certs': b64encode(str(certs_der)), 'rands': str(rands), 'step': 2 } response = post(ACA + "/sign_in", data=dumps(data), headers=headers) # If response is OK if response.status_code is 200: signed_b_hash = b64decode(response.content) signature = pk.unblind(long(signed_b_hash), r) # Check that the signature is valid if pk.verify(cert_hashes[p], [signature, 0]): # Attach the signature to the certificate bin_signature = Signature( "'%s'H" % ''.join("%02X" % ord(c) for c in long_to_bytes(signature))) certs[p].setComponentByName("signatureValue", bin_signature) # Set the bitcoin address to the chosen one self.btc_address = btc_addresses[p] # Rename and move the keys associated with the chosen bitcoin address if not path.exists(self.data_path + "/private"): mkdir(self.data_path + "private") rename( self.data_path + tmp + self.btc_address + "_key.pem", self.data_path + "/private/paysense.key") rename( self.data_path + tmp + self.btc_address + "_public_key.pem", self.data_path + "paysense_public.key") rename( self.data_path + tmp + self.btc_address + "_WIF.png", self.data_path + "private/wif_qr.png") # Delete the temp folder and all the other keys rmtree(self.data_path + tmp) # Store the certificate der_cert = encoder.encode(certs[p]) store_certificate(der_cert, self.data_path + filename) # Send the final certificate to the ACA data = { 'certificate': b64encode(der_cert), 'bitcoin_address': self.btc_address } response = post(ACA + "/store_certificate", data=dumps(data), headers=headers) else: response = "Invalid certificate signature" return response except URLError as e: return e