Security API Reference¶
Classes for creating and processing Bundle Protocol Security (BPSec) extension blocks.
Security Workflow¶
bespokebpv7 builds and parses BPSec blocks, but it does not run the
cryptography. You compute the HMAC or authentication tag yourself, then
store it in the block as a security result. This keeps full control over
the bytes for V&V testing, including deliberately wrong results.
The sequence for a Block Integrity Block (BIB) is:
- Build the bundle's primary block.
- Compute the security result over the target block.
- Create the
BlockIntegrityBlock: set its targets and source, then add eachSecurityParameter(SHA variant, integrity scope flags) and theSecurityResult. - Add the BIB to the
BPv7bundle, followed by the payload block so the payload stays last.
The example below reproduces RFC 9173 Appendix A.1 (an HMAC-SHA-512 BIB over the payload block). The serialized bundle is byte-for-byte identical to the one in the RFC.
import hashlib
import hmac
import cbor2
from bespokebpv7 import BlockType, BPv7
from bespokebpv7.block_enum import BIBSHAVariant, IntegrityScopeFlags
from bespokebpv7.bpsec import BlockIntegrityBlock
key = bytes.fromhex("1a2b1a2b1a2b1a2b1a2b1a2b1a2b1a2b")
payload = b"Ready to generate a 32-byte payload"
# 1. Primary block: ipn:2.1 -> ipn:1.2, creation time 0, sequence 40
bundle = BPv7()
bundle.primary_block.route.dest_eid = "ipn:1.2"
bundle.primary_block.route.source_eid = "ipn:2.1"
bundle.primary_block.route.report_to = "ipn:2.1"
bundle.primary_block.life.timestamp_ms = 0
bundle.primary_block.life.sequence = 40
bundle.primary_block.life.lifetime = 1000000
# 2. Integrity-protected plaintext (RFC 9173 Section 3.7) with no
# additional scope: the CBOR-encoded scope flags followed by the
# target block's CBOR-encoded block-type-specific data.
scope = IntegrityScopeFlags(0)
ippt = cbor2.dumps(int(scope)) + cbor2.dumps(payload)
mac = hmac.new(key, ippt, hashlib.sha512).digest()
# 3. BIB targeting the payload block (block number 1)
bib = BlockIntegrityBlock(block_number=2)
bib.security_targets = [1]
bib.security_source = [2, [2, 1]] # ipn:2.1, CBOR form written as-is
bib.set_sha_variant(BIBSHAVariant.HMAC_512_512)
bib.integrity_scope_flags = scope
bib.add_integrity_scope()
bib.add_security_result(mac)
# 4. BIB first, then the payload block
bundle.blocks[BlockType.BIB] = bib
bundle.add_payload_block(payload)
serialized = bytes(bundle)
When a scope flag is set, the IPPT also includes the primary block, the
target block header or the security block header, as listed in RFC 9173
Section 3.7. To check a received BIB, rebuild the IPPT from the parsed
bundle, compute the HMAC with the shared key and compare it with
bib.security_results[0].value using hmac.compare_digest.
A Block Confidentiality Block (BCB) follows the same steps with
BlockConfidentialityBlock. Add the initialization vector as
SecurityParameter(BCBParmEnum.IV, iv) (RFC 9173 requires it; there is
no helper method), then set_aes_variant() and add_aad_scope(), and
store the AES-GCM authentication tag with add_security_result(). The
target block's data must also be replaced with the ciphertext.
Classes¶
SecurityParameter¶
Represents a single Security Context Parameter.
Structure: [ Parameter ID, Parameter Value ].
Attributes:
parm_id(int): The parameter identifier.value(bytes | int): The parameter value.
Methods:
_structure(cls, data: list[Any]) -> Self: Structure aSecurityParameterfrom a list._unstructure(self) -> list[Any]: Flatten class for CBOR encoding.
SecurityResult¶
Represents a single Security Result. Structure: [ Result ID, Result Value ].
Attributes:
result_id(int): The result identifier.value(bytes): The result value.
Methods:
_structure(cls, data: list[Any]) -> Self: Structure aSecurityResultfrom a list[id, value]._unstructure(self) -> list[int | bytes]: Flatten class for CBOR encoding.
AbstractSecurityBlock¶
Represents the Abstract Security Block (ASB). Inherits from CanonicalBlock.
Attributes:
security_targets(list[int]): List of security targets.security_context_id(int): Security context identifier. Defaults to0.security_context_flags(SecurityContextFlags): Security context flags.security_source(list[Any]): Security source. Defaults to[1, "none"].security_parameters(list[SecurityParameter]): List of security parameters.security_results(list[SecurityResult]): List of security results.parm_present(bool, property): Indicates if security parameters are present.
Methods:
set_context_flag(self, security_flag: SecurityContextFlags) -> None: Set an individual security context flag.clear_context_flag(self, security_flag: SecurityContextFlags) -> None: Clear an individual security context flag.
BlockIntegrityBlock¶
Block Integrity Block (BIB). Inherits from AbstractSecurityBlock.
Attributes:
block_type(BlockType): Block type. Defaults toBlockType.BIB.security_context_id(int): Security context identifier. Defaults to1.integrity_scope_flags(IntegrityScopeFlags): Integrity scope flags. Defaults toIntegrityScopeFlags(7).include_primary_block(bool, property): Whether to include the primary block in the integrity scope.include_target_header(bool, property): Whether to include the target header in the integrity scope.include_security_header(bool, property): Whether to include the security header in the integrity scope.
Methods:
set_sha_variant(self, variant: BIBSHAVariant | None = None) -> None: Set SHA variant security parameter.add_wrapped_key(self, key: bytes) -> None: Set wrapped key security parameter.add_integrity_scope(self, val: int | None = None) -> None: Store integrity scope flags as a security parameter.add_security_result(self, result: bytes) -> None: Add expected HMAC result.set_scope_flag(self, security_flag: IntegrityScopeFlags) -> None: Set an individual integrity scope flag.clear_scope_flag(self, security_flag: IntegrityScopeFlags) -> None: Clear an individual integrity scope flag._structure(cls, data: list[Any]) -> Self: Structure a BIB from a CBOR list._unstructure(self) -> list[Any]: Unstructure the BIB into a CBOR list.
BlockConfidentialityBlock¶
Block Confidentiality Block (BCB). Inherits from AbstractSecurityBlock.
Attributes:
block_type(BlockType): Block type. Defaults toBlockType.BCB.security_context_id(int): Security context identifier. Defaults to2.aad_scope_flags(AADScopeFlags): AAD scope flags. Defaults toAADScopeFlags(7).include_primary_block(bool, property): Whether to include the primary block in the AAD scope.include_target_header(bool, property): Whether to include the target header in the AAD scope.include_security_header(bool, property): Whether to include the security header in the AAD scope.
Methods:
set_aes_variant(self, variant: BCBAESVariant | None = None) -> None: Set AES-GCM variant security parameter.add_wrapped_key(self, key: bytes) -> None: Set wrapped key security parameter.add_aad_scope(self, val: int | None = None) -> None: Store AAD scope flags as a security parameter.add_security_result(self, result: bytes) -> None: Add authentication tag result.set_scope_flag(self, security_flag: AADScopeFlags) -> None: Set an individual AAD scope flag.clear_scope_flag(self, security_flag: AADScopeFlags) -> None: Clear an individual AAD scope flag._structure(cls, data: list[Any]) -> Self: Structure a BCB from a CBOR list._unstructure(self) -> list[Any]: Unstructure the BCB into a CBOR list.