Skip to main content

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

Build docs developers (and LLMs) love