LockerPeopleSlot locker.people-slot@1
Generated at from
openvibe-contracts v0.419.0 and
openvibe-sdk v0.161.0.
- Version
- 1.0.0
- Owner
- network
- Visibility
- public
- Status
- active
- Compatibility
- backward
- Schema
https://openvibe.network/contracts/locker/people-slot.v1.json
locker.people-slot@1: the content key wrapped for one person. The wrapping key is ECDH P-256 (an ephemeral key pair per envelope) put through HKDF-SHA-256, and the content key is sealed with AES-256-GCM. The tag covers the subject, the recipient's key, the ephemeral public key and the salt, so a slot cannot be moved to another person or to another envelope.
Fields
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
subject | identity.subject-ref | yes | ||
algorithm | const | yes |
| |
recipient_key | string | yes | The RFC 7638 thumbprint of the recipient's ECDH public key: SHA-256 over the canonical JSON of the key's four members, base64url. The slot is bound to this key as well as to the subject, and the reader checks it before it derives anything. |
|
ephemeral_public_key | locker.public-key | yes | ||
salt | string | yes | Sixteen random bytes, base64: the HKDF salt for this slot. |
|
nonce | string | yes | Twelve random bytes, base64: the AES-GCM nonce of the wrapped content key. |
|
wrapped_key | string | yes | The 32-byte content key and its 16-byte tag, base64. Never the key itself. |
|
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: example
{
"subject": {
"type": "user",
"id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPR"
},
"algorithm": "ECDH-P256/HKDF-SHA256/AES-256-GCM",
"recipient_key": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8",
"ephemeral_public_key": {
"kty": "EC",
"crv": "P-256",
"x": "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHg",
"y": "eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXk"
},
"salt": "c3Nzc3Nzc3Nzc3Nzc3Nzcw==",
"nonce": "bm5ubm5ubm5ubm5u",
"wrapped_key": "d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3"
}Rejected: no-recipient-key
{
"subject": {
"type": "user",
"id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPR"
},
"algorithm": "ECDH-P256/HKDF-SHA256/AES-256-GCM",
"ephemeral_public_key": {
"kty": "EC",
"crv": "P-256",
"x": "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHg",
"y": "eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXk"
},
"salt": "c3Nzc3Nzc3Nzc3Nzc3Nzcw==",
"nonce": "bm5ubm5ubm5ubm5u",
"wrapped_key": "d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3"
}Rejected: no-subject
{
"algorithm": "ECDH-P256/HKDF-SHA256/AES-256-GCM",
"recipient_key": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8",
"ephemeral_public_key": {
"kty": "EC",
"crv": "P-256",
"x": "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHg",
"y": "eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXk"
},
"salt": "c3Nzc3Nzc3Nzc3Nzc3Nzcw==",
"nonce": "bm5ubm5ubm5ubm5u",
"wrapped_key": "d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3"
}Rejected: wrong-algorithm
{
"subject": {
"type": "user",
"id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPR"
},
"algorithm": "RSA-OAEP/AES-256-GCM",
"ephemeral_public_key": {
"kty": "EC",
"crv": "P-256",
"x": "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHg",
"y": "eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXl5eXk"
},
"salt": "c3Nzc3Nzc3Nzc3Nzc3Nzcw==",
"nonce": "bm5ubm5ubm5ubm5u",
"wrapped_key": "d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3d3"
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('locker.people-slot@1', value); // { valid, errors: [{ path, message }] }