ESP - Encapsulating Security Payload¶
ESP - Encapsulating Security Payload¶
pcapkit.protocols.internet.esp contains
ESP only,
which implements extractor for Encapsulating
Security Payload (ESP) [*], whose structure is
described as below:
Octets |
Bits |
Name |
Description |
|---|---|---|---|
0 |
0 |
|
Security Parameters Index (SPI) |
4 |
32 |
|
Sequence Number |
8 |
64 |
|
Payload Data (variable, encrypted) |
? |
? |
Padding (0-255 bytes, encrypted) |
|
? |
? |
|
Pad Length (encrypted) |
? |
? |
|
Next Header (encrypted) |
? |
? |
|
Integrity Check Value (ICV, variable) |
Unlike every other protocol in pcapkit, ESP is not self
describing. RFC 4303 places the Pad Length and Next Header
fields inside the ciphertext, and leaves the length of the Integrity
Check Value to be determined by the Security Association (SA), which is
negotiated out of band. Therefore:
Without SA context,
ESPparses theSPIandSequence Number, reports the remainder as an opaque encrypted payload, and says so throughesp.status. It does not guess at the trailer, and it does not raise.With SA context,
ESPsplits off the ICV, verifies integrity, decrypts, strips the padding usingPad Length, and dispatches the recovered plaintext to the next layer usingNext Header– so an ESP tunnelled TCP segment decodes as TCP.
SA context is supplied through the generic, protocol keyed context channel
in pcapkit.corekit.context:
import pcapkit
from pcapkit.protocols.internet.esp import (Cipher, ESPContext, Integrity,
SecurityAssociation)
sa = SecurityAssociation(
spi=0x4321,
encryption=Cipher.AES_CBC,
encryption_key=bytes.fromhex('90d382b410eeba7ad938c46cec1a82bf'),
integrity=Integrity.HMAC_SHA2_256_128,
integrity_key=bytes.fromhex('00' * 32),
destination='192.168.123.100', # optional, disambiguates several tunnels
)
extraction = pcapkit.extract('esp.pcap', context=ESPContext(sa))
Registered algorithms, and supported ones¶
ESP has no algorithm registry of its own – an SA’s algorithms are negotiated
by IKEv2 – so Cipher and
Integrity are generated from
the IKEv2 transform ID sub-registries and enumerate everything IANA has
registered: 3DES, AES-CTR, the AES-CCM and Camellia families,
ChaCha20-Poly1305, the implicit IV variants of RFC 8750, the RFC 9227
MGM suites, and the transforms long since deprecated.
Registration is not support. A member of either enumeration says only that
IANA assigned the transform an ID; what pcapkit can actually apply is
the separate, explicit CIPHER_SUITES and INTEGRITY_SUITES
tables, and CipherSuite.get() / IntegritySuite.get() refuse
anything outside them rather than half-working:
>>> Cipher.get('ENCR_3DES') # registered, so the enum has it
<Cipher.ENCR_3DES: 3>
>>> CipherSuite.get('ENCR_3DES') # but ESP cannot apply it
Traceback (most recent call last):
...
pcapkit.utilities.exceptions.ProtocolError: unsupported ESP encryption
algorithm: ENCR_3DES; pcapkit implements ENCR_NULL, ENCR_AES_CBC,
ENCR_AES_GCM_8, ENCR_AES_GCM_12, ENCR_AES_GCM_16
Decryption requires the optional cryptography dependency
(pip install pypcapkit[crypto]). pcapkit imports and works
without it; an SA that names an AES suite simply degrades to the opaque
payload path, with a warning.
The supported set is anchored on the mandatory to implement algorithms of
RFC 8221. The rows marked yes are exactly the keys of
CIPHER_SUITES; everything else the registry lists is enumerated and
rejected.
Encryption |
RFC 8221 status |
Implemented |
Notes |
|---|---|---|---|
|
MUST |
yes |
RFC 2410; needs no |
|
MUST |
yes |
RFC 3602; 128/192/256-bit keys |
|
MUST |
yes |
RFC 4106; 8-octet explicit IV |
|
– |
yes |
RFC 4106, 8-octet ICV |
|
– |
yes |
RFC 4106, 12-octet ICV |
|
SHOULD |
no |
registered, not implemented |
|
SHOULD |
no |
registered, not implemented |
|
SHOULD NOT |
no |
registered, deliberately omitted |
DES, Blowfish, 3IDEA |
MUST NOT |
no |
registered, deliberately omitted |
“DES, Blowfish, 3IDEA” above covers ENCR_DES, ENCR_DES_IV64,
ENCR_DES_IV32, ENCR_BLOWFISH and ENCR_3IDEA.
Likewise, the rows marked yes below are exactly the keys of
INTEGRITY_SUITES:
Integrity |
RFC 8221 status |
Implemented |
Notes |
|---|---|---|---|
|
MUST (AEAD only) |
yes |
for AEAD suites |
|
MUST |
yes |
|
|
SHOULD |
yes |
|
|
– |
yes |
|
|
MUST- |
yes |
RFC 2404; still widely captured |
|
SHOULD / MAY |
no |
registered, not implemented |
|
MAY |
no |
registered, not implemented |
MD5, DES-MAC, KPDK-MD5 |
MUST NOT |
no |
registered, deliberately omitted |
“MD5, DES-MAC, KPDK-MD5” above covers AUTH_HMAC_MD5_96,
AUTH_HMAC_MD5_128, AUTH_DES_MAC and AUTH_KPDK_MD5. The registry
spells the “no integrity algorithm” transform NONE rather than
AUTH_NONE, and Integrity.NONE follows it.
Both enumerations additionally carry each transform’s prefix-stripped spelling
as an alias, since that is how ESP and RFC 8221 name the algorithms, so
Cipher.AES_CBC and
Cipher.ENCR_AES_CBC
are the same member.
Known limitations¶
Extended Sequence Numbers (ESN, RFC 4303 §2.2.1) are not supported. The high-order 32 bits of an ESN are not transmitted, and a stateless parser cannot recover them; they are required both for the ICV computation and for the AEAD associated data. An ESN protected packet therefore fails the integrity check cleanly rather than being decoded.
Traffic Flow Confidentiality (TFC) padding (§2.4) is not detected. TFC padding is indistinguishable from real payload without inspecting the inner protocol’s own length field, so it is handed to the next layer as part of the plaintext.
Anti-replay is not performed.
pcapkitis an analyser, not a receiver; the sequence number is reported, never checked.The ICV is verified but a failure is reported rather than raised, so that one bad packet does not abort a capture.
- class pcapkit.protocols.internet.esp.ESP(file=None, length=None, **kwargs)[source]¶
-
This class implements Encapsulating Security Payload.
- property name: Literal['Encapsulating Security Payload']¶
Name of corresponding protocol.
- property length: int¶
Length of the ESP header, payload, trailer and ICV.
Note
Unlike most protocols, this is not just the fixed header: RFC 4303 puts the trailer and the ICV at the end of the packet, and the next layer is recovered from inside the ciphertext rather than from the bytes that follow. Every byte ESP owns is therefore counted here.
- read(length=None, *, version=4, extension=False, **kwargs)[source]¶
Read Encapsulating Security Payload.
Structure of ESP header [RFC 4303]:
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ---- | Security Parameters Index (SPI) | ^Int. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Cov- | Sequence Number | |ered +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ---- | Payload Data* (variable) | | ^ ~ ~ | | | | |Conf. + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Cov- | | Padding (0-255 bytes) | |ered* +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | | Pad Length | Next Header | v v +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ------ | Integrity Check Value-ICV (variable) | ~ ~ | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Parameters:
version (
Literal[4,6]) – IP protocol version.extension (
bool) – If the protocol is used as an IPv6 extension header. Unlike the other extension headers, ESP terminates the header chain – everything after it is encrypted – so it decodes its own next layer either way.**kwargs (
Any) – Arbitrary keyword arguments.
- Return type:
- Returns:
Parsed packet data.
Notes
The outer destination address, used to disambiguate Security Associations that share an SPI, is taken from the
packetinformation the enclosing IP layer passes down. It is not available for every encapsulation, and an SA that names a destination still matches when it cannot be confirmed – seeSecurityAssociation.matches().
- make(spi=0, seq=0, next=<TransType.UDP: 17>, next_default=None, next_namespace=None, next_reversed=False, encrypt=False, iv=None, pad_len=None, icv=b'', payload=b'', **kwargs)[source]¶
Make (construct) packet data.
There are two modes, chosen by
encrypt:encrypt=False(the default) writespayloadafter the SPI and sequence number verbatim, followed byicv. This is the mode used to reproduce a captured packet byte for byte, and is what_make_data()drives – re-encrypting a packet that was only ever read would change its bytes.encrypt=Truetreatspayloadas the inner plaintext: it appends RFC 4303 §2.4 padding, the pad length andnext, encrypts the result under the Security Association matchingspi, and appends the resulting ICV.
- Parameters:
spi (
int) – Security Parameters Index.seq (
int) – Sequence number.next (
TransType|IntEnum|IntEnum|str|int) – Next header type, written into the ESP trailer. Only used whenencryptisTrue.next_default (
int|None) – Default value of next header type.next_namespace (
dict[str,int] |dict[int,str] |Type[IntEnum] |Type[IntEnum] |None) – Namespace of next header type.next_reversed (
bool) – If the namespace is reversed.encrypt (
bool) – Whether to protectpayload, as described above.iv (
bytes|None) – Explicit IV to use; a random one is generated when omitted. Only used whenencryptisTrue.pad_len (
int|None) – Pad length to use; the smallest value that satisfies the alignment requirement is chosen when omitted. Only used whenencryptisTrue.icv (
bytes) – Integrity check value. Ignored whenencryptisTrue, where it is computed instead.payload (
bytes|ProtocolBase|Schema) – Payload of current instance.**kwargs (
Any) – Arbitrary keyword arguments.
- Return type:
- Returns:
Constructed packet data.
- Raises:
ProtocolError – If
encryptisTrueand no Security Association is available forspi, or ifpad_lendoes not satisfy the algorithm’s alignment requirement.
- classmethod _make_data(data)[source]¶
Create key-value pairs from
datafor protocol construction.The payload is reproduced verbatim rather than re-encrypted, so that reconstruction is byte exact and does not need the keys.
- static _payload_bytes(payload)[source]¶
Render
payloadasbytes.- Parameters:
payload (
bytes|ProtocolBase|Schema) – Payload as supplied tomake().- Return type:
- Returns:
Packed payload.
- Raises:
ProtocolUnbound – If
payloadis of an unsupported type. This mirrorsSchema.pack, which rejects the same set.
- static _read_trailer(plaintext, association, spi)[source]¶
Split the ESP trailer off the decrypted plaintext.
- Parameters:
plaintext (
bytes) – Decrypted payload data, i.e. the inner payload followed by the ESP trailer.association (
SecurityAssociation) – Security Association the packet was decrypted with.spi (
int) – Security Parameters Index, for the diagnostic message.
- Return type:
- Returns:
A 4-tuple of the inner payload, the padding, the pad length and the next header, or a
strexplaining why the trailer is not self consistent.
- _make_opaque(spi, seq, total, payload_data, status, error, *, icv=b'', version=4, packet=None, warning=True)[source]¶
Report an ESP packet whose payload was not decrypted.
The payload is surfaced as
Raw– which is what a next header ofNoneresolves to – so thatself.payloadand the protocol chain behave as they do for any other protocol, and the trailer fields are leftNonerather than guessed at.- Parameters:
spi (
int) – Security Parameters Index.seq (
int) – Sequence number.total (
int) – Total length of the ESP portion of the packet.payload_data (
bytes) – Payload data, excluding the ICV.status (
ESPStatus) – Why the payload was not decrypted.error (
str) – Human readable form ofstatus.icv (
bytes) – Integrity check value, when its length is known.version (
Literal[4,6]) – IP protocol version.packet (
dict[str,Any] |None) – Packet information from the enclosing layer.warning (
bool) – Whether to warn; a capture taken without keys is the expected case and does not warrant one.
- Return type:
- Returns:
Parsed packet data.
- __post_init__(file=None, length=None, *, version=4, extension=False, **kwargs)[source]¶
Post initialisation hook.
- Overloads:
self, file (IO[bytes] | bytes), length (Optional[int]), version (Literal[4, 6]), extension (bool), kwargs (Any) → None
self, kwargs (Any) → None
- Parameters:
See also
For construction argument, please refer to
self.make.
Security Associations¶
SA context is supplied through the generic, protocol keyed channel of
pcapkit.corekit.context.
- class pcapkit.protocols.internet.esp.SecurityAssociation(spi=None, *, encryption=<Cipher.ENCR_NULL: 11>, encryption_key=b'', salt=None, integrity=<Integrity.NONE: 0>, integrity_key=b'', icv_length=None, destination=None, strict=True)[source]¶
Bases:
objectAn inbound IPsec Security Association, as far as ESP parsing needs one.
- Parameters:
spi (
int|None) – Security Parameters Index the SA applies to;Nonematches any SPI, which is convenient for a capture holding a single tunnel.encryption (
Cipher|str|int) – Encryption algorithm, c.f.CipherSuite.get(). Must be onepcapkitimplements; being in the IANA registry is not enough.encryption_key (
bytes) – Encryption keying material. For an AEAD suite this is the AES key followed by the 4-octet salt [RFC 4106 §8.1], unlesssaltis given separately.salt (
bytes|None) – AEAD salt, when not appended toencryption_key.integrity (
Integrity|str|int) – Integrity algorithm, c.f.IntegritySuite.get(). Must beIntegrity.NONEfor an AEAD suite, which provides its own.integrity_key (
bytes) – Integrity key.icv_length (
int|None) – Override for the ICV length, in octets. Needed for the long standing implementation bug noted in RFC 8221 §6, whereAUTH_HMAC_SHA2_256_128is truncated to 96 rather than 128 bits.destination (
IPv4Address|IPv6Address|str|int|bytes|None) – Outer destination address the SA applies to. IPsec keys an SA by(SPI, destination, protocol), and supplying the address is what lets several tunnels sharing an SPI be told apart. Matched only when the outer destination is known topcapkit; seeESP.read().strict (
bool) – Whether a padding pattern that does not follow the monotonically increasing sequence of RFC 4303 §2.4 should be treated as a decryption failure. Only applied when nothing else authenticated the packet, since a verified ICV or AEAD tag is a far better signal than the padding is. Some implementations pad with zeros; set toFalsefor those.
- Raises:
ProtocolError – If the algorithms or key lengths are inconsistent.
Important
Key material is held in private attributes of this object, and is exposed only through
encryption_key/integrity_key. It is deliberately absent from__repr__(), and it is never copied into the ESP data model, which is the only thing that reachesInfo.to_dictand hence the output dumpers.- matches(spi, destination=None)[source]¶
Score how well the SA matches a packet.
- Parameters:
spi (
int) – SPI read from the packet.destination (
IPv4Address|IPv6Address|None) – Outer destination address, if known.
- Return type:
- Returns:
A non-negative score, where a higher score is a better match, or
-1when the SA does not apply at all. An SA pinned to this exact SPI outranks a wildcard one, and an SA whose destination was confirmed outranks one whose destination is unconstrained.
Say whether the SA’s algorithms can be applied at all.
This is checked before a packet is processed, so that a missing optional dependency is reported as a configuration problem once per packet rather than raised as an error from
decrypt()– it is not a defect in the packet.
- compute_icv(spi, seq, body)[source]¶
Compute the ICV over the integrity protected part of the packet.
The integrity computation of RFC 4303 §2.8 covers the SPI, the Sequence Number, the payload data (including any explicit IV) and the explicit ESP trailer – that is, everything transmitted except the ICV itself.
- Parameters:
- Return type:
- Returns:
The truncated ICV.
- Raises:
ProtocolError – If the SA has no separate integrity algorithm.
- decrypt(spi, seq, body, icv)[source]¶
Decrypt the payload data of an ESP packet.
- Parameters:
spi (
int) – Security Parameters Index.seq (
int) – Sequence number.body (
bytes) – Payload data as transmitted, i.e. the explicit IV (if the algorithm uses one) followed by the ciphertext.icv (
bytes) – ICV as transmitted; for an AEAD algorithm this is the authentication tag and is an input to the decryption.
- Return type:
- Returns:
The plaintext, i.e. the inner payload followed by the ESP trailer (padding, pad length, next header).
- Raises:
ProtocolError – If the payload is malformed for the algorithm, or if
cryptographyis needed and unavailable.cryptography.exceptions.InvalidTag – If an AEAD tag fails to verify – typically a wrong key.
- encrypt(spi, seq, plaintext, iv=None)[source]¶
Encrypt the payload data of an ESP packet.
This is the inverse of
decrypt(), used byESP.make().- Parameters:
- Return type:
- Returns:
A 2-tuple of the payload data as it goes on the wire (explicit IV followed by ciphertext) and the AEAD tag, which is empty for a non-AEAD algorithm.
- Raises:
ProtocolError – If
ivis of the wrong length, or ifcryptographyis needed and unavailable.
- static _split_key(suite, material, salt)[source]¶
Split keying material into the key and the AEAD salt.
- Parameters:
suite (
CipherSuite) – Encryption algorithm parameters.material (
bytes) – Keying material as supplied by the caller.salt (
bytes|None) – Explicit salt, if the caller kept it separate.
- Return type:
- Returns:
A 2-tuple of the key and the salt.
- Raises:
ProtocolError – If the lengths do not match the algorithm.
- class pcapkit.protocols.internet.esp.ESPContext(*associations)[source]¶
Bases:
ProtocolContextCaller supplied Security Association context for
ESP.- Parameters:
*associations (
SecurityAssociation) – Security Associations to make available to the parser, in order of preference for otherwise equal matches.
- property associations: tuple[SecurityAssociation, ...]¶
Registered Security Associations.
- register(association)[source]¶
Add a Security Association to the context.
- Parameters:
association (
SecurityAssociation) – Security Association to add.- Raises:
ProtocolError – If
associationis not aSecurityAssociation.- Return type:
- match(spi, destination=None)[source]¶
Find the Security Association that best fits a packet.
- Parameters:
spi (
int) – SPI read from the packet.destination (
IPv4Address|IPv6Address|None) – Outer destination address, if known.
- Return type:
- Returns:
The best matching SA, or
Nonewhen none applies.
Algorithm Registries¶
The algorithm enumerations are the IANA IKEv2 transform ID registries,
generated into pcapkit.const.esp and re-exported here for convenience:
Cipher is
pcapkit.const.esp.cipher.Cipher and Integrity is
pcapkit.const.esp.integrity.Integrity.
Algorithm Support¶
A registry enumerates what IANA assigned an ID to, which is far more than
pcapkit implements. The tables below are the authority on what an SA may
actually name, and the two get methods refuse anything outside them.
- class pcapkit.protocols.internet.esp.CipherSuite(cipher: Cipher, is_aead: bool, iv_length: int, block_size: int, icv_length: int, key_sizes: tuple[int, ...], salt_length: int, requires_cryptography: bool)[source]¶
Bases:
NamedTupleParameters of an ESP encryption algorithm
pcapkitimplements.A member of
Cipherrecords only that IANA registered the transform. This records how to apply it, and membership ofCIPHER_SUITESis what “supported” means – see the module docstring.- is_aead: bool¶
Whether the algorithm is a combined mode (AEAD) algorithm, i.e. one that provides its own integrity protection.
- block_size: int¶
Cipher block size, in octets. RFC 4303 §2.4 additionally requires the ciphertext to be a multiple of 4 octets, which is why
ESP.make()aligns tomax(block_size, 4)rather than to this value alone.
- requires_cryptography: bool¶
Whether the algorithm needs the optional
cryptographydependency.
- classmethod get(value)[source]¶
Look up how to apply an encryption algorithm.
- Parameters:
value (
Cipher|str|int) – ACiphermember, an IKEv2 transform ID, or a name such as'AES-CBC','aes_cbc'or'ENCR_AES_CBC'.- Return type:
- Returns:
The suite describing how to apply the algorithm.
- Raises:
ProtocolError – If
valuenames no registered algorithm, or names onepcapkitdoes not implement. The registry is far larger than the set of suites here, so the second case is the common one.
- class pcapkit.protocols.internet.esp.IntegritySuite(integrity: Integrity, digest: str | None, icv_length: int, key_size: int)[source]¶
Bases:
NamedTupleParameters of an ESP integrity algorithm
pcapkitimplements.As with
CipherSuite, membership ofINTEGRITY_SUITES– not membership of the IANA registry – is what makes an algorithm supported.- digest: str | None¶
Name of the underlying hash, for
hmac.new(), orNonewhen the algorithm computes no ICV of its own.
- classmethod get(value)[source]¶
Look up how to apply an integrity algorithm.
- Parameters:
value (
Integrity|str|int) – AnIntegritymember, an IKEv2 transform ID, or a name such as'HMAC-SHA-256-128','hmac_sha2_256_128'or'AUTH_HMAC_SHA2_256_128'.- Return type:
- Returns:
The suite describing how to apply the algorithm.
- Raises:
ProtocolError – If
valuenames no registered algorithm, or names onepcapkitdoes not implement.
- pcapkit.protocols.internet.esp.CIPHER_SUITES: dict[Cipher, CipherSuite] = {<Cipher.ENCR_NULL: 11>: (<Cipher.ENCR_NULL: 11>, False, 0, 1, 0, (0,), 0, False), <Cipher.ENCR_AES_CBC: 12>: (<Cipher.ENCR_AES_CBC: 12>, False, 16, 16, 0, (16, 24, 32), 0, True), <Cipher.ENCR_AES_GCM_8: 18>: (<Cipher.ENCR_AES_GCM_8: 18>, True, 8, 1, 8, (16, 24, 32), 4, True), <Cipher.ENCR_AES_GCM_12: 19>: (<Cipher.ENCR_AES_GCM_12: 19>, True, 8, 1, 12, (16, 24, 32), 4, True), <Cipher.ENCR_AES_GCM_16: 20>: (<Cipher.ENCR_AES_GCM_16: 20>, True, 8, 1, 16, (16, 24, 32), 4, True)}¶
Encryption algorithms
pcapkitimplements, keyed by IKEv2 transform. This table – notCipher, which is the whole IANA registry – defines what an SA may name.
- pcapkit.protocols.internet.esp.INTEGRITY_SUITES: dict[Integrity, IntegritySuite] = {<Integrity.NONE: 0>: (<Integrity.NONE: 0>, None, 0, 0), <Integrity.AUTH_HMAC_SHA1_96: 2>: (<Integrity.AUTH_HMAC_SHA1_96: 2>, 'sha1', 12, 20), <Integrity.AUTH_HMAC_SHA2_256_128: 12>: (<Integrity.AUTH_HMAC_SHA2_256_128: 12>, 'sha256', 16, 32), <Integrity.AUTH_HMAC_SHA2_384_192: 13>: (<Integrity.AUTH_HMAC_SHA2_384_192: 13>, 'sha384', 24, 48), <Integrity.AUTH_HMAC_SHA2_512_256: 14>: (<Integrity.AUTH_HMAC_SHA2_512_256: 14>, 'sha512', 32, 64)}¶
Integrity algorithms
pcapkitimplements, keyed by IKEv2 transform.Integrity.NONEis here because “no separate integrity algorithm” is a supported configuration – it is what an AEAD suite, and an unprotected SA, use.
- pcapkit.protocols.internet.esp._resolve(registry, value, prefix, kind)[source]¶
Resolve
valueto a member of an IKEv2 transform registry.- Parameters:
registry (
Type[Cipher] |Type[Integrity]) –CipherorIntegrity.value (
Any) – A member ofregistry, an IKEv2 transform ID, or a transform name.prefix (
str) – Prefix the registry spells its names with, i.e.'ENCR_'or'AUTH_'.kind (
str) – Word naming the registry for the error message, i.e.'encryption'or'integrity'.
- Return type:
- Returns:
The corresponding member of
registry.- Raises:
ProtocolError – If
valuenames nothing the registry holds.
Notes
Both enumerations carry each transform’s prefix-stripped spelling as an alias, so a plain lookup already accepts
'AES_CBC'as well as'ENCR_AES_CBC'.prefixis still needed for the few names that are no Python identifier once stripped, and so have no alias –ENCR_3DESandENCR_3IDEA.Resolution is deliberately separate from support: it answers only whether IANA registered the transform. See
CipherSuite.get().
Processing Status¶
- class pcapkit.protocols.internet.esp.ESPStatus(*values)[source]¶
Bases:
IntEnumOutcome of ESP payload processing.
- DECRYPTED = 0¶
The payload was decrypted and its trailer recovered.
- NO_SA = 1¶
No Security Association matched the packet’s SPI, so the payload is reported as opaque ciphertext. This is the expected state for a capture taken without keys, and is not an error.
- AUTH_FAILED = 2¶
A Security Association matched, but the ICV did not verify.
- DECRYPT_FAILED = 3¶
A Security Association matched and the packet was authentic (or unauthenticated), but decryption did not yield a self consistent RFC 4303 trailer – most commonly a wrong encryption key.
- TRUNCATED = 4¶
The packet is shorter than the Security Association says it must be.
- UNSUPPORTED = 5¶
A Security Association matched but its algorithms cannot be applied, e.g. because the optional
cryptographydependency is missing.
- pcapkit.protocols.internet.esp.load_cryptography()[source]¶
Load the optional
cryptographyprimitives.- Return type:
- Returns:
A 4-tuple of
(Cipher, algorithms, modes, InvalidTag)taken fromcryptography.hazmat.primitives.ciphersandcryptography.exceptions, orNonewhencryptographyis not installed.
Notes
The import is attempted at most once and the outcome is cached, so that a capture full of ESP packets does not pay for a failing import on every frame.
Header Schemas¶
- class pcapkit.protocols.schema.internet.esp.ESP(dict_=None, **kwargs)[source]¶
Bases:
SchemaHeader schema for ESP packet.
Notes
Only the two fixed fields of RFC 4303 –
SPIandSequence Number– can be described declaratively. Everything after them (the payload data, including any cryptographic synchronisation such as an IV, the ESP trailer and the optional Integrity Check Value) is of a length that is a property of the Security Association rather than of the packet, so it is captured verbatim aspayloadand split byESP.read.This also means
payloadis not the next layer’s data: the next layer lives inside the ciphertext, and is handed toProtocol._decode_next_layerexplicitly once decrypted.
Data Models¶
- class pcapkit.protocols.data.internet.esp.ESP(*args: VT, **kwargs: VT)[source]¶
Bases:
ProtocolData model for ESP protocol.
The trailer fields (
next,pad_len,padding) andplaintextare recovered from the decrypted payload, and are thereforeNonewhenever the payload could not be decrypted – RFC 4303 places them inside the ciphertext, so guessing them from an encrypted payload is not possible.statussays which of those two cases applies, anderrorsays why.Important
No key material is recorded here, by design. This data model is what
Info.to_dictreturns and hence what reaches the output dumpers, so the Security Association – and the keys it holds – is deliberately kept out of it.- length: int¶
Total length of the ESP header, payload, trailer and ICV, i.e. every byte of the packet that ESP owns.
- payload_data: bytes¶
Payload data exactly as transmitted – ciphertext, prefixed by any cryptographic synchronisation data (IV) – excluding the ICV.