synta 0.1.12

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
# CertificationRequest (CSR)


`CertificationRequest` represents an RFC 2986 PKCS#10 Certificate Signing Request.

## Construction

```python
CertificationRequest.from_der(data: bytes) -> CertificationRequest
CertificationRequest.from_pem(data: bytes) -> CertificationRequest | list[CertificationRequest]
CertificationRequest.to_pem(csr_or_list) -> bytes
```

## Properties

| Property | Type | Description |
|---|---|---|
| `version` | `int` | CSR version (always `0` = v1 per RFC 2986) |
| `subject` | `str` | RFC 4514 DN string |
| `subject_raw_der` | `bytes` | Raw DER of subject Name SEQUENCE |
| `signature_algorithm` | `str` | Algorithm name or dotted OID |
| `signature_algorithm_oid` | `ObjectIdentifier` | |
| `signature` | `bytes` | Raw signature bytes |
| `public_key_algorithm` | `str` | Algorithm name or dotted OID |
| `public_key_algorithm_oid` | `ObjectIdentifier` | |
| `public_key` | `bytes` | Raw subject public key bytes |

## Methods

| Method | Signature | Returns | Description |
|---|---|---|---|
| `to_der()` | `()` | `bytes` | Original DER bytes |
| `get_extension_value_der` | `(oid: str \| ObjectIdentifier)` | `bytes \| None` | Return the extnValue bytes of the named extension from the CSR's `extensionRequest` attribute, or `None` if absent. |
| `subject_alt_names()` | `()` | `list[tuple[int, bytes]]` | Parse the SAN extension from the CSR's `extensionRequest` attribute. Returns `(tag_number, content_bytes)` pairs — the same format as `synta.parse_general_names()`. Returns an empty list if no SAN is present. |
| `verify_self_signature()` | `()` | `None` | Verify the PKCS#10 self-signature. Raises `ValueError` if the signature is invalid or the algorithm is unsupported. |

## Full class stub

```python
class CertificationRequest:
    @staticmethod
    def from_der(data: bytes) -> CertificationRequest: ...
    @staticmethod
    def from_pem(data: bytes) -> CertificationRequest | list[CertificationRequest]: ...
    @staticmethod
    def to_pem(csr_or_list) -> bytes: ...

    version: int
    subject: str
    subject_raw_der: bytes
    signature_algorithm: str
    signature_algorithm_oid: ObjectIdentifier
    signature: bytes
    public_key_algorithm: str
    public_key_algorithm_oid: ObjectIdentifier
    public_key: bytes

    def to_der(self) -> bytes: ...
    def get_extension_value_der(self, oid: str) -> bytes | None: ...
    def subject_alt_names(self) -> list[tuple[int, bytes]]: ...
    def verify_self_signature(self) -> None: ...
```

## Usage

```python
import synta

# Parse from DER
with open("request.csr", "rb") as f:
    csr = synta.CertificationRequest.from_der(f.read())

# Parse from PEM
pem_data = open("request.pem", "rb").read()
csr = synta.CertificationRequest.from_pem(pem_data)

# Access fields
print(csr.subject)
print(csr.public_key_algorithm)
print(csr.public_key_algorithm_oid)

# Verify the self-signature
try:
    csr.verify_self_signature()
    print("CSR self-signature is valid")
except ValueError as e:
    print(f"Invalid CSR: {e}")

# Retrieve the extensionRequest attribute (if present)
san_der = csr.get_extension_value_der("2.5.29.17")   # SubjectAltName
if san_der:
    # san_der is the extnValue content bytes — pass to a Decoder
    dec = synta.Decoder(san_der, synta.Encoding.DER)
    san_seq = dec.decode_sequence()
    while not san_seq.is_empty():
        tag_num, tag_class, _ = san_seq.peek_tag()
        child = san_seq.decode_implicit_tag(tag_num, "Context")
        print(f"SAN tag {tag_num}: {child.remaining_bytes()}")
```

See also [Certificate](certificate.md) for the issued certificate type and
[CRL](crl.md) for certificate revocation lists.