synta 0.2.4

ASN.1 parser, decoder, and encoder library with DER/BER support and C FFI
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
# Example Programs


Runnable programs in `examples/` exercise every binding documented
in this guide. Each program is self-contained and runs with:

```bash
uv run python3 examples/example_<name>.py
```

from the repository root (after `maturin develop`).

## 1. `example_pem_helpers.py` — PEM/DER conversion

[Source](example_pem_helpers.md) · [`example_pem_helpers.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_pem_helpers.py)

Bindings: `pem_to_der`, `der_to_pem`, `Certificate.from_pem`, `Certificate.to_pem`,
`CertificationRequest.from_pem`, `CertificationRequest.to_pem`,
`CertificateList.from_pem`, `CertificateList.to_pem`.

- Round-trip a single PEM certificate block through `pem_to_der` / `der_to_pem` (`pem_to_der` always returns `list[bytes]`).
- Show `pem_to_der` with a multi-block PEM chain.
- Use `Certificate.from_pem` on a single block and on a two-certificate chain.
- Use `Certificate.to_pem` on a single cert and a list of certs.

## 2. `example_certificate_fields.py` — All Certificate properties

[Source](example_certificate_fields.md) · [`example_certificate_fields.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_certificate_fields.py)

Bindings: `Certificate.from_der`, `Certificate.full_from_der`, all `Certificate`
properties (`serial_number`, `version`, `issuer`, `issuer_raw_der`, `subject`,
`subject_raw_der`, `not_before`, `not_after`, `signature_algorithm`,
`signature_algorithm_oid`, `signature_algorithm_params`, `signature_value`,
`public_key_algorithm`, `public_key_algorithm_oid`, `public_key_algorithm_params`,
`public_key`, `tbs_bytes`), and `Certificate.to_der()` method.

- Parse the same certificate with `from_der` (lazy) and `full_from_der` (eager).
- Print every property with its Python type.
- Verify `to_der()` round-trip (re-parse the returned bytes).
- Show `signature_algorithm_params` is `None` for Ed25519 and non-`None` for RSA.

## 3. `example_certificate_extensions.py` — Extension access, SAN parsing, and ext builders

[Source](example_certificate_extensions.md) · [`example_certificate_extensions.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_certificate_extensions.py)

Bindings: `Certificate.subject_alt_names`, `Certificate.extensions_der`,
`Certificate.get_extension_value_der`, `synta.general_name` tag constants,
`synta.parse_general_names`, `synta.parse_name_attrs`,
`synta.oids.SUBJECT_ALT_NAME`, `synta.oids.BASIC_CONSTRAINTS`,
`synta.oids.SUBJECT_KEY_IDENTIFIER`, `Decoder.decode_sequence`, `Decoder.peek_tag`,
`Decoder.decode_implicit_tag`, `Decoder.decode_explicit_tag`,
`Decoder.remaining_bytes`, `Decoder.decode_raw_tlv`, `Decoder.is_empty`;
`synta.ext.SubjectAlternativeNameBuilder` (alias `SAN`),
`synta.ext.ExtendedKeyUsageBuilder` (alias `EKU`),
`synta.ext.AuthorityInformationAccessBuilder` (alias `AIA`),
`synta.ext.basic_constraints`, `synta.ext.key_usage`,
`synta.ext.subject_key_identifier`, `synta.ext.authority_key_identifier`,
`synta.ext.KU_*` bitmask constants, `synta.ext.KEYID_*` method constants.

- Call `cert.subject_alt_names()` for high-level SAN access; dispatch on
  `synta.general_name` constants (`gn.DNS_NAME`, `gn.IP_ADDRESS`, etc.);
  use `ipaddress.ip_address(content)` for IP rendering.
- Verify that a certificate without a SAN extension returns an empty list.
- Access `extensions_der` and iterate the raw extension TLVs.
- Look up individual extensions by `get_extension_value_der`.
- Parse SAN entries manually with `peek_tag` / `decode_implicit_tag`
  as a lower-level alternative to `subject_alt_names()`.
- Demonstrate `peek_tag` for CHOICE dispatch; `remaining_bytes` for primitive implicit values.
- Look up BasicConstraints and decode the cA BOOLEAN.
- Build SAN DER with `SubjectAlternativeNameBuilder` (two dNSName, rfc822Name, iPAddress); verify
  with short alias `SAN`; build EKU DER with `ExtendedKeyUsageBuilder` (serverAuth+clientAuth);
  build AIA DER with `AuthorityInformationAccessBuilder` (OCSP+caIssuers); use short aliases.
- Encode `basic_constraints(ca=False)` (empty SEQUENCE) and `basic_constraints(ca=True, path_length=0)`.
- Encode `key_usage(KU_KEY_CERT_SIGN | KU_CRL_SIGN)` and `key_usage(KU_DIGITAL_SIGNATURE)`.
- Compute `subject_key_identifier` with RFC 5280 and RFC 7093 method 1 from SPKI DER;
  compute `authority_key_identifier` from issuer SPKI DER.

## 4. `example_certificate_pyca.py` — PyCA interoperability

[Source](example_certificate_pyca.md) · [`example_certificate_pyca.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_certificate_pyca.py)

Bindings: `Certificate.to_pyca`, `Certificate.from_pyca`.

- Parse a DER certificate with synta, then call `.to_pyca()` for cryptographic operations.
- Load a PyCA certificate, convert to synta with `from_pyca()`, and compare fields.
- Show `ImportError` message when `cryptography` is absent (caught and printed).

## 5. `example_csr.py` — PKCS#10 CSR parsing

[Source](example_csr.md) · [`example_csr.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_csr.py)

Bindings: `CertificationRequest.from_der`, `CertificationRequest.from_pem`,
`CertificationRequest.to_pem`, and all `CertificationRequest` properties.

- Parse a CSR from DER and print every field.
- Round-trip through PEM with `from_pem` / `to_pem`.
- Verify `subject_raw_der` by re-decoding it as a raw Name SEQUENCE.

## 6. `example_certificate_builder.py` — X.509 certificate building

[Source](example_certificate_builder.md) · [`example_certificate_builder.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_certificate_builder.py)

Bindings: `CertificateBuilder` (`issuer_name`, `subject_name`, `public_key`,
`public_key_der`, `serial_number`, `not_valid_before_utc`, `not_valid_after_utc`,
`add_extension`, `sign`, `sign_unsigned`); `NameBuilder`; `PrivateKey.generate_ec`;
`PublicKey.to_der`; `synta.ext.SubjectAlternativeNameBuilder`,
`synta.ext.ExtendedKeyUsageBuilder`, `synta.ext.basic_constraints`,
`synta.ext.key_usage`, `synta.ext.subject_key_identifier`,
`synta.ext.authority_key_identifier`, `synta.ext.KU_*` bitmask constants.

- Generate a self-signed CA certificate with `PrivateKey.generate_ec("P-256")`,
  `NameBuilder`, and `CertificateBuilder` (basicConstraints CA:TRUE, keyUsage
  keyCertSign+cRLSign, subjectKeyIdentifier); verify DER round-trip.
- Issue a leaf certificate signed by the CA key with `issuer_name` from
  `ca_cert.subject_raw_der`, SAN from `SubjectAlternativeNameBuilder`, EKU
  from `ExtendedKeyUsageBuilder` (serverAuth), basicConstraints CA:FALSE,
  authorityKeyIdentifier, and keyUsage digitalSignature+keyEncipherment.
- Demonstrate `public_key_der()` setter: pass pre-encoded SPKI DER bytes directly
  (zero re-encoding); verify `cert.subject_public_key_info_der` round-trip.
- Show `sign_unsigned()` (RFC 9925): confirm `signature_algorithm_oid` is
  `id-alg-unsigned` (1.3.6.1.5.5.7.6.36) and `signature_value` is empty.

## 7. `example_crl.py` — CRL parsing and building

[Source](example_crl.md) · [`example_crl.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_crl.py)

Bindings: `CertificateList.from_der`, `CertificateList.from_pem`,
`CertificateList.to_pem`, and all `CertificateList` properties
(`issuer`, `issuer_raw_der`, `this_update`, `next_update`, `signature_algorithm`,
`signature_algorithm_oid`, `signature_value`, `revoked_count`, `crl_number`);
`CertificateListBuilder` (`issuer`, `signature_algorithm`, `this_update`,
`next_update`, `revoke`, `build`, `assemble`); `NameBuilder`.

- Parse a CRL and print issuer, dates, algorithm, revoked count.
- Show `next_update` is `None` for CRLs that omit the field.
- Round-trip through `to_pem` / `from_pem`.
- Build a CRL from scratch with `CertificateListBuilder`: set issuer name via
  `NameBuilder`, add two revoked entries with `revoke()` (one with keyCompromise
  reason, one unspecified), call `build()` for the TBSCertList, assemble with a
  dummy signature via `assemble()`; verify `revoked_count == 2`.
- Show `crl_number` returns `None` when the CRL Number extension is absent.

## 8. `example_ocsp.py` — OCSP parsing and building

[Source](example_ocsp.md) · [`example_ocsp.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_ocsp.py)

Bindings: `OCSPResponse.from_der`, `OCSPResponse.from_pem`, `OCSPResponse.to_pem`,
and all `OCSPResponse` properties; `OCSPResponseBuilder` (`responder_name`,
`responder_key_hash`, `produced_at`, `add_response`, `build_tbs`, `assemble`);
`OCSPSingleResponse`; `OCSPRequest.from_der`, `OCSPRequest.from_pem`, `OCSPRequest.to_der`,
and all `OCSPRequest` properties (`request_list`, `requestor_name`, `request_extensions`);
`CertID` properties (`hash_algorithm_oid`, `issuer_name_hash`, `issuer_key_hash`,
`serial_number`); `OCSPRequestBuilder` (`add_request`, `requestor_name`, `build_tbs`,
`build_tbs_inner`, `assemble`); `OCSPCertIDSpec`; `NameBuilder`.

- Parse a successful OCSP response; print `status`, `response_type_oid`, length of `response_bytes`.
- Parse a non-successful response (e.g. `tryLater`); confirm `response_bytes` is `None`.
- Round-trip through `to_pem` / `from_pem`.
- Build an OCSP response from scratch with `OCSPResponseBuilder`: create a
  `OCSPSingleResponse` entry (SHA-1 name hash of issuer name, fixed key hash,
  status=good), set `responder_key_hash`, call `build_tbs()`, assemble with a
  dummy signature; verify `status == "successful"` and response OID.
- Demonstrate the `responder_name` variant using a DER Name from `NameBuilder`.
- Build an unsigned `OCSPRequest` with `OCSPRequestBuilder`: create an `OCSPCertIDSpec`
  (SHA-1 issuer name hash, fixed key hash, serial), call `build_tbs()`, parse the result
  back with `OCSPRequest.from_der`, and verify all `CertID` fields.
- Demonstrate the signed-request path: call `build_tbs_inner()`, assemble with a dummy
  signature via `assemble()`, parse back and confirm `request_list` length.
- Demonstrate `requestor_name` on `OCSPRequestBuilder` using a DER Name from `NameBuilder`.

## 9. `example_pkcs7.py` — PKCS#7 certificate bundles

[Source](example_pkcs7.md) · [`example_pkcs7.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_pkcs7.py)

Bindings: `load_der_pkcs7_certificates`, `load_pem_pkcs7_certificates`.

- Load a `.p7b` file and print the subject of each extracted certificate.
- Demonstrate PEM-encoded PKCS#7 with `load_pem_pkcs7_certificates`.
- Show `ValueError` for non-PKCS#7 input.

## 10. `example_pkcs12.py` — PKCS#12 archive parsing and creation

[Source](example_pkcs12.md) · [`example_pkcs12.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_pkcs12.py)

Bindings: `load_pkcs12_certificates`, `load_pkcs12_keys`, `load_pkcs12`,
`create_pkcs12`.

- Parse a password-less PKCS#12 file; print subjects of extracted certificates.
- Extract private keys using `load_pkcs12_keys`; show raw PKCS#8 DER length.
- Extract both with `load_pkcs12`; show the `(certs, keys)` tuple.
- Parse an AES-256-CBC encrypted PKCS#12 with a password.
- Show `ValueError` for wrong password (encrypted case, with `openssl` feature).
- Build a PFX from extracted certificates using `create_pkcs12` without a password.
- Build a password-protected PFX with `create_pkcs12` (requires `openssl` feature).
- Build a cert+key PFX bundle.
- Roundtrip: build an archive then parse it back and verify the extracted certificates.

## 11. `example_pki_blocks.py` — Format-agnostic PKI reader

[Source](example_pki_blocks.md) · [`example_pki_blocks.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_pki_blocks.py)

Bindings: `read_pki_blocks`.

- Pass PEM, DER, PKCS#7, and PKCS#12 bytes to `read_pki_blocks` and print the
  `(label, len(der))` tuples returned.
- Show PKCS#12 password handling.

## 12. `example_objectidentifier.py` — ObjectIdentifier constructors and operations

[Source](example_objectidentifier.md) · [`example_objectidentifier.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_objectidentifier.py)

Bindings: `ObjectIdentifier(str)`, `ObjectIdentifier.from_components`,
`ObjectIdentifier.from_der_value`, `ObjectIdentifier.components`,
`ObjectIdentifier.__eq__`, `ObjectIdentifier.__hash__`,
`Decoder.decode_oid`, `Encoder.encode_oid`, `Encoder.encode_oid_object`.

- Construct OIDs via all three constructors; verify they compare equal.
- Show `__eq__` working against a dotted string.
- Use OIDs as dict keys (demonstrate hashability).
- Round-trip through `encode_oid` / `decode_oid`.
- Show `from_der_value` with the raw content bytes from an implicit-tag context.

## 13. `example_oids_catalog.py``synta.oids` constant groups

[Source](example_oids_catalog.md) · [`example_oids_catalog.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_oids_catalog.py)

Bindings: every constant in `synta.oids` and `synta.oids.attr`,
plus the helper functions `identify_signature_algorithm`,
`identify_public_key_algorithm`.

- Print algorithm OIDs (RSA, EC, EdDSA, ML-DSA, ML-KEM).
- Print hash OIDs (SHA-2, SHA-3).
- Print SLH-DSA OIDs.
- Print prefix OIDs and demonstrate `components()`-based prefix matching.
- Print X.509v3 extension OIDs.
- Print EKU OIDs.
- Print PKINIT OIDs.
- Print MS PKI OIDs.
- Print all nine PKCS#9 attribute OIDs (`PKCS9_EMAIL_ADDRESS`, `PKCS9_CONTENT_TYPE`,
  `PKCS9_MESSAGE_DIGEST`, `PKCS9_SIGNING_TIME`, `PKCS9_COUNTERSIGNATURE`,
  `PKCS9_CHALLENGE_PASSWORD`, `PKCS9_EXTENSION_REQUEST`, `PKCS9_FRIENDLY_NAME`,
  `PKCS9_LOCAL_KEY_ID`).
- Print every `synta.oids.attr` DN attribute OID with its RFC 4514 label.

## 14. `example_time_types.py` — UtcTime and GeneralizedTime

[Source](example_time_types.md) · [`example_time_types.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_time_types.py)

Bindings: `UtcTime(…)`, `UtcTime` properties (`year`, `month`, `day`, `hour`,
`minute`, `second`), `GeneralizedTime(…)`, `GeneralizedTime` properties,
`Encoder.encode_utc_time`, `Encoder.encode_utc_time_object`,
`Encoder.encode_generalized_time`, `Encoder.encode_generalized_time_object`,
`Decoder.decode_utc_time`, `Decoder.decode_generalized_time`.

- Construct both time types and inspect every property.
- Round-trip each through encode / decode; verify string representations.
- Show millisecond sub-second precision on `GeneralizedTime`.
- Show `ValueError` for out-of-range UTCTime year (< 1950 or > 2049).
- Demonstrate `encode_utc_time_object` and `encode_generalized_time_object` variants.

## 15. `example_integer_advanced.py` — Integer edge cases and bigint

[Source](example_integer_advanced.md) · [`example_integer_advanced.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_integer_advanced.py)

Bindings: `Integer(int)`, `Integer.from_bytes`, `Integer.from_u64`,
`Integer.to_int`, `Integer.to_i128`, `Integer.to_bytes`,
`Encoder.encode_integer` (bigint path), `Encoder.encode_integer_object`.

- Construct integers via all three constructors.
- Show `to_int()` succeeds for small values; raises `OverflowError` for 20-byte serials.
- Use `to_i128()` for up to 16-byte values (i128 max = 2¹²⁷−1); show `OverflowError` beyond that.
- Use `to_bytes()` for arbitrary-precision big-endian representation.
- Encode a 20-byte certificate serial number via `encode_integer(large_python_int)`.
- Verify `encode_integer_object` round-trip.

## 16. `example_string_types_advanced.py` — Alternative string constructors

[Source](example_string_types_advanced.md) · [`example_string_types_advanced.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_string_types_advanced.py)

Bindings: `TeletexString.from_latin1`, `TeletexString.from_str`,
`GeneralString.from_ascii`, `GeneralString.from_str`,
`UniversalString.from_bytes`, `BmpString.from_bytes`,
plus `to_bytes()` / `as_str()` on each.

- Construct `TeletexString` from bytes and Latin-1 strings; `GeneralString` from bytes and ASCII strings.
- Construct `UniversalString` and `BmpString` from raw UCS-4/UCS-2 byte buffers.
- Show `ValueError` when non-BMP code points are passed to `BmpString`.
- Round-trip each through the encoder / decoder.

## 17. `example_decoder_advanced.py` — Advanced Decoder operations

[Source](example_decoder_advanced.md) · [`example_decoder_advanced.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_decoder_advanced.py)

Bindings: `Decoder.decode_set`, `Decoder.peek_tag`, `Decoder.decode_raw_tlv`,
`Decoder.remaining_bytes`, `Decoder.decode_implicit_tag`, `Decoder.position`,
`Decoder.remaining`, `Decoder.is_empty`, `Decoder.decode_any_str`.

- Build a hand-crafted SET and decode it with `decode_set`.
- Use `peek_tag` in a loop to drive CHOICE dispatch.
- Capture unknown elements with `decode_raw_tlv`.
- Use `decode_implicit_tag` + `remaining_bytes` to decode a primitive implicit type
  (e.g. `[2] IMPLICIT IA5String` for a dNSName GeneralName).
- Show `position()` and `remaining()` advancing through multi-element input.
- Use `decode_any_str()` to decode a mixed-string SEQUENCE without tag inspection.

## 18. `example_encoder_advanced.py` — Advanced Encoder operations

[Source](example_encoder_advanced.md) · [`example_encoder_advanced.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_encoder_advanced.py)

Bindings: `Encoder.encode_implicit_tag`, `Encoder.encode_set`,
`Encoder.encode_explicit_tag`, `Encoder.encode_sequence`,
and all `_object` variants not demonstrated elsewhere.

- Build a SET containing two PrintableStrings using `encode_set`.
- Encode an implicit context tag `[2] IMPLICIT IA5String` (dNSName).
- Encode a nested structure: SEQUENCE { [0] EXPLICIT SEQUENCE { INTEGER } }.
- Demonstrate every `_object` encode variant with a typed object sourced from a decode.
- Show `ValueError` for unknown tag class strings.

## 19. `example_krb5_principal.py` — Kerberos principal names

[Source](example_krb5_principal.md) · [`example_krb5_principal.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_krb5_principal.py)

Bindings: `synta.krb5.Krb5PrincipalName`, `synta.krb5.KRB5_PRINCIPAL_NAME_OID`,
and every `NT_*` constant.

- Construct `Krb5PrincipalName` instances for each name type (`NT_PRINCIPAL`,
  `NT_SRV_INST`, `NT_SRV_HST`, `NT_ENTERPRISE`, `NT_WELLKNOWN`).
- Encode each with `to_der()` and decode back with `from_der()`.
- Verify realm, name_type, and components survive the round-trip.
- Show `__eq__` and `__repr__`.
- Print `KRB5_PRINCIPAL_NAME_OID` and demonstrate it matches `synta.oids.PKINIT_SAN`.
- Show `ValueError` for non-ASCII realm or component.

## 20. `example_krb5_pkinit.py` — PKINIT protocol classes

[Source](example_krb5_pkinit.md) · [`example_krb5_pkinit.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_krb5_pkinit.py)

Bindings: `EncryptionKey`, `Checksum`, `KDFAlgorithmId`, `IssuerAndSerialNumber`,
`ExternalPrincipalIdentifier`, `PKAuthenticator`, `AuthPack`, `PaPkAsReq`,
`DHRepInfo`, `KDCDHKeyInfo`, `ReplyKeyPack`, `PaPkAsRep`.

For each class: parse hand-crafted DER bytes with `from_der`, access every property,
and print a summary of key values.

## 21. `example_error_handling.py` — Exception catalogue

[Source](example_error_handling.md) · [`example_error_handling.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_error_handling.py)

Bindings: `synta.SyntaError`, `ValueError`, `OverflowError`, `EOFError`.

- Inspect `SyntaError` as a module exception class (MRO, `issubclass` check).
- Demonstrate `EOFError` from empty input, tag-only input, and truncated value in `Decoder`.
- Demonstrate `ValueError` from tag mismatch (decoding BOOLEAN as INTEGER).
- Demonstrate `ValueError` from DER constraint violations (non-canonical BOOLEAN, non-minimal INTEGER).
- Demonstrate `OverflowError` from `Integer.to_int()` and `to_i128()` on values exceeding the target type.
- Demonstrate `ValueError` from constructor validation: `BmpString` with a non-BMP character,
  `GeneralizedTime` with an invalid month, `ObjectIdentifier` with a malformed string,
  `Krb5PrincipalName` with a non-ASCII realm, `GeneralString.from_ascii` with a non-ASCII character.

## 22. `example_cms_encrypted_data.py` — CMS EncryptedData round-trip

[Source](example_cms_encrypted_data.md) · [`example_cms_encrypted_data.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_cms_encrypted_data.py)

Bindings: `synta.cms.EncryptedData`, `synta.cms.ID_AES128_CBC`,
`synta.cms.ID_AES192_CBC`, `synta.cms.ID_AES256_CBC`.

Requires the `openssl` Cargo feature (`maturin develop --features openssl`).

- Create an `EncryptedData` with `EncryptedData.create` (AES-128-CBC) and inspect
  all properties: `version`, `content_type`, `content_encryption_algorithm_oid`,
  `content_encryption_algorithm_params` (IV extraction), `encrypted_content`.
- Decrypt → replace text in plaintext → re-encrypt with a fresh random IV;
  verify the round-trip with `to_der()` / `from_der()`.
- Encrypt with each of AES-128/192/256-CBC using `ID_AES128_CBC`,
  `ID_AES192_CBC`, `ID_AES256_CBC`; confirm random IV differs across calls.
- Verify synta-produced ciphertext with `openssl enc -d` (synta → openssl interop).
- Inspect the `EncryptedData` DER structure with `openssl asn1parse`.
- Encrypt raw bytes with `openssl enc -e`, wrap in an `EncryptedData` DER
  by hand, parse with `from_der`, and decrypt with synta (openssl → synta interop).

## 23. `example_x509_verify.py` — X.509 certificate chain verification

[Source](example_x509_verify.md) · [`example_x509_verify.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_x509_verify.py)

Bindings: `synta.x509.TrustStore`, `synta.x509.VerificationPolicy`,
`synta.x509.verify_server_certificate`, `synta.x509.verify_client_certificate`,
`synta.x509.X509VerificationError`.

Requires the `openssl` Cargo feature (`maturin develop --features openssl`).

- Build a self-signed root CA DER in memory with `openssl req -x509` and load it
  into a `TrustStore`; print `store.len` and `repr(store)`.
- Verify a leaf certificate signed by that root with `verify_server_certificate`;
  print the chain length and each certificate's subject with `synta.Certificate.from_der`.
- Demonstrate `VerificationPolicy` variants: single name, multi-name `any`, multi-name
  `all`, fixed `validation_time`, `max_chain_depth`, `profile="rfc5280"`.
- Demonstrate client certificate verification with `verify_client_certificate`.
- Show that `X509VerificationError` is raised when the trust store does not contain
  the issuer, the server name does not match the SAN, and the validation time is
  outside the validity window.

## 24. `example_general_name.py` — Typed GeneralName API

[Source](example_general_name.md) · [`example_general_name.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_general_name.py)

Bindings: `synta.general_name.DNSName`, `synta.general_name.IPAddress`,
`synta.general_name.RFC822Name`, `synta.general_name.OtherName`,
`synta.general_name.UniformResourceIdentifier`, `synta.parse_general_names`.

- Call `cert.subject_alt_names()` on a certificate with four SANs (two
  `dNSName`, one `iPAddress`, one `rfc822Name`); dispatch by `isinstance`.
- Use `cert.general_names(oid)` to retrieve SANs by extension OID.
- Use `synta.parse_general_names(san_der)` for low-level tag/bytes access.
- Demonstrate integer tag constants (`gn.DNS_NAME`, `gn.IP_ADDRESS`, etc.).

## 25. `example_pkixalgs.py` — RFC 3279 algorithm parameter types

[Source](example_pkixalgs.md) · [`example_pkixalgs.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_pkixalgs.py)

Bindings: `synta.pkixalgs.DssParms`, `synta.pkixalgs.ECParameters`,
`synta.pkixalgs.EcdsaSigValue`, `synta.pkixalgs.DssSigValue` and OID constants.

- Parse `DssParms` (DSA domain parameters P/Q/G) from hand-crafted DER; verify round-trip.
- Parse `ECParameters` in `namedCurve` form; access `arm` and `named_curve_oid`.
- Parse `EcdsaSigValue` (r and s components of an ECDSA signature).
- Use OID constants: `ID_DSA`, `ID_EC_PUBLIC_KEY`, `ECDSA_WITH_SHA256`, `PRIME256V1`.

## 26. `example_ac.py` — RFC 5755 Attribute Certificates

[Source](example_ac.md) · [`example_ac.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_ac.py)

Bindings: `synta.ac.AttributeCertificate` and related OID constants.

- Build a minimal RFC 5755 v2 Attribute Certificate from scratch in DER.
- Access all eight `AttributeCertificate` properties: `version`, `holder`,
  `issuer`, `signature_algorithm`, `serial_number`, `not_before`, `not_after`,
  `attributes`.
- Demonstrate OID constants: `ID_AT_ROLE`, `ID_PE_AC_AUDIT_IDENTITY`,
  `ID_CE_SUBJECT_DIRECTORY_ATTRIBUTES`.

## 27. `example_ms_pki.py` — Microsoft PKI (AD CS) extension types

[Source](example_ms_pki.md) · [`example_ms_pki.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_ms_pki.py)

Bindings: `synta.ms_pki.MSCSTemplateV2`, `synta.ms_pki.RequestClientInfo`
and OID constants.

- Parse `MSCSTemplateV2` with major version only and with both versions; verify
  `template_id`, `template_major_version`, `template_minor_version`, and
  `to_der()` round-trip.
- Parse `RequestClientInfo` with all four fields present, with partial fields,
  and from an empty SEQUENCE.
- Print all nineteen OID constants with their dot-notation values.

## 28. `example_spnego.py` — SPNEGO negotiation tokens (RFC 4178)

[Source](example_spnego.md) · [`example_spnego.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_spnego.py)

Bindings: `synta.spnego.NegTokenInit`, `synta.spnego.NegTokenResp`,
`synta.spnego.NegotiationToken`, `NEG_STATE_*` constants, `SPNEGO_OID`.

> **DER encoding note:** GssapiSpnego.asn1 uses `DEFINITIONS IMPLICIT TAGS`.
> The example builds all test vectors using IMPLICIT encoding helpers.

- Parse `NegTokenInit` with `mech_types` (two OIDs) and `mech_token`; verify
  each property and confirm `req_flags`/`mech_list_mic` are absent.
- Parse an empty `NegTokenInit` SEQUENCE; verify `mech_types == []`.
- Parse `NegotiationToken` in the `negTokenInit` CHOICE arm (`0xa0`) and the
  `negTokenResp` arm (`0xa1`).
- Parse a GSSAPI-wrapped token (`0x60` APPLICATION tag) and verify that
  `from_der` strips the OID prefix automatically.
- Parse `NegTokenResp` with `neg_state` 3 (`NEG_STATE_REQUEST_MIC`) and a
  `response_token`; verify `supported_mech` and `mech_list_mic`.
- Verify all four `NEG_STATE_*` integer constants and `SPNEGO_OID`.

## 29. `example_crmf.py` — CRMF certificate request messages

[Source](example_crmf.md) · [`example_crmf.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_crmf.py)

Bindings: `CertReqMsgBuilder`, `CertReqMessagesBuilder`, `CertReqMessages.from_der`,
`CertReqMsg.from_der`; OID constants from `synta.crmf`.

- Build a `CertReqMsg` with `CertReqMsgBuilder`: set subject name via `NameBuilder`,
  add a `SubjectPublicKeyInfo` DER, set validity, and call `build()`.
- Assemble a batch with `CertReqMessagesBuilder.add(msg).build()`.
- DER round-trip via `CertReqMessages.from_der`; iterate the batch and inspect
  each request's `cert_req_id`, subject, and public key fields.
- Print OID constants from `synta.crmf`.

## 30. `example_cmp.py` — CMP certificate management messages

[Source](example_cmp.md) · [`example_cmp.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_cmp.py)

Bindings: `CMPMessageBuilder`, `CMPMessage.from_der`; OID constants from `synta.cmp`.

- Build a `pkiConf` message with `CMPMessageBuilder`: set `sender_rfc822`,
  `recipient_directory_name`, `transaction_id`, call `body_pkiconf()`, and `build()`.
- Build an `ir` (Initialization Request) that wraps a `CertReqMessages` body.
- DER round-trip via `CMPMessage.from_der`; inspect `pvno`, `body_type`,
  `sender_der`, and nonce fields.
- Print OID constants from `synta.cmp`.

## 31. `example_mtc.py` — Merkle Tree Certificates

[Source](example_mtc.md) · [`example_mtc.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_mtc.py)

Bindings: `synta.mtc.ProofNode`, `synta.mtc.Subtree`, `synta.mtc.SubtreeProof`,
`synta.mtc.InclusionProof`, `synta.mtc.LogID`, `synta.mtc.CosignerID`,
`synta.mtc.Checkpoint`, `synta.mtc.SubtreeSignature`,
`synta.mtc.MerkleTreeCertEntry`, `synta.mtc.LandmarkID`.

- Parse `ProofNode` (left and right variants); verify `is_left` and `hash`.
- Parse `Subtree`; verify `start`, `end`, and `value`.
- Parse `SubtreeProof` with both subtree lists; verify element count.
- Parse `InclusionProof`; verify `log_entry_index`, `tree_size`, and path length.
- Parse `LogID`; verify `hash_algorithm_oid` and `public_key_der`.
- Parse `CosignerID`; verify `issuer_der` and `serial_number`.
- Parse `Checkpoint`; verify all five properties (`log_id`, `tree_size`, `tree_minimum_index`, `root_value`, `timestamp`).
- Parse `SubtreeSignature`; verify `cosigner`, `subtree`, `checkpoint`, `signature_algorithm_oid`, and `signature`.
- Parse `MerkleTreeCertEntry` in the `TbsCertEntry` CHOICE arm; verify
  `tbs_cert_entry` with `issuer_der` and `subject_der`.
- Verify `repr()` output for `LandmarkID`.

## 32. `example_name_constraints.py` — NameConstraints extension (RFC 5280 §4.2.1.10)

[Source](example_name_constraints.md) · [`example_name_constraints.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_name_constraints.py)

Bindings: `synta.ext.NameConstraintsBuilder` (alias `NC`),
`synta.oids.NAME_CONSTRAINTS`, `Certificate.get_extension_value_der`,
`CertificateBuilder.add_extension`, `PrivateKey.generate_ec`, `NameBuilder`.

- Build a `NameConstraints` value with `permit_dns` (with and without a leading dot),
  `exclude_dns`, `permit_ip` (8-byte IPv4 address+mask), `exclude_ip`,
  and `permit_rfc822` using the `NC` alias.
- Verify the DER structure: decode the outer SEQUENCE and confirm the
  `[0] IMPLICIT` (permittedSubtrees) and `[1] IMPLICIT` (excludedSubtrees)
  CONSTRUCTED context tags via `Decoder`.
- Show that `permit_*`-only and `exclude_*`-only builders produce DER with
  only the relevant IMPLICIT field present.
- Build a self-signed CA certificate with `NameConstraints` marked critical
  (as required by RFC 5280 §4.2.1.10); look it up with
  `get_extension_value_der(oids.NAME_CONSTRAINTS)`; walk `extensions_der`
  to confirm the critical flag is set; verify DER round-trip.
- Confirm that `NC` (short alias) and `NameConstraintsBuilder` (full class
  name) produce identical DER.

## 33. `example_acme_rfc8737.py` — ACME RFC 8737 TLS-ALPN challenge

[Source](example_acme_rfc8737.md) · [`example_acme_rfc8737.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_acme_rfc8737.py)

See [`example_acme_rfc8737.md`](example_acme_rfc8737.md) for details.

## 34. `example_composite_mldsa_certificate.py` — Composite ML-DSA certificates

[`example_composite_mldsa_certificate.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_composite_mldsa_certificate.py)

Bindings: `PrivateKey.generate_composite_ml_dsa`, `CertificateBuilder.sign`,
`PrivateKey.to_der`, `PrivateKey.from_der`, `synta.oids` composite ML-DSA constants.

- Generate composite ML-DSA keys for several representative variants using
  `PrivateKey.generate_composite_ml_dsa(sub_arc)`.
- Build and sign a self-signed X.509 certificate with each composite key using
  `CertificateBuilder`.
- Demonstrate PKCS#8 round-trip (`to_der` / `from_der`) for composite private keys.
- Access the composite OID constants from `synta.oids` (e.g.
  `oids.MLDSA65_ECDSA_P256_SHA512`, `oids.COMPOSITE_MLDSA_ARC`).

Requires the `openssl` + `pqc` Cargo features (OpenSSL 3.3+) or the `nss` feature.
NSS backend limitations: SHAKE256 variants (sub-arc 51) and Brainpool curves
(sub-arcs 47, 50) are unsupported.

## 35. `example_schema.py` — ASN.1 structure definitions with `synta.schema`

[Source](example_schema.md) · [`example_schema.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_schema.py)

Bindings: `synta.schema.asn1_sequence`, `synta.schema.asn1_choice`,
`synta.schema.asn1_field`.

- Define a CHOICE type with `@asn1_choice` over two time variants (`UtcTime`,
  `GeneralizedTime`); encode and decode each variant; verify active field.
- Define a SEQUENCE with `@asn1_sequence` nesting the CHOICE type; verify
  round-trip and that dataclass `__eq__` and `__repr__` are preserved.
- Show optional `[0] EXPLICIT` and `[2] IMPLICIT` tagged fields with
  `asn1_field()`; verify absent fields decode as `None`.
- Encode a `List[synta.IA5String]` field as SEQUENCE OF; verify element count
  and values after decoding.
- Show `ValueError` when encoding a CHOICE with all fields `None`.
- Show `ValueError` when encoding a SEQUENCE with a required field set to `None`.
- Show `TypeError` when `@asn1_sequence` is applied before `@dataclass`.

## 36. `example_jwtcc.py` — RFC 9118 EnhancedJWTClaimConstraints

[Source](example_jwtcc.md) · [`example_jwtcc.py` on Codeberg](https://codeberg.org/abbra/synta/src/branch/main/examples/example_jwtcc.py)

Bindings: `synta.schema.asn1_sequence`, `synta.schema.asn1_sequence_of`,
`synta.schema.asn1_field`.

- Implement the RFC 9118 `EnhancedJWTClaimConstraints` ASN.1 module in pure Python.
- Use `@asn1_sequence_of` to define `JWTClaimNames` (naked `SEQUENCE OF IA5String`)
  and `JWTClaimValuesList` (naked `SEQUENCE OF JWTClaimValues`).
- Use `@asn1_sequence` to define `JWTClaimValues` with a claim name and a
  `list[synta.Utf8String]` values field.
- Use `asn1_field(tag=N, explicit=True)` for the three optional tagged fields of
  `EnhancedJWTClaimConstraints`.
- Demonstrate three scenarios: `mustInclude` only, `permittedValues` only, and all
  three fields simultaneously; verify each DER round-trip.
- Print and assert the OID constant `ID_PE_EJWT_CLAIM_CONSTRAINTS = 1.3.6.1.5.5.7.1.33`.