openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
66 lines (65 loc) • 2.79 kB
JavaScript
import crypto from "node:crypto";
//#region src/infra/ed25519-signature.ts
const ED25519_RAW_KEY_LENGTH = 32;
const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
Buffer.from("302e020100300506032b657004220420", "hex");
const MAX_BASE64URL_DECODE_INPUT_LENGTH = 4096;
/** Decode the existing permissive base64url wire shape. */
function base64UrlDecode(input) {
if (input.length > MAX_BASE64URL_DECODE_INPUT_LENGTH) throw new Error("base64url input exceeds the maximum allowed length");
const normalized = input.replaceAll("-", "+").replaceAll("_", "/");
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
return Buffer.from(padded, "base64");
}
function assertEd25519KeyType(key, label) {
if (key.asymmetricKeyType !== "ed25519") throw new Error(`${label} must be an Ed25519 key`);
}
function deriveRawKeyFromDer(der, label, prefix) {
const expectedLength = prefix.length + ED25519_RAW_KEY_LENGTH;
if (der.length !== expectedLength || !der.subarray(0, prefix.length).equals(prefix)) throw new Error(`${label} has a noncanonical Ed25519 encoding`);
return der.subarray(prefix.length);
}
/** Parse any Node-compatible Ed25519 PEM and return its canonical raw public key. */
function deriveEd25519PublicKeyRaw(publicKeyPem) {
const key = crypto.createPublicKey(publicKeyPem);
assertEd25519KeyType(key, "public key");
return deriveRawKeyFromDer(key.export({
type: "spki",
format: "der"
}), "public key", ED25519_SPKI_PREFIX);
}
function publicKeyRawBase64UrlFromEd25519Pem(publicKeyPem) {
return deriveEd25519PublicKeyRaw(publicKeyPem).toString("base64url");
}
function normalizeEd25519PublicKeyBase64Url(publicKey) {
try {
const raw = publicKey.includes("BEGIN") ? deriveEd25519PublicKeyRaw(publicKey) : base64UrlDecode(publicKey);
if (raw.length === 0) return null;
return raw.toString("base64url");
} catch {
return null;
}
}
function signEd25519Payload(privateKeyPem, payload) {
const key = crypto.createPrivateKey(privateKeyPem);
return crypto.sign(null, Buffer.from(payload, "utf8"), key).toString("base64url");
}
function createEd25519PublicKey(publicKey) {
if (publicKey.includes("BEGIN")) return crypto.createPublicKey(publicKey);
return crypto.createPublicKey({
key: Buffer.concat([ED25519_SPKI_PREFIX, base64UrlDecode(publicKey)]),
type: "spki",
format: "der"
});
}
function verifyEd25519SignatureBytes(params) {
try {
const key = createEd25519PublicKey(params.publicKey);
const signature = base64UrlDecode(params.signatureBase64Url);
return crypto.verify(null, params.payload, key, signature);
} catch {
return false;
}
}
//#endregion
export { verifyEd25519SignatureBytes as i, publicKeyRawBase64UrlFromEd25519Pem as n, signEd25519Payload as r, normalizeEd25519PublicKeyBase64Url as t };