Cryptography
The crypto module is a hybrid integrated-encryption scheme (ephemeral key → ECDH →
HKDF-SHA256 → AEAD), built directly on @noble/curves, @noble/ciphers, and @noble/hashes.
It is the basis for sealing every encrypted prism slot. The central type is DataPrismKey.
DataPrismKey
The cryptographic identity of a prism. The private key is never stored: it is derived from a wallet signature and reconstructed on demand.
Constructors (static)
| Method | Description |
|---|---|
DataPrismKey.fromSignature(signature, config) | derives the secret from a wallet signature, keccak256(signature), reduced to a valid scalar. Deterministic. |
DataPrismKey.fromSecret(secret, config) | from a raw 32-byte secret (reduced to a valid scalar) |
DataPrismKey.fromPublicKey(publicKey, config) | a public-only key: can encrypt, cannot open |
import { DataPrismKey } from "@dataprism/sdk";
const sig = await walletClient.signMessage({ message: `dataprism:key:${cloudId}` });
const key = DataPrismKey.fromSignature(sig, { curve: "secp256k1", algorithm: "aes-256-gcm" });Because the derivation is deterministic, signing the same message always produces the same key.
Derive the message from the cloudId (default), it is public and reproducible from the
prism's id, so nothing per-prism is stored. For extra security, mix in a password
(`dataprism:key:${cloudId}:${password}`): without it, anyone who steals the wallet's
private key could reproduce the signature and decrypt; with it, decryption also requires the
password, which is never stored.
Properties
| Property | Type | Note |
|---|---|---|
config | EncryptionConfig | curve + algorithm |
curve | Curve | |
canOpen | boolean | false for a public-only key |
publicKeyHex | Hex | |
secretHex | Hex | throws if public-only |
Methods
| Method | Returns | Note |
|---|---|---|
seal(data, aad?) | Uint8Array | encrypt for this prism |
open(blob, aad?) | Uint8Array | decrypt (requires the secret) |
sealJson(value, aad?) | Hex | JSON → sealed hex |
openJson<T>(blob, aad?) | T | sealed hex → JSON |
toKeySlot(includePrivate = false) | KeySlot | { public, private }; private empty unless explicit public mode |
const sealed = key.sealJson({ secret: "value" }); // Hex, safe to put on-chain
const data = key.openJson<{ secret: string }>(sealed);toKeySlot(true) is the explicit, opt-in "public mode": it writes the private key into the
slot so anyone can decrypt the prism's data. The default (false) keeps private empty.
Low-level functions
seal(config: EncryptionConfig, recipientPublicKey: Uint8Array, data: Uint8Array, aad?): Uint8Array
open(config: EncryptionConfig, recipientSecret: Uint8Array, blob: Uint8Array, aad?): Uint8ArrayThe blob layout is ephemeralKey ‖ nonce ‖ tag ‖ ciphertext. Because it is AEAD, any tampering
with a sealed payload is detected, open fails rather than returning corrupt data.
Configuration
type Curve = "secp256k1" | "x25519" | "ed25519";
type Algorithm = "aes-256-gcm" | "xchacha20";
interface EncryptionConfig { curve: Curve; algorithm: Algorithm }
const DEFAULT_ENCRYPTION = { curve: "secp256k1", algorithm: "aes-256-gcm" };
assertEncryptionConfig(config): void // validates, or throwsAll six curve × algorithm combinations are supported and round-trip tested. The chosen config
is stored (in clear) in the prism's dataprism.encryption
slot so any reader knows how to decrypt the rest.
Access control
A public-only key (fromPublicKey) can seal / write but cannot open, attempting to
decrypt a sealed slot throws. This is the access boundary used by the
CloudReader: give a collaborator the public key
and they can write data for the prism, but only the secret holder can read the sealed slots.

