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 addressalias 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 Uint8ArraySign 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 signatureSign 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:
messageType | Meaning |
|---|---|
RAW | Sign the message bytes directly (the gateway hashes them). |
DIGEST | message is already a hash; sign it as-is. |
EIP191 | Apply 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 dataPlaintext 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:
| Code | When |
|---|---|
KMS_KEY_NOT_FOUND | The keyId does not exist (or has been deleted). |
KMS_INVALID_KEY_STATE | The key cannot be used for the requested operation in its current state. |
KMS_ERROR | A generic gateway-side KMS failure. |
JSON_RPC_ERROR | The gateway returned a JSON-RPC error envelope. |
AUTH_FAILED | Credentials 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
| Scheme | Encrypt / Decrypt | Sign | Generate Data Key | Rotate |
|---|---|---|---|---|
TRANSIT | yes | yes | yes | yes |
ETHEREUM | no | yes | no | no |
Key specs
| Scheme | Key specs |
|---|---|
TRANSIT | AES_256_GCM96, ECDSA_P256, ECDSA_P384, ED25519, RSA_4096 |
ETHEREUM | ECC_SECG_P256K1 |
Signing algorithms
| Algorithm | Compatible key specs |
|---|---|
ECDSA_SHA_256 | ECDSA_P256 |
ECDSA_SHA_384 | ECDSA_P384 |
ED25519 | ED25519 |
RSA_PKCS1V15_SHA_256 | RSA_4096 |
RSA_PSS_SHA_256 | RSA_4096 |
ETHEREUM_SECP256K1 | ECC_SECG_P256K1 |
Next steps
- Authentication -- get credentials for the API.
- Fetch cTRNG values -- read cosmic randomness alongside your KMS operations.
- Orbitport Architecture -- understand how KMS fits into the wider system.