# PKCS#5 v2.1 — Password-Based Cryptography (RFC 8018)
`synta.pkcs5` provides DER-encoding helpers for PKCS#5 v2.1 (RFC 8018)
parameter structures used in password-based key derivation and encryption.
Two fluent builder classes are exported from the `synta.pkcs5` submodule, and
are also available directly from the top-level `synta` module.
```python
import synta.pkcs5 as pkcs5
```
## Pbkdf2ParamsBuilder
Fluent builder for `PBKDF2-params` (RFC 8018 §5.2).
Required fields: `salt` and `iteration_count`. When `prf` is absent the
default HMAC-SHA-1 PRF is used per RFC 8018 §5.2; modern deployments should
always set `prf` explicitly to a SHA-2 HMAC.
```python
class Pbkdf2ParamsBuilder:
def __init__(self) -> None: ...
def salt(self, salt: bytes) -> Pbkdf2ParamsBuilder: ...
# Set the salt OCTET STRING.
# RFC 8018 recommends at least 8 bytes of random salt.
def iteration_count(self, count: int) -> Pbkdf2ParamsBuilder: ...
# Set the iterationCount.
# RFC 8018 minimum is 1000; modern deployments use at least 10 000.
# Raises ValueError if count is 0 (deferred to build()).
def key_length(self, len: int) -> Pbkdf2ParamsBuilder: ...
# Set the optional keyLength (output key length in bytes).
def prf(self, prf_oid: list[int]) -> Pbkdf2ParamsBuilder: ...
# Set the optional prf (pseudo-random function) algorithm OID.
# Use an OID constant from synta.pkcs5, e.g. list(pkcs5.ID_HMAC_WITH_SHA256.components()).
# When absent, defaults to HMAC-SHA-1 per RFC 8018.
# Raises ValueError if the OID is invalid (deferred to build()).
def build(self) -> bytes: ...
# Build the DER-encoded PBKDF2-params SEQUENCE.
# Raises ValueError if salt or iteration_count are missing, or if DER
# encoding fails.
def build_as_algorithm_identifier(self, alg_oid: list[int]) -> bytes: ...
# Build PBKDF2-params and wrap it as an AlgorithmIdentifier.
# Produces AlgorithmIdentifier { id-PBKDF2, PBKDF2-params } DER for use
# as the keyDerivationFunc field in Pbes2ParamsBuilder.
# Pass list(pkcs5.ID_PBKDF2.components()) as alg_oid.
# Raises ValueError if any required field is missing or encoding fails.
```
## Pbes2ParamsBuilder
Fluent builder for `PBES2-params` (RFC 8018 §6.2).
`PBES2-params` contains two `AlgorithmIdentifier` fields: the key derivation
function (typically PBKDF2) and the encryption scheme (typically AES-CBC-PAD).
Both fields are required.
```python
class Pbes2ParamsBuilder:
def __init__(self) -> None: ...
def key_derivation_func(self, alg_id_der: bytes) -> Pbes2ParamsBuilder: ...
# Set the keyDerivationFunc from a pre-encoded AlgorithmIdentifier DER blob.
# Use Pbkdf2ParamsBuilder.build_as_algorithm_identifier() to produce this.
def encryption_scheme(self, alg_id_der: bytes) -> Pbes2ParamsBuilder: ...
# Set the encryptionScheme from a pre-encoded AlgorithmIdentifier DER blob.
def encryption_scheme_from_oid(
self,
enc_oid: list[int],
iv: bytes,
) -> Pbes2ParamsBuilder: ...
# Set the encryptionScheme from an OID and an IV OCTET STRING value.
# Builds AlgorithmIdentifier { oid, OCTET STRING iv } for AES-CBC-PAD.
# enc_oid: e.g. list(pkcs5.AES256_CBC_PAD.components())
# iv: 16-byte initialization vector.
# Raises ValueError if the OID is invalid (deferred to build()).
def build(self) -> bytes: ...
# Build the DER-encoded PBES2-params SEQUENCE.
# Raises ValueError if either field was not set or DER encoding fails.
```
## OID constants (synta.pkcs5)
| `ID_PBKDF2` | `1.2.840.113549.1.5.12` | PBKDF2 key derivation |
| `ID_PBES2` | `1.2.840.113549.1.5.13` | PBES2 encryption scheme |
| `ID_HMAC_WITH_SHA1` | `1.2.840.113549.2.7` | HMAC-SHA-1 PRF (RFC 8018 default) |
| `ID_HMAC_WITH_SHA224` | `1.2.840.113549.2.8` | HMAC-SHA-224 PRF |
| `ID_HMAC_WITH_SHA256` | `1.2.840.113549.2.9` | HMAC-SHA-256 PRF |
| `ID_HMAC_WITH_SHA384` | `1.2.840.113549.2.10` | HMAC-SHA-384 PRF |
| `ID_HMAC_WITH_SHA512` | `1.2.840.113549.2.11` | HMAC-SHA-512 PRF |
| `AES128_CBC_PAD` | `2.16.840.1.101.3.4.1.2` | AES-128-CBC-PAD |
| `AES192_CBC_PAD` | `2.16.840.1.101.3.4.1.22` | AES-192-CBC-PAD |
| `AES256_CBC_PAD` | `2.16.840.1.101.3.4.1.42` | AES-256-CBC-PAD |
## Usage
### Building PBKDF2 parameters
```python,ignore
import os
import synta
import synta.pkcs5 as pkcs5
salt = os.urandom(16)
params_der = (
synta.Pbkdf2ParamsBuilder()
.salt(salt)
.iteration_count(600_000)
.key_length(32)
.prf(list(pkcs5.ID_HMAC_WITH_SHA256.components()))
.build()
)
```
### Building PBES2 parameters (PBKDF2 + AES-256-CBC)
```python,ignore
import os
import synta
import synta.pkcs5 as pkcs5
salt = os.urandom(16)
iv = os.urandom(16)
# Step 1: build the key derivation AlgorithmIdentifier
kdf_der = (
synta.Pbkdf2ParamsBuilder()
.salt(salt)
.iteration_count(600_000)
.prf(list(pkcs5.ID_HMAC_WITH_SHA256.components()))
.build_as_algorithm_identifier(list(pkcs5.ID_PBKDF2.components()))
)
# Step 2: wrap in PBES2-params with AES-256-CBC-PAD
pbes2_der = (
synta.Pbes2ParamsBuilder()
.key_derivation_func(kdf_der)
.encryption_scheme_from_oid(list(pkcs5.AES256_CBC_PAD.components()), iv)
.build()
)
# pbes2_der is ready for use as the parameters field of the
# PBES2 AlgorithmIdentifier (OID = pkcs5.ID_PBES2)
```
See also [PKCS#8 Private Key Envelope](../protocols/pkcs8.md) where PBES2
parameters appear when encrypting a `OneAsymmetricKey`, and
[CMS EncryptedData](../cms/encrypted-data.md) for symmetric encryption of CMS
content.