Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Keys & encryption

The crypto module is a hybrid integrated-encryption scheme (ephemeral key, then ECDH, then HKDF-SHA256, then 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. Your application supplies it separately from the account that signs writes to the public registry. The dashboard derives its key from an account signature; SDK integrations can also supply an independently generated secret. Neither path sends the secret to DataPrism.

Constructors (static)

MethodDescription
DataPrismKey.fromSecret(secret, config)from a raw 32-byte secret (reduced to a valid scalar). The standard integration path.
DataPrismKey.fromSignature(signature, config)derives the secret from an account signature, hashed and reduced to a valid scalar. Deterministic.
DataPrismKey.fromPublicKey(publicKey, config)a public-only key: can encrypt, cannot open

Connecting to a dashboard-created prism

Open your project's SDK tab in the dashboard and copy the Secret key (and the Project ID next to it). Use it to construct the encryption key:

import { DataPrismKey } from "@dataprism/sdk";
 
const key = DataPrismKey.fromSecret(secretKey, {
  curve: "secp256k1",       // shown in the SDK tab
  algorithm: "aes-256-gcm", // shown in the SDK tab
});

Whoever holds the Secret key can decrypt the prism's sealed slots, including sealed indexes. Scoped file contents additionally require their derivation scope keys. Keep the Secret key in your secret manager, never in source control or in browser-exposed configuration. Copying a dashboard-derived secret into a secret manager does not make it independent of the signing account or remove the original derivation path.

Supplying an independent prism key

For a new SDK-created prism, your application can supply a separately generated 32-byte secret from customer-controlled secret storage. Pass that key to CloudStandard, and pass the transaction-signing account to the client:

import { CloudStandard, DataPrismClient, DataPrismKey } from "@dataprism/sdk";
 
const key = DataPrismKey.fromSecret(independentSecret, {
  curve: "secp256k1",
  algorithm: "aes-256-gcm",
});
const standard = new CloudStandard(key);
const client = new DataPrismClient(network, { accountClient });
const prism = client.prism(standard);
const { cloudId } = await prism.create({ fundAmount, salt, metadata });

Here, independentSecret is not derived from accountClient. Possession of the signing account alone does not reproduce that secret. Your application must retain the prism key to read its sealed slots. For an existing prism, load its existing key; generating a replacement does not decrypt or re-encrypt earlier payloads.

An authorized writer can use a different execution account while sealing data for the same prism public key. This does not change prism ownership or rotate the encryption key. Keeping the signing account and prism secret in the same process also does not isolate them from a compromise of that process.

The derived path: from an account signature

fromSignature is how the dashboard itself produces the key, and your app can do the same when the user's account is present, for example to avoid storing any secret at all:

const sig = await accountClient.signMessage({ message: `dataprism:key:${cloudId}` });
const key = DataPrismKey.fromSignature(sig, { curve: "secp256k1", algorithm: "aes-256-gcm" });

fromSignature produces the same key from the same signature bytes. Reproducing the key therefore requires a signing implementation that returns the same signature for the same message; not every account provider guarantees this. 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 account's private key could reproduce the signature and decrypt; with it, decryption also requires the password, which is never stored.

Properties

PropertyTypeNote
configEncryptionConfigcurve plus algorithm
curveCurve
canOpenbooleanfalse for a public-only key
publicKeyHexHex
secretHexHexthrows if public-only

Methods

MethodReturnsNote
seal(data, aad?)Uint8Arrayencrypt for this prism
open(blob, aad?)Uint8Arraydecrypt (requires the secret)
sealJson(value, aad?)HexJSON to sealed hex
openJson<T>(blob, aad?)Tsealed hex to JSON
toKeySlot()KeySlot{ public, private: "" }; never serializes the secret
const sealed = key.sealJson({ secret: "value" });   // Hex, safe to store on the network
const data   = key.openJson<{ secret: string }>(sealed);

Key-slot writes are public-key-only. The private member remains in KeySlot so older slots can still be read, but the SDK no longer provides a publication flag. Calls using the removed positional boolean throw instead of silently changing behaviour.

Low-level functions

seal(config: EncryptionConfig, recipientPublicKey: Uint8Array, data: Uint8Array, aad?): Uint8Array
open(config: EncryptionConfig, recipientSecret: Uint8Array, blob: Uint8Array, aad?): Uint8Array

The 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 throws

All six curve and 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 but cannot open: attempting to decrypt a sealed slot throws. A writer can therefore encrypt new payloads without holding the prism secret, although it still sees the plaintext it submits. Opening sealed slots through CloudReader requires the secret.

The public key does not grant permission to write to the public registry. The execution account must be the owner or an authorized writer. Conversely, a writer grant does not supply the prism secret or grant decryption access.

Copyright © 2026 DataPrism.