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

FieldTypeRequiredDescriptionConstraints
subjectidentity.subject-refyes
algorithmconstyes
  • = "ECDH-P256/HKDF-SHA256/AES-256-GCM"
recipient_keystringyesThe 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.
  • pattern ^[A-Za-z0-9_-]{43}$
ephemeral_public_keylocker.public-keyyes
saltstringyesSixteen random bytes, base64: the HKDF salt for this slot.
  • pattern ^[A-Za-z0-9+/]{22}==$
noncestringyesTwelve random bytes, base64: the AES-GCM nonce of the wrapped content key.
  • pattern ^[A-Za-z0-9+/]{16}$
wrapped_keystringyesThe 32-byte content key and its 16-byte tag, base64. Never the key itself.
  • pattern ^[A-Za-z0-9+/]{64}$

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 }] }