# API Reference for Rust Crates
<style>
.content main { padding: 0 !important; max-width: none !important; }
</style>
<iframe
src="api/synta/index.html"
style="width:100%; height:calc(100vh - var(--menu-bar-height, 50px)); border:none; display:block;"
title="Synta Rust API Reference (rustdoc)">
</iframe>
> If the frame above is empty, build the documentation first:
> ```bash
> bash contrib/ci/local-ci.sh doc
> ```
---
## PKCS#11 URI Key Loading
The functions and types described below are part of `synta-certificate` and
allow loading private keys directly from PKCS#11 hardware or software tokens
without ever extracting key material into process memory.
### `BackendPrivateKey::from_pkcs11_uri`
```rust
pub fn from_pkcs11_uri(uri: &str) -> Result<Self, PrivateKeyError>
```
Loads a private key from a PKCS#11 token identified by the given RFC 7512
`pkcs11:` URI. The URI must begin with the `pkcs11:` scheme.
The key handle (or, for the NSS backend, the slot reference) is stored inside
the returned `BackendPrivateKey`. Key material is never extracted; all signing
operations are delegated to the token.
**When to use it:** Use `from_pkcs11_uri` instead of `from_pem` or
`from_pkcs8_der` whenever the private key resides in an HSM, smart card, or
software token and must not leave the token boundary.
**Backend-specific requirements:**
| OpenSSL (`openssl` feature) | None | `pkcs11-provider` configured via `OPENSSL_CONF` before the call |
| NSS (`nss` feature) | `token=` and `object=` | PKCS#11 module registered via `modutil` before the call |
See [deployment-guide.md](deployment-guide.md#hsm--pkcs11-key-storage) for
step-by-step setup instructions for each backend.
### `BackendPrivateKey::pkcs11_info`
```rust
pub fn pkcs11_info(&self) -> Option<&Pkcs11Uri>
```
Returns the parsed PKCS#11 URI for keys loaded via `from_pkcs11_uri`, or
`None` for software keys loaded from PEM/DER.
Useful for logging, diagnostics, or conditional logic that must behave
differently for HSM-backed keys.
### `Pkcs11Uri`
```rust
pub struct Pkcs11Uri {
pub raw: String, // verbatim URI string as supplied to from_pkcs11_uri
pub attrs: Pkcs11UriAttributes,
}
```
Parsed representation of an RFC 7512 `pkcs11:` URI. The `raw` field preserves
the original string exactly; `attrs` contains the pre-decoded path and query
attributes.
### `Pkcs11UriAttributes`
```rust
pub struct Pkcs11UriAttributes {
pub token: Option<String>, // token= path attribute (slot/token label)
pub object: Option<String>, // object= path attribute (key nickname/label)
pub id: Option<Vec<u8>>, // id= CKA_ID, percent-decoded raw bytes
pub pin_value: Option<String>, // ?pin-value= query attribute (token PIN)
}
```
Pre-decoded path and query attributes extracted from a `pkcs11:` URI.
### URI format example
```
pkcs11:token=MyHSM;object=cakey;type=private?pin-value=1234
```
- `token=MyHSM` — the token label (mandatory for NSS, optional for OpenSSL)
- `object=cakey` — the key label / nickname (mandatory for NSS, optional for OpenSSL)
- `type=private` — selects the private-key object class (recommended)
- `pin-value=1234` — PIN supplied inline; omit if the token is already authenticated
### Note on key material
`BackendPrivateKey::pkcs8_der` is always empty for HSM-backed keys. The token
handle is stored internally and used for every signing operation. Callers
should never attempt to serialise an HSM key via `pkcs8_der`.
---
## RSA Key Transport
`BackendPublicKey` and `BackendPrivateKey` in `synta-certificate` expose
RSA encryption and decryption operations. These are used in CMS
`EnvelopedData` construction (key transport RecipientInfo) and in any other
protocol that requires wrapping a symmetric key with an RSA public key.
Both backends (OpenSSL and NSS) are supported. When both features are enabled,
OpenSSL takes priority.
### `BackendPublicKey::rsa_oaep_encrypt`
```rust
pub fn rsa_oaep_encrypt(
&self,
plaintext: &[u8],
hash_alg: &str,
) -> Result<Vec<u8>, PrivateKeyError>
```
RSA-OAEP encryption using the recipient's public key.
`hash_alg` is the OAEP hash algorithm name: `"sha1"`, `"sha224"`,
`"sha256"`, `"sha384"`, or `"sha512"`.
Returns the ciphertext (same byte-length as the RSA modulus).
### `BackendPublicKey::rsa_pkcs1v15_encrypt`
```rust
pub fn rsa_pkcs1v15_encrypt(
&self,
plaintext: &[u8],
) -> Result<Vec<u8>, PrivateKeyError>
```
RSA PKCS#1 v1.5 encryption using the recipient's public key. For new
protocols prefer RSA-OAEP; PKCS#1 v1.5 is supported for compatibility with
legacy CMS content.
Returns the ciphertext (same byte-length as the RSA modulus).
### `BackendPrivateKey::rsa_oaep_decrypt`
```rust
pub fn rsa_oaep_decrypt(
&self,
ciphertext: &[u8],
hash_alg: &str,
) -> Result<Vec<u8>, PrivateKeyError>
```
RSA-OAEP decryption using the recipient's private key.
`hash_alg` must match the algorithm used during encryption.
### `BackendPrivateKey::rsa_pkcs1v15_decrypt`
```rust
pub fn rsa_pkcs1v15_decrypt(
&self,
ciphertext: &[u8],
) -> Result<Vec<u8>, PrivateKeyError>
```
RSA PKCS#1 v1.5 decryption using the recipient's private key.
**Backend notes:**
| OpenSSL (`openssl` feature) | Uses `EVP_PKEY_CTX_set_rsa_padding` / `EVP_PKEY_decrypt` |
| NSS (`nss` feature, no `openssl`) | Imports the public key via `SECKEY_DecodeDERSubjectPublicKeyInfo` and the private key via `PK11_ImportDERPrivateKeyInfoAndReturnKey` into the NSS internal softokn slot, then calls `PK11_PubEncrypt` / `PK11_PrivDecrypt` |
---
## AES-GCM Authenticated Encryption
Both the Rust `BlockCipherProvider` trait and the Python `synta.crypto` module expose
AES-GCM (AEAD) encryption and decryption. Both backends (OpenSSL and NSS) are supported.
### `BlockCipherProvider::aes_gcm_encrypt` (Rust)
```rust
fn aes_gcm_encrypt(
&self,
key: &[u8],
nonce: &[u8],
plaintext: &[u8],
aad: &[u8],
) -> Result<Vec<u8>, Self::Error>
```
Encrypts `plaintext` with AES-GCM. `key` must be 16, 24, or 32 bytes (AES-128,
AES-192, or AES-256). `nonce` must be exactly 12 bytes. `aad` is additional
authenticated data that is authenticated but not encrypted; pass `&[]` when not
needed.
Returns `ciphertext ‖ tag` where the authentication tag is 16 bytes.
### `BlockCipherProvider::aes_gcm_decrypt` (Rust)
```rust
fn aes_gcm_decrypt(
&self,
key: &[u8],
nonce: &[u8],
ciphertext_with_tag: &[u8],
aad: &[u8],
) -> Result<Vec<u8>, Self::Error>
```
Decrypts and verifies `ciphertext_with_tag` (the output of `aes_gcm_encrypt`).
The last 16 bytes of `ciphertext_with_tag` are treated as the authentication tag.
Returns `Err` if the tag does not verify or the inputs are otherwise invalid.
Obtain the provider via `default_block_cipher_provider()` for backend-agnostic code.
### `synta.crypto.aes_gcm_encrypt` (Python)
```text
synta.crypto.aes_gcm_encrypt(
key: bytes,
nonce: bytes,
plaintext: bytes,
aad: bytes | None = None,
) -> bytes
```
Python wrapper around `BlockCipherProvider::aes_gcm_encrypt`. `key` is 16, 24, or
32 bytes; `nonce` is 12 bytes. `aad` defaults to `None` (no AAD). Returns
`ciphertext ‖ tag` (16-byte tag). Output is byte-for-byte compatible with
`cryptography.hazmat.primitives.ciphers.aead.AESGCM(key).encrypt(nonce, plaintext, aad)`.
Raises `ValueError` on invalid key length, nonce length, or backend error.
### `synta.crypto.aes_gcm_decrypt` (Python)
```text
synta.crypto.aes_gcm_decrypt(
key: bytes,
nonce: bytes,
ciphertext_with_tag: bytes,
aad: bytes | None = None,
) -> bytes
```
Decrypts and verifies the output of `aes_gcm_encrypt`. `nonce` and `aad` must
match those used during encryption. Raises `ValueError` if the authentication tag
does not verify.
---
## Importing Private Keys from Raw Components
Two `BackendPrivateKey` constructors allow importing key material that is already
available as raw big-endian byte slices. Both require the `openssl` or `nss` feature
and are available from the Rust API only; there is no Python-level equivalent.
### `BackendPrivateKey::from_ec_private_scalar`
```rust
pub fn from_ec_private_scalar(
d: &[u8],
x: &[u8],
y: &[u8],
curve: &str,
) -> Result<Self, PrivateKeyError>
```
Builds an EC private key from the private scalar `d` and the affine public-point
coordinates `x` and `y` (all big-endian). `curve` must be `"P-256"`, `"P-384"`,
or `"P-521"`.
Returns `Err(PrivateKeyError)` if `curve` is unrecognised or if the backend rejects
the key material (e.g. the point is not on the curve).
### `RsaPrivateComponents`
```rust
pub struct RsaPrivateComponents<'a> {
pub n: &'a [u8], // RSA modulus
pub e: &'a [u8], // public exponent
pub d: &'a [u8], // private exponent
pub p: &'a [u8], // first prime factor
pub q: &'a [u8], // second prime factor
pub dp: &'a [u8], // d mod (p - 1)
pub dq: &'a [u8], // d mod (q - 1)
pub qi: &'a [u8], // q^{-1} mod p
}
```
Helper struct that groups the eight CRT fields required to import an RSA private key.
All fields are big-endian unsigned integers, the same encoding used by JWK and PKCS#1.
### `BackendPrivateKey::from_rsa_private_components`
```rust
pub fn from_rsa_private_components(
components: &RsaPrivateComponents<'_>,
) -> Result<Self, PrivateKeyError>
```
Builds an RSA private key from the fields supplied in `components`. Returns
`Err(PrivateKeyError)` if the backend rejects the key material (e.g. inconsistent
CRT values).