SpaceComputer

Use the KMS

Create keys, encrypt, decrypt, sign, generate data keys, and rotate keys through the Orbitport KMS.

This guide covers the Orbitport Key Management Service through the SDK: discovering capabilities, creating keys, encrypting and decrypting data, signing messages (including Ethereum EIP-191), generating data keys for envelope encryption, and rotating keys.

:::danger[Experimental — do not use in production] The Orbitport KMS is experimental. Interfaces, key formats, and on-the-wire shapes can change without notice, and operational guarantees (durability, availability, key recoverability) are not in place yet.

Do not use it to protect production data, sign production transactions, or hold keys you cannot afford to lose. Use it for prototypes, internal tooling, and exploration only -- and assume any keys you create today may be rotated, invalidated, or deleted before general availability. :::

What KMS provides

The Orbitport KMS gives you managed cryptographic keys with two schemes:

  • TRANSIT -- general-purpose keys for symmetric encryption (AES_256_GCM96) and signing (ECDSA_P256/P384, Ed25519, RSA_4096). Supports encrypt, decrypt, sign, generate data key, and rotate.
  • ETHEREUM -- secp256k1 keys that expose an Ethereum address and support EIP-191 personal-sign-style messages. Supports sign only.

The SDK talks JSON-RPC 2.0 to the gateway at POST /api/v1/rpc. Inputs are camelCase; outputs preserve the gateway's PascalCase wire shape (so KeyId, KeyMetadata, CiphertextBlob, etc. appear as-is on the response).

Prerequisites

KMS requires API credentials -- there is no public fallback for key operations. Follow the Authentication guide to get a Client ID and Secret if you don't have them yet.

import { OrbitportSDK } from "@spacecomputer-io/orbitport-sdk-ts";

const sdk = new OrbitportSDK({
  config: {
    clientId: process.env.ORBITPORT_CLIENT_ID,
    clientSecret: process.env.ORBITPORT_CLIENT_SECRET,
  },
});

Discover capabilities

Use getCapabilities() to inspect the schemes, key specs, and algorithms the gateway supports:

const caps = await sdk.kms.getCapabilities();
console.log(caps.data.Schemes.map((s) => s.Scheme).join(", "));
// e.g. "TRANSIT, ETHEREUM"

This is the authoritative source -- the reference tables at the bottom of this page reflect what the SDK supports today, but getCapabilities() always reports what your gateway actually offers.

Create a key

createKey provisions a new key. The most common shape:

const aes = await sdk.kms.createKey({
  alias: "demo-aes",
  keySpec: "AES_256_GCM96",
  keyUsage: "ENCRYPT_DECRYPT",
  scheme: "TRANSIT", // default
});
const aesKeyId = aes.data.KeyMetadata.KeyId;

For an Ethereum-compatible signing key:

const eth = await sdk.kms.createKey({
  alias: "demo-eth",
  keySpec: "ECC_SECG_P256K1",
  keyUsage: "SIGN_VERIFY",
  scheme: "ETHEREUM",
});
console.log(eth.data.KeyMetadata.Address); // the Ethereum address

alias must be unique within your tenant. description and tags are optional.

Encrypt and decrypt

Symmetric round-trip with a TRANSIT AES key:

const enc = await sdk.kms.encrypt({
  keyId: aesKeyId,
  plaintext: "hello kms",
});

const dec = await sdk.kms.decrypt({
  keyId: aesKeyId,
  ciphertextBlob: enc.data.CiphertextBlob,
});

console.log(dec.data.Plaintext); // "hello kms"

encrypt and decrypt accept an encoding: "utf8" | "bytes" option. The default is "utf8", which auto-decodes to a string. Use "bytes" for binary fidelity:

const bytes = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);

const enc = await sdk.kms.encrypt({
  keyId: aesKeyId,
  plaintext: bytes,
  encoding: "bytes",
});

const dec = await sdk.kms.decrypt({
  keyId: aesKeyId,
  ciphertextBlob: enc.data.CiphertextBlob,
  encoding: "bytes",
});
// dec.data.Plaintext is a Uint8Array

Sign a message

Sign over a precomputed digest with an ECDSA P-256 key:

const ec = await sdk.kms.createKey({
  alias: "demo-ecdsa",
  keySpec: "ECDSA_P256",
  keyUsage: "SIGN_VERIFY",
});

// 32 bytes -- a SHA-256 digest you computed locally.
const digest = new Uint8Array(32); // fill with your digest

const sig = await sdk.kms.sign({
  keyId: ec.data.KeyMetadata.KeyId,
  message: digest,
  signingAlgorithm: "ECDSA_SHA_256",
  messageType: "DIGEST",
});

console.log(sig.data.Signature); // base64 signature

Sign an Ethereum personal-sign-style message with EIP-191:

const ethSig = await sdk.kms.sign({
  keyId: eth.data.KeyMetadata.KeyId,
  message: "Hello, Ethereum",
  signingAlgorithm: "ETHEREUM_SECP256K1",
  messageType: "EIP191",
});

messageType controls how the gateway interprets message:

messageTypeMeaning
RAWSign the message bytes directly (the gateway hashes them).
DIGESTmessage is already a hash; sign it as-is.
EIP191Apply the Ethereum personal-sign prefix before hashing. ETHEREUM scheme only.

Generate a data key (envelope encryption)

generateDataKey returns a fresh symmetric key both as plaintext (so you can use it locally) and wrapped under your master key (so you can store the wrapped form alongside the data and only need the master key to decrypt later):

import { fromBase64ToUint8Array } from "@spacecomputer-io/orbitport-sdk-ts";

const dk = await sdk.kms.generateDataKey({
  keyId: aesKeyId,
  dataKeySpec: "AES_256",
});

const rawKeyBytes = fromBase64ToUint8Array(dk.data.Plaintext);
const wrappedBlob = dk.data.CiphertextBlob; // store this with your data

Plaintext is always raw base64 binary key material -- there is no encoding flag for this method. The SDK exports fromBase64ToUint8Array, fromBase64ToUtf8, and toBase64 helpers for manual decoding.

You can request numberOfBytes instead of dataKeySpec for a custom-length key.

Rotate a key

Bump the key's primary version. New encryptions and signatures use the new version; previously produced ciphertexts and signatures remain decryptable / verifiable under their original version.

const before = aes.data.KeyMetadata.PrimaryVersion;
const rotated = await sdk.kms.rotateKey({ keyId: aesKeyId });
console.log(`PrimaryVersion: ${before} -> ${rotated.data.KeyMetadata.PrimaryVersion}`);

Rotation is supported on TRANSIT keys only. ETHEREUM keys do not support rotation.

Errors and retries

KMS methods throw OrbitportSDKError with a typed code. Common KMS-specific codes:

CodeWhen
KMS_KEY_NOT_FOUNDThe keyId does not exist (or has been deleted).
KMS_INVALID_KEY_STATEThe key cannot be used for the requested operation in its current state.
KMS_ERRORA generic gateway-side KMS failure.
JSON_RPC_ERRORThe gateway returned a JSON-RPC error envelope.
AUTH_FAILEDCredentials missing or token rejected.

The raw JSON-RPC code is exposed at error.details.jsonRpcCode for advanced branching.

KMS methods do not retry by default -- createKey and sign are not idempotent. Pass RequestOptions.retries per call when you want retry behavior:

await sdk.kms.encrypt(
  { keyId: aesKeyId, plaintext: "hi" },
  { retries: 3 },
);

Reference

Schemes and supported operations

SchemeEncrypt / DecryptSignGenerate Data KeyRotate
TRANSITyesyesyesyes
ETHEREUMnoyesnono

Key specs

SchemeKey specs
TRANSITAES_256_GCM96, ECDSA_P256, ECDSA_P384, ED25519, RSA_4096
ETHEREUMECC_SECG_P256K1

Signing algorithms

AlgorithmCompatible key specs
ECDSA_SHA_256ECDSA_P256
ECDSA_SHA_384ECDSA_P384
ED25519ED25519
RSA_PKCS1V15_SHA_256RSA_4096
RSA_PSS_SHA_256RSA_4096
ETHEREUM_SECP256K1ECC_SECG_P256K1

Next steps

On this page