synta 0.2.4

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
# Format-Agnostic PKI Reader


`read_pki_blocks` is the single entry point for reading any supported PKI file
format — PEM, PKCS#7/CMS, PKCS#12, or raw DER — without knowing the format in advance.

## Function

```python
read_pki_blocks(data: bytes, password: bytes = None) -> list[tuple[str, bytes]]
```

Auto-detect the encoding of `data` and return every PKI object as a `(label, der_bytes)`
tuple, in document order.

**Supported formats:** PEM (any label), PKCS#7 / CMS SignedData (DER or BER), PKCS#12 PFX
(DER or BER), and raw DER.

### Label semantics

| Input format | Label per entry |
|---|---|
| PEM — PKCS#7 blocks | `"CERTIFICATE"` per embedded cert (block expanded) |
| PEM — all other block types | Block type as-is (`"CERTIFICATE"`, `"PRIVATE KEY"`, …) |
| PKCS#7 / CMS SignedData (binary) | `"CERTIFICATE"` per cert |
| PKCS#12 — `certBag` | `"CERTIFICATE"` per cert |
| PKCS#12 — `keyBag` / `pkcs8ShroudedKeyBag` | `"PRIVATE KEY"` per key |
| Raw DER | `"CERTIFICATE"` |

Malformed PEM blocks (bad base64, truncated header) are silently skipped.

### PKCS#12 encryption

When `password` is supplied and the library is built with `--features openssl`, encrypted
bags are decrypted. Without that feature (or when no password is given) encrypted bags are
**silently skipped**; unencrypted certificates in the same archive are still returned.
This differs from `load_pkcs12_certificates`, which raises `ValueError` on encrypted bags
when the `openssl` feature is absent.

### Errors

Raises `ValueError` on structural failures:
- A PKCS#7 block has malformed DER, or its contentType OID is not id-signedData.
- The PKCS#12 input has a structural ASN.1 error.
- `password` was supplied with the `openssl` feature and decryption failed (e.g. wrong
  password, unsupported cipher).

Raises `TypeError` if `data` is not `bytes`, or `password` is not `bytes` or `None`.

## Usage

```python
import synta

# Any format — let synta detect it automatically
data = open("bundle.p7b", "rb").read()   # or .pem, .p12, .der, …
blocks = synta.read_pki_blocks(data)
for label, der in blocks:
    print(f"{label}: {len(der)} bytes")

# Parse the DER bytes directly
certs = [synta.Certificate.from_der(der)
         for label, der in blocks if label == "CERTIFICATE"]

# PKCS#12 with a password (openssl feature required for encrypted bags)
data = open("archive.p12", "rb").read()
blocks = synta.read_pki_blocks(data, b"s3cr3t")

# Split certificates and private keys
certs = [synta.Certificate.from_der(der) for label, der in blocks if label == "CERTIFICATE"]
key_ders = [der for label, der in blocks if label == "PRIVATE KEY"]
```

See also [PKCS Loaders](pkcs-loaders.md) for format-specific functions with precise error
semantics, and [PEM/DER](pem-der.md) for simple PEM encode/decode.