Documentation Index
Fetch the complete documentation index at: https://mintlify.com/fortra/impacket/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The impacket.krb5.asn1 module implements all ASN.1 (Abstract Syntax Notation One) structures defined in RFC 4120 and Microsoft extensions from [MS-KILE]. These structures represent Kerberos protocol messages, tickets, and data types encoded using Distinguished Encoding Rules (DER).
Module Location
from impacket.krb5.asn1 import (
AS_REQ, AS_REP, TGS_REQ, TGS_REP,
AP_REQ, AP_REP, KRB_ERROR,
Ticket, EncryptedData, PrincipalName,
EncASRepPart, EncTGSRepPart
)
Source: impacket/krb5/asn1.py
Basic Data Types
Primitive Types
Int32
32-bit signed integer used throughout Kerberos messages.
class Int32(univ.Integer):
subtypeSpec = constraint.ValueRangeConstraint(-2147483648, 2147483647)
Range: -2,147,483,648 to 2,147,483,647
UInt32
32-bit unsigned integer for nonces and sequence numbers.
class UInt32(univ.Integer):
pass # 0 to 4,294,967,295
Microseconds
Microsecond values for timestamps.
class Microseconds(univ.Integer):
subtypeSpec = constraint.ValueRangeConstraint(0, 999999)
Range: 0 to 999,999
KerberosString
UTF-8 encoded general string.
class KerberosString(char.GeneralString):
encoding = 'utf-8'
# Usage
krb_string = KerberosString('username')
Realm
Kerberos realm name (domain).
class Realm(KerberosString):
pass
# Example
realm = Realm('DOMAIN.LOCAL')
KerberosTime
Generalized time format: YYYYMMDDHHMMSSz
class KerberosTime(useful.GeneralizedTime):
pass
# Format: "20240315120000Z"
KerberosFlags
Bit string for flags (32 bits minimum).
class KerberosFlags(univ.BitString):
pass
# Usage with helper function
from impacket.krb5.asn1 import seq_set_flags
from impacket.krb5.constants import TicketFlags
flags = TicketFlags()
flags.forwardable = True
flags.renewable = True
seq_set_flags(ticket, 'flags', flags)
Principal Names
PrincipalName
Represents a Kerberos principal identity.
class PrincipalName(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component("name-type", 0, Int32()),
_sequence_component("name-string", 1,
univ.SequenceOf(componentType=KerberosString()))
)
Fields:
name-type: Principal type (NT_PRINCIPAL, NT_SRV_INST, etc.)
name-string: Sequence of name components
Example:
from impacket.krb5.asn1 import PrincipalName, seq_set
from impacket.krb5 import constants
# Create principal
principal = PrincipalName()
principal.setComponentByName('name-type',
constants.PrincipalNameType.NT_PRINCIPAL.value)
# Set name components
name_string = principal.setComponentByName('name-string').getComponentByName('name-string')
name_string.setComponentByPosition(0, 'john')
name_string.setComponentByPosition(1, 'admin') # Optional instance
# Result: john/admin
Common Name Types:
NT_PRINCIPAL = 1: User principal (user@REALM)
NT_SRV_INST = 2: Service with instance (krbtgt/REALM)
NT_SRV_HST = 3: Service with host (host/server.domain)
NT_ENTERPRISE = 10: UPN format
Encryption Structures
EncryptionKey
Cryptographic key with type identifier.
class EncryptionKey(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component('keytype', 0, Int32()),
_sequence_component('keyvalue', 1, univ.OctetString())
)
Fields:
keytype: Encryption algorithm identifier
keyvalue: Raw key bytes
Example:
from binascii import unhexlify
key = EncryptionKey()
key.setComponentByName('keytype', 18) # AES256
key.setComponentByName('keyvalue', unhexlify('a1b2c3...'))
Key Types:
1: DES-CBC-CRC
3: DES-CBC-MD5
16: DES3-CBC-SHA1
17: AES128-CTS-HMAC-SHA1-96
18: AES256-CTS-HMAC-SHA1-96
23: RC4-HMAC
EncryptedData
Encrypted data with algorithm and optional version.
class EncryptedData(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component("etype", 0, Int32()),
_sequence_optional_component("kvno", 1, UInt32()),
_sequence_component("cipher", 2, univ.OctetString())
)
Fields:
etype: Encryption type
kvno: Key version number (optional)
cipher: Encrypted ciphertext
Example:
enc_data = EncryptedData()
enc_data.setComponentByName('etype', 18) # AES256
enc_data.setComponentByName('kvno', 3)
enc_data.setComponentByName('cipher', ciphertext_bytes)
Checksum
Integrity checksum for messages.
class Checksum(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component('cksumtype', 0, Int32()),
_sequence_component('checksum', 1, univ.OctetString())
)
Fields:
cksumtype: Checksum algorithm
checksum: Checksum value
Checksum Types:
12: HMAC-SHA1-DES3
15: HMAC-SHA1-96-AES128
16: HMAC-SHA1-96-AES256
-138: HMAC-MD5 (0xffffff76)
Ticket Structures
Ticket
Kerberos ticket for service access.
class Ticket(univ.Sequence):
tagSet = _application_tag(constants.ApplicationTagNumbers.Ticket.value)
componentType = namedtype.NamedTypes(
_vno_component(name="tkt-vno", tag_value=0),
_sequence_component("realm", 1, Realm()),
_sequence_component("sname", 2, PrincipalName()),
_sequence_component("enc-part", 3, EncryptedData())
)
Fields:
tkt-vno: Ticket version (always 5)
realm: Service realm
sname: Service principal name
enc-part: Encrypted ticket contents
Example:
from pyasn1.codec.der import decoder, encoder
# Parse ticket
ticket = decoder.decode(ticket_bytes, asn1Spec=Ticket())[0]
print(f"Realm: {ticket['realm']}")
print(f"Service: {ticket['sname']}")
print(f"Encryption: {ticket['enc-part']['etype']}")
# Encode ticket
ticket_bytes = encoder.encode(ticket)
EncTicketPart
Decrypted ticket contents (encrypted in ticket).
class EncTicketPart(univ.Sequence):
tagSet = _application_tag(constants.ApplicationTagNumbers.EncTicketPart.value)
componentType = namedtype.NamedTypes(
_sequence_component("flags", 0, TicketFlags()),
_sequence_component("key", 1, EncryptionKey()),
_sequence_component("crealm", 2, Realm()),
_sequence_component("cname", 3, PrincipalName()),
_sequence_component("transited", 4, TransitedEncoding()),
_sequence_component("authtime", 5, KerberosTime()),
_sequence_optional_component("starttime", 6, KerberosTime()),
_sequence_component("endtime", 7, KerberosTime()),
_sequence_optional_component("renew-till", 8, KerberosTime()),
_sequence_optional_component("caddr", 9, HostAddresses()),
_sequence_optional_component("authorization-data", 10, AuthorizationData())
)
Key Fields:
flags: Ticket flags (forwardable, renewable, etc.)
key: Session key for client-service communication
crealm: Client realm
cname: Client principal name
authtime: Initial authentication time
starttime: Ticket valid start time
endtime: Ticket expiration time
renew-till: Renewable until time
authorization-data: MS-PAC and other authz data
TicketFlags
Bit flags controlling ticket behavior.
class TicketFlags(KerberosFlags):
pass
Common Flags:
- Bit 1:
forwardable - Can be forwarded to another service
- Bit 2:
forwarded - Ticket was forwarded
- Bit 3:
proxiable - Can be used to obtain proxy
- Bit 8:
renewable - Can be renewed
- Bit 9:
initial - Initial authentication
- Bit 10:
pre-authent - Pre-authentication used
Request Structures
AS-REQ (Authentication Service Request)
Initial authentication request for TGT.
class AS_REQ(KDC_REQ):
tagSet = _application_tag(constants.ApplicationTagNumbers.AS_REQ.value)
Inherits from KDC_REQ:
class KDC_REQ(univ.Sequence):
componentType = namedtype.NamedTypes(
_vno_component(1),
_msg_type_component(2, (AS_REQ_TAG, TGS_REQ_TAG)),
_sequence_optional_component('padata', 3,
univ.SequenceOf(componentType=PA_DATA())),
_sequence_component('req-body', 4, KDC_REQ_BODY())
)
Fields:
pvno: Protocol version (5)
msg-type: Message type (10 for AS-REQ)
padata: Pre-authentication data
req-body: Request body
Example:
from impacket.krb5.asn1 import AS_REQ, seq_set
from pyasn1.type.univ import noValue
asReq = AS_REQ()
asReq['pvno'] = 5
asReq['msg-type'] = 10
# Add pre-auth data
asReq['padata'] = noValue
asReq['padata'][0] = noValue
asReq['padata'][0]['padata-type'] = 2 # PA-ENC-TIMESTAMP
asReq['padata'][0]['padata-value'] = enc_timestamp
# Set request body
reqBody = seq_set(asReq, 'req-body')
reqBody['realm'] = 'DOMAIN.LOCAL'
reqBody['nonce'] = 123456
KDC_REQ_BODY
Request body for AS-REQ and TGS-REQ.
class KDC_REQ_BODY(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component('kdc-options', 0, KDCOptions()),
_sequence_optional_component('cname', 1, PrincipalName()),
_sequence_component('realm', 2, Realm()),
_sequence_optional_component('sname', 3, PrincipalName()),
_sequence_optional_component('from', 4, KerberosTime()),
_sequence_component('till', 5, KerberosTime()),
_sequence_optional_component('rtime', 6, KerberosTime()),
_sequence_component('nonce', 7, UInt32()),
_sequence_component('etype', 8, univ.SequenceOf(componentType=Int32())),
_sequence_optional_component('addresses', 9, HostAddresses()),
_sequence_optional_component('enc-authorization-data', 10, EncryptedData()),
_sequence_optional_component('additional-tickets', 11,
univ.SequenceOf(componentType=Ticket()))
)
Key Fields:
kdc-options: Request options (forwardable, renewable, etc.)
cname: Client name (AS-REQ only)
realm: Target realm
sname: Service name
till: Requested expiration time
nonce: Random nonce for replay protection
etype: Acceptable encryption types
TGS-REQ (Ticket Granting Service Request)
Request for service ticket.
class TGS_REQ(KDC_REQ):
tagSet = _application_tag(constants.ApplicationTagNumbers.TGS_REQ.value)
TGS-REQ Pre-auth Data:
# Requires AP-REQ in padata
tgsReq['padata'][0]['padata-type'] = 1 # PA-TGS-REQ
tgsReq['padata'][0]['padata-value'] = encoder.encode(apReq)
PA_DATA
Pre-authentication data.
class PA_DATA(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component('padata-type', 1, Int32()),
_sequence_component('padata-value', 2, univ.OctetString())
)
Common PA Types:
1: PA-TGS-REQ (AP-REQ for TGS)
2: PA-ENC-TIMESTAMP (encrypted timestamp)
11: PA-ETYPE-INFO (salt information)
19: PA-ETYPE-INFO2 (extended salt info)
128: PA-PAC-REQUEST (request PAC)
129: PA-FOR-USER (S4U2Self)
Example:
from impacket.krb5.asn1 import PA_DATA, PA_ENC_TIMESTAMP
from pyasn1.codec.der import encoder
# Create encrypted timestamp
pa_enc_ts = PA_ENC_TS_ENC()
pa_enc_ts['patimestamp'] = KerberosTime.to_asn1(now)
pa_enc_ts['pausec'] = now.microsecond
# Encrypt it
enc_ts = cipher.encrypt(key, 1, encoder.encode(pa_enc_ts), None)
# Wrap in PA_DATA
padata = PA_DATA()
padata['padata-type'] = 2
padata['padata-value'] = enc_ts
Response Structures
AS-REP (Authentication Service Reply)
TGT response from KDC.
class AS_REP(KDC_REP):
tagSet = _application_tag(constants.ApplicationTagNumbers.AS_REP.value)
Inherits from KDC_REP:
class KDC_REP(univ.Sequence):
componentType = namedtype.NamedTypes(
_vno_component(0),
_msg_type_component(1, (AS_REP_TAG, TGS_REP_TAG)),
_sequence_optional_component('padata', 2,
univ.SequenceOf(componentType=PA_DATA())),
_sequence_component('crealm', 3, Realm()),
_sequence_component('cname', 4, PrincipalName()),
_sequence_component('ticket', 5, Ticket()),
_sequence_component('enc-part', 6, EncryptedData())
)
Fields:
pvno: Protocol version (5)
msg-type: Message type (11 for AS-REP)
crealm: Client realm
cname: Client name
ticket: The TGT
enc-part: Encrypted part (session key, times, etc.)
Example:
from pyasn1.codec.der import decoder
# Decode AS-REP
asRep = decoder.decode(response_bytes, asn1Spec=AS_REP())[0]
# Extract ticket
tgt = asRep['ticket']
# Decrypt enc-part
cipherText = asRep['enc-part']['cipher']
plainText = cipher.decrypt(key, 3, cipherText) # Key usage 3
encASRepPart = decoder.decode(plainText, asn1Spec=EncASRepPart())[0]
sessionKey = encASRepPart['key']
EncASRepPart
Decrypted AS-REP encrypted part.
class EncASRepPart(EncKDCRepPart):
tagSet = _application_tag(constants.ApplicationTagNumbers.EncASRepPart.value)
Inherits from EncKDCRepPart:
class EncKDCRepPart(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component('key', 0, EncryptionKey()),
_sequence_component('last-req', 1, LastReq()),
_sequence_component('nonce', 2, UInt32()),
_sequence_optional_component('key-expiration', 3, KerberosTime()),
_sequence_component('flags', 4, TicketFlags()),
_sequence_component('authtime', 5, KerberosTime()),
_sequence_optional_component('starttime', 6, KerberosTime()),
_sequence_component('endtime', 7, KerberosTime()),
_sequence_optional_component('renew-till', 8, KerberosTime()),
_sequence_component('srealm', 9, Realm()),
_sequence_component('sname', 10, PrincipalName()),
_sequence_optional_component('caddr', 11, HostAddresses())
)
Critical Fields:
key: Session key for TGS-REQ
nonce: Must match request nonce
flags: Ticket flags granted
authtime: Authentication time
endtime: TGT expiration
srealm: Server realm
sname: Server name (krbtgt/REALM)
TGS-REP (Ticket Granting Service Reply)
Service ticket response.
class TGS_REP(KDC_REP):
tagSet = _application_tag(constants.ApplicationTagNumbers.TGS_REP.value)
Similar to AS-REP but:
msg-type: 13
ticket: Service ticket (not TGT)
- Encrypted with TGS session key
EncTGSRepPart
Decrypted TGS-REP encrypted part.
class EncTGSRepPart(EncKDCRepPart):
tagSet = _application_tag(constants.ApplicationTagNumbers.EncTGSRepPart.value)
Key usage: 8 (TGS session key)
Application Protocol
AP-REQ (Application Request)
Client authentication to service.
class AP_REQ(univ.Sequence):
tagSet = _application_tag(constants.ApplicationTagNumbers.AP_REQ.value)
componentType = namedtype.NamedTypes(
_vno_component(0),
_msg_type_component(1, (AP_REQ_TAG,)),
_sequence_component('ap-options', 2, APOptions()),
_sequence_component('ticket', 3, Ticket()),
_sequence_component('authenticator', 4, EncryptedData())
)
Fields:
pvno: 5
msg-type: 14
ap-options: Request options
ticket: Service ticket from TGS-REP
authenticator: Encrypted authenticator
AP Options:
- Bit 2:
mutual-required - Request AP-REP
Example:
apReq = AP_REQ()
apReq['pvno'] = 5
apReq['msg-type'] = 14
# Set mutual authentication
opts = []
opts.append(2) # mutual-required
apReq['ap-options'] = constants.encodeFlags(opts)
# Set ticket
seq_set(apReq, 'ticket', ticket.to_asn1)
# Create and encrypt authenticator
authenticator = Authenticator()
authenticator['authenticator-vno'] = 5
authenticator['crealm'] = domain
authenticator['cusec'] = now.microsecond
authenticator['ctime'] = KerberosTime.to_asn1(now)
enc_auth = cipher.encrypt(sessionKey, 11, encoder.encode(authenticator), None)
apReq['authenticator']['etype'] = cipher.enctype
apReq['authenticator']['cipher'] = enc_auth
Authenticator
Proof of session key possession.
class Authenticator(univ.Sequence):
tagSet = _application_tag(constants.ApplicationTagNumbers.Authenticator.value)
componentType = namedtype.NamedTypes(
_vno_component(name='authenticator-vno', tag_value=0),
_sequence_component('crealm', 1, Realm()),
_sequence_component('cname', 2, PrincipalName()),
_sequence_optional_component('cksum', 3, Checksum()),
_sequence_component('cusec', 4, Microseconds()),
_sequence_component('ctime', 5, KerberosTime()),
_sequence_optional_component('subkey', 6, EncryptionKey()),
_sequence_optional_component('seq-number', 7, UInt32()),
_sequence_optional_component('authorization-data', 8, AuthorizationData())
)
Fields:
crealm: Client realm
cname: Client name
cksum: Checksum of application data (optional)
cusec: Microseconds of ctime
ctime: Current time
subkey: Optional session subkey
seq-number: Sequence number
Key Usage: 11 (for encryption)
AP-REP (Application Reply)
Mutual authentication response.
class AP_REP(univ.Sequence):
tagSet = _application_tag(constants.ApplicationTagNumbers.AP_REP.value)
componentType = namedtype.NamedTypes(
_vno_component(0),
_msg_type_component(1, (AP_REP_TAG,)),
_sequence_component('enc-part', 2, EncryptedData())
)
Fields:
pvno: 5
msg-type: 15
enc-part: Encrypted EncAPRepPart
EncAPRepPart
Decrypted AP-REP contents.
class EncAPRepPart(univ.Sequence):
tagSet = _application_tag(constants.ApplicationTagNumbers.EncApRepPart.value)
componentType = namedtype.NamedTypes(
_sequence_component('ctime', 0, KerberosTime()),
_sequence_component('cusec', 1, Microseconds()),
_sequence_optional_component('subkey', 2, EncryptionKey()),
_sequence_optional_component('seq-number', 3, UInt32())
)
Key Usage: 12
Error Messages
KRB_ERROR
Error response from KDC or service.
class KRB_ERROR(univ.Sequence):
tagSet = _application_tag(constants.ApplicationTagNumbers.KRB_ERROR.value)
componentType = namedtype.NamedTypes(
_vno_component(0),
_msg_type_component(1, (KRB_ERROR_TAG,)),
_sequence_optional_component('ctime', 2, KerberosTime()),
_sequence_optional_component('cusec', 3, Microseconds()),
_sequence_component('stime', 4, KerberosTime()),
_sequence_component('susec', 5, Microseconds()),
_sequence_component('error-code', 6, Int32()),
_sequence_optional_component('crealm', 7, Realm()),
_sequence_optional_component('cname', 8, PrincipalName()),
_sequence_component('realm', 9, Realm()),
_sequence_component('sname', 10, PrincipalName()),
_sequence_optional_component('e-text', 11, KerberosString()),
_sequence_optional_component('e-data', 12, univ.OctetString())
)
Critical Fields:
stime: Server time
error-code: Kerberos error code
e-text: Human-readable error
e-data: Additional error data
Example:
try:
asRep = decoder.decode(response, asn1Spec=AS_REP())[0]
except:
krbError = decoder.decode(response, asn1Spec=KRB_ERROR())[0]
error_code = krbError['error-code']
if error_code == 25: # KDC_ERR_PREAUTH_REQUIRED
# Extract salt from e-data
methods = decoder.decode(krbError['e-data'], asn1Spec=METHOD_DATA())[0]
# Process pre-auth requirements
Microsoft Extensions
KERB_PA_PAC_REQUEST
Request PAC in ticket.
class KERB_PA_PAC_REQUEST(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('include-pac', univ.Boolean().subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)))
)
Usage:
pacRequest = KERB_PA_PAC_REQUEST()
pacRequest['include-pac'] = True
encodedPacRequest = encoder.encode(pacRequest)
asReq['padata'][0]['padata-type'] = 128 # PA-PAC-REQUEST
asReq['padata'][0]['padata-value'] = encodedPacRequest
PA_FOR_USER_ENC
S4U2Self protocol data.
class PA_FOR_USER_ENC(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component('userName', 0, PrincipalName()),
_sequence_optional_component('userRealm', 1, Realm()),
_sequence_optional_component('cksum', 2, Checksum()),
_sequence_optional_component('auth-package', 3, KerberosString())
)
Purpose: Request ticket on behalf of user
PA_S4U_X509_USER
S4U with certificate.
class PA_S4U_X509_USER(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('user-id', S4UUserID().subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
namedtype.NamedType('checksum', Checksum().subtype(
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
)
ETYPE_INFO2
Extended encryption type info.
class ETYPE_INFO2_ENTRY(univ.Sequence):
componentType = namedtype.NamedTypes(
_sequence_component('etype', 0, Int32()),
_sequence_optional_component('salt', 1, KerberosString()),
_sequence_optional_component('s2kparams', 2, univ.OctetString())
)
class ETYPE_INFO2(univ.SequenceOf):
componentType = ETYPE_INFO2_ENTRY()
Usage: Provides salt for string-to-key conversion
Helper Functions
seq_set
Set component and return it for chaining.
def seq_set(seq, name, builder=None, *args, **kwargs):
component = seq.setComponentByName(name).getComponentByName(name)
if builder is not None:
seq.setComponentByName(name, builder(component, *args, **kwargs))
else:
seq.setComponentByName(name)
return seq.getComponentByName(name)
# Usage
reqBody = seq_set(asReq, 'req-body')
seq_set(reqBody, 'sname', serverName.components_to_asn1)
seq_set_iter
Set sequence from iterable.
def seq_set_iter(seq, name, iterable):
component = seq.setComponentByName(name).getComponentByName(name)
for pos, v in enumerate(iterable):
component.setComponentByPosition(pos, v)
# Usage
seq_set_iter(reqBody, 'etype', (17, 18, 23)) # AES128, AES256, RC4
seq_append
Append to sequence component.
def seq_append(seq, name, pairs):
component = seq.getComponentByName(name)
if component is None:
component = seq.setComponentByName(name).getComponentByName(name)
index = len(component)
element = component.setComponentByPosition(index).getComponentByPosition(index)
for k, v in pairs.items():
element.setComponentByName(k, v)
# Usage
seq_append(asReq, 'padata', {'padata-type': 2, 'padata-value': data})
Encoding/Decoding
Encoding to DER
from pyasn1.codec.der import encoder
# Encode AS-REQ to bytes
asReqBytes = encoder.encode(asReq)
# Send to KDC
messageLen = struct.pack('!i', len(asReqBytes))
socket.sendall(messageLen + asReqBytes)
Decoding from DER
from pyasn1.codec.der import decoder
# Try to decode as AS-REP
try:
asRep = decoder.decode(responseBytes, asn1Spec=AS_REP())[0]
except:
# Maybe it's an error
krbError = decoder.decode(responseBytes, asn1Spec=KRB_ERROR())[0]
Complete Example
Building AS-REQ
from impacket.krb5.asn1 import (
AS_REQ, PA_DATA, KERB_PA_PAC_REQUEST,
PA_ENC_TS_ENC, EncryptedData, seq_set, seq_set_iter
)
from impacket.krb5.types import Principal, KerberosTime
from impacket.krb5 import constants, crypto
from pyasn1.codec.der import encoder
from pyasn1.type.univ import noValue
import datetime
def build_as_req(username, password, domain, salt):
# Create AS-REQ
asReq = AS_REQ()
asReq['pvno'] = 5
asReq['msg-type'] = int(constants.ApplicationTagNumbers.AS_REQ.value)
# Add PAC request
pacRequest = KERB_PA_PAC_REQUEST()
pacRequest['include-pac'] = True
encodedPacRequest = encoder.encode(pacRequest)
asReq['padata'] = noValue
asReq['padata'][0] = noValue
asReq['padata'][0]['padata-type'] = 128
asReq['padata'][0]['padata-value'] = encodedPacRequest
# Add encrypted timestamp
cipher = crypto._enctype_table[18] # AES256
key = cipher.string_to_key(password, salt, None)
timeStamp = PA_ENC_TS_ENC()
now = datetime.datetime.now(datetime.timezone.utc)
timeStamp['patimestamp'] = KerberosTime.to_asn1(now)
timeStamp['pausec'] = now.microsecond
encTS = cipher.encrypt(key, 1, encoder.encode(timeStamp), None)
encryptedData = EncryptedData()
encryptedData['etype'] = cipher.enctype
encryptedData['cipher'] = encTS
asReq['padata'][1] = noValue
asReq['padata'][1]['padata-type'] = 2
asReq['padata'][1]['padata-value'] = encoder.encode(encryptedData)
# Build request body
clientName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
serverName = Principal(f'krbtgt/{domain}', type=constants.PrincipalNameType.NT_SRV_INST.value)
reqBody = seq_set(asReq, 'req-body')
opts = [1, 8, 3] # forwardable, renewable, proxiable
reqBody['kdc-options'] = constants.encodeFlags(opts)
seq_set(reqBody, 'cname', clientName.components_to_asn1)
seq_set(reqBody, 'sname', serverName.components_to_asn1)
reqBody['realm'] = domain
reqBody['till'] = KerberosTime.to_asn1(now + datetime.timedelta(days=1))
reqBody['nonce'] = 12345
seq_set_iter(reqBody, 'etype', (18,)) # AES256 only
return encoder.encode(asReq)
See Also