Zero Access + HPKE
Introduction
Hybrid Public Key Encryption (HPKE) is a general-purpose specification which enables encrypting data against an asymmetric public key. It's often used to encrypt data between a sender and a receiver.
Trinsic supports HPKE to optionally provide an additional layer of security on top of Zero Access Encryption. When HPKE is configured and enabled, Session Results are HPKE-encrypted by Trinsic before being stored within a Session Data Vault. While stored in the vault, and during transmission to you, PII is encrypted such that only your private key can decrypt it.
Trinsic operates as the sender of data, encrypting data against your recipient public key.
HPKE increases the complexity of an integration with Trinsic, but offers the greatest level of data protection possible when paired with Zero Access Encryption.
Key Management
HPKE keys are currently managed and configured manually by Trinsic.
To configure an HPKE key on your account, reach out to Trinsic and provide us with your key in PEM or JWK form.
For testing and development, we offer a Self-Test API to test your implementation against encrypted bundles from Trinsic's API without configuring a public key ahead of time.
Core HPKE Implementation
Algorithms
HPKE is a general-purpose protocol which supports a large variety of cryptographic algorithms and curves. However, to simplify development and integration for languages or environments which do not yet have high-quality HPKE libraries available, Trinsic uses a minimal HPKE profile, with no variability in chosen algorithms.
Presently, all HPKE operations are performed using the following parameters:
| Parameter | Value | Notes |
|---|---|---|
Mode | Base (0x00) | Trinsic's API authentication and TLS certificate satisfy sender authentication requirements, so a Mode other than Base is not presently supported. |
KEM | DHKEM(P-256, HKDF-SHA-256) (0x0010 / 16) |
This parameter determines the asymmetric algorithm used to derive a shared secret. |
KDF | HKDF-SHA256 (0x0001 / 1) |
This parameter determines the key derivation function used for various operations within HPKE. |
AEAD | AES_128_GCM( 0x0001 / 1) |
This parameter determines the symmetric encryption algorithm to use when encrypting/decrypting data within HPKE. |
Sequence | 0 | This parameter increases by All Trinsic HPKE operations are single-shot, so this is always |
info Parameter
info ParameterThe info parameter is used to cryptographically bind a message with a context, ensuring that a recipient can only decrypt a message if it was encrypted with the same context. The sender (Trinsic) and receiver (your application) must each construct the info independently; decryption will fail if info differs in any way. This prevents a hypothetical attacker from swapping encrypted message contents.
The info parameter for Trinsic HPKE operations is a byte array containing a UTF-8-encoded string with the following structure:
trinsic-hpke:{version}:{domain}:{context}trinsic-hpke:1:session-results:6725f68a-5501-80c2-9c85-c5f36fbc602a| Parameter | Description | Example Value |
|---|---|---|
version | Version of the Trinsic HPKE Scheme. Always | 1 |
domain | The kind of message being encoded. | session-results |
context | Further context information, in a domain-specific structure. | 6725f68a-5501-80c2-9c85-c5f36fbc602a |
See below for a list of all possible values for domain and their corresponding context structures.
Encryption Domains
Each different kind of message that Trinsic encrypts via HPKE is encrypted using a different domain; further, each domain has additional context defined for it.
The following table lists all domain values, as well as their context templates.
| Domain | Context Template | Message Data Model | Notes |
|---|---|---|---|
session-results | {sessionId} | IdentityData | Used for Session Results |
attachment-contents | {sessionId}:{attachmentId} | GetAttachmentResponse | Used for Attachments |
customer-self-test | {infoSuffix} | N/A | Used for messages encrypted using the Self-Test APIs |
Example: When decrypting Session Results for a Session with ID 772836df-9312-70ad-2c35-c6fd6fac613f:
- Domain:
session-results - Context:
772836df-9312-70ad-2c35-c6fd6fac613f - Full Info String:
trinsic-hpke:1:session-results:772836df-9312-70ad-2c35-c6fd6fac613f
Example: When decrypting an Attachment with ID 5f2c3276-a04e-44c9-b503-75f9dff5e08d for a Session with ID b4675c1f-5602-415a-86df-45d3b376402e:
- Domain:
attachment-contents - Context:
b4675c1f-5602-415a-86df-45d3b376402e:5f2c3276-a04e-44c9-b503-75f9dff5e08d - Full Info String:
trinsic-hpke:1:attachment-contents:b4675c1f-5602-415a-86df-45d3b376402e:5f2c3276-a04e-44c9-b503-75f9dff5e08d
Trinsic HPKE Bundle
When HPKE is enabled on your account, Trinsic does not return raw identityData or attachment content from our APIs. Instead, we return HPKE-encrypted data, in the form of a TrinsicHPKEBundle:
{
// Always 1
"trinsicHpkeVersion": 1,
// HPKE parameters and metadata.
"metadata": {
// HPKE Mode. Always `0`.
"mode": 0,
// HPKE Key Encapsulation Mechanism. Always `16`.
"kem": 16,
// HPKE Key Derivation Function. Always `1`.
"kdf": 1,
// HPKE AEAD. Always `1`.
"aead": 1,
// Base64-encoded SHA256 hash of `info`. Useful for debugging only.
"infoHash": "K5iric4zDBxK2mND77jy5Iu9N1K0K+1YXrYMtXbQvJQ=",
// Base64-encoded SHA256 hash of the encoded recipient public key point.
"recipientPublicKeyHash": "mmTQVVYT13zL9eA4HoijLh+FwUzgRC7tV5CaHji+hcI=",
// Base64-encoded JWK thumbprint of the recipient public key
"recipientPublicKeyJwkThumbprint": "4yE7QV4mtViQzZQ0LinkAj2uYVTOf0TxC21w-HccbnI",
},
// The base64-coded public key point of the ephemeral public key.
// Use as the `enc` parameter for HPKE.
"ephemeralSenderPublicKey": "BMV9NqGWIe00D0Z8z88uN72JC1hR6DaBciSsVDmjGiOLCQLrjRptF1wGrMRpLlmc4m02R4CssDS586eRLItU2yA=",
// The base64-encoded ciphertext.
// Use as the `ct` parameter for HPKE.
"ciphertext": "6/KCzUhwWaAoAioz0z6AU/HbZX8="
}{
"trinsicHpkeVersion": 1,
"metadata": {
"mode": 0,
"kem": 16,
"kdf": 1,
"aead": 1,
"infoHash": "K5iric4zDBxK2mND77jy5Iu9N1K0K+1YXrYMtXbQvJQ=",
"recipientPublicKeyHash": "mmTQVVYT13zL9eA4HoijLh+FwUzgRC7tV5CaHji+hcI="
},
"ephemeralSenderPublicKey": "BMV9NqGWIe00D0Z8z88uN72JC1hR6DaBciSsVDmjGiOLCQLrjRptF1wGrMRpLlmc4m02R4CssDS586eRLItU2yA=",
"ciphertext": "6/KCzUhwWaAoAioz0z6AU/HbZX8="
}Self-Test API
To test your HPKE implementation against Trinsic's API without needing to configure any keys, use the Self-Test API.
POST https://api.trinsic.id/api/valpha/hpke-test
Authorization: Bearer {TrinsicApiToken}
{
"data": "{dataToEncryptBase64}",
"infoSuffix": "{32RandomCharacters}",
"publicKey": "{P256PublicKeyInJWKOrPEMFormat}"
}{
"trinsicHpkeVersion": 1,
"metadata": {
"mode": 0,
"kem": 16,
"kdf": 1,
"aead": 1,
"infoHash": "K5iric4zDBxK2mND77jy5Iu9N1K0K+1YXrYMtXbQvJQ=",
"recipientPublicKeyHash": "mmTQVVYT13zL9eA4HoijLh+FwUzgRC7tV5CaHji+hcI="
},
"ephemeralSenderPublicKey": "BMV9NqGWIe00D0Z8z88uN72JC1hR6DaBciSsVDmjGiOLCQLrjRptF1wGrMRpLlmc4m02R4CssDS586eRLItU2yA=",
"ciphertext": "6/KCzUhwWaAoAioz0z6AU/HbZX8="
}This API allows you to provide any data to encrypt, a custom infoSuffix, and any P-256 public key string (JWK or PEM).
The output is a TrinsicHPKEBundle, with an HPKE message containing data encrypted against your provided publicKey.
The info used for encryption is in the form:
trinsic-hpke:1:customer-self-test:{infoSuffix}
Decryption Process
Once you have a TrinsicHPKEBundle and your private key on hand, the decryption process should follow these general steps:
1. Validate static metadata
- Validate HPKE bundle version
trinsicHpkeVersion == 1
- Validate fixed HPKE Parameters
metadata.mode == 0metadata.kem == 16metadata.kdf == 1metadata.aead == 1
2. Construct info
infoYou must know the domain and context of the message you are decrypting.
See above for a list of domains and context templates.
- Determine
domainstring - Create
contextStringaccording todomaintemplate - Create
infoStringtrinsic-hpke:1:{domain}:{contextString}
- Encode
infoStringvia UTF-8 encoding to a byte array,infoBytes
3. Perform HPKE
Perform HPKE decryption.
- Use
infoBytesasinfo - Use
ephemeralSenderPublicKeyasenc - Use
ciphertextasct
4. Deserialize Results
The output of HPKE decryption is a byte array dataBytes, which contains a UTF-8 encoded JSON string.
- Decode
dataBytesto a string via UTF-8 to getdataString - JSON-deserialize
dataStringto one of the following models, available in our SDKs:IdentityDataGetAttachmentResponse
Updated about 9 hours ago
