Licensing
Verify a license record
Check the Ed25519 signature on a downloaded license record offline, against the public key published here.
Every license record the console serves is signed with Ed25519. The signature says the record came from OpenE2EE and that nobody edited it after issue. You can check it offline, with Node.js alone, and without contacting the console.
What the download contains
The downloaded file is open-e2ee-<licenseId>.license.json, a signed envelope:
{
"recordType": "open-e2ee-signed-license-record",
"recordVersion": 1,
"record": { "recordType": "open-e2ee-signal-protocol-sdk-commercial-license-record", "...": "..." },
"algorithm": "Ed25519",
"publicKeyId": "3f3488f7c4cd43f4",
"signature": "<base64>"
}The signature covers the record member, serialized as JSON with two-space indentation and one trailing newline. It does not cover the envelope itself, so a verifier rebuilds those exact bytes from record before checking the signature.
The signing key
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAlJbMbvvNR7HmQ3PvSp7v8PwL3dJSqMl0nha/Pu5r9QE=
-----END PUBLIC KEY-----Its key id is 3f3488f7c4cd43f4: the first 16 hexadecimal characters of the SHA-256 of the DER-encoded SPKI public key. The envelope names the key id it was signed with. Reject any record whose publicKeyId is not this one.
The same key is committed in the console repository, so this page and the source agree by construction. Take the key from a page you loaded over HTTPS, and keep your copy.
Verify with Node.js
Save this as verify-license.mjs and run node verify-license.mjs open-e2ee-<licenseId>.license.json. It needs Node.js 22 or later and no dependencies.
import { createPublicKey, verify } from 'node:crypto';
import { readFile } from 'node:fs/promises';
const publicKeyPem = `-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAlJbMbvvNR7HmQ3PvSp7v8PwL3dJSqMl0nha/Pu5r9QE=
-----END PUBLIC KEY-----
`;
const expectedKeyId = '3f3488f7c4cd43f4';
const envelope = JSON.parse(await readFile(process.argv[2], 'utf8'));
if (envelope.recordType !== 'open-e2ee-signed-license-record' || envelope.recordVersion !== 1) {
throw new Error('Not a signed OpenE2EE license record.');
}
if (envelope.algorithm !== 'Ed25519' || envelope.publicKeyId !== expectedKeyId) {
throw new Error(`Unexpected signing key: ${envelope.algorithm} ${envelope.publicKeyId}`);
}
// The signed bytes are the record on its own, pretty-printed with two spaces
// and terminated by one newline. JSON.parse keeps the member order, so this
// reproduces the issued bytes exactly.
const signedBytes = Buffer.from(`${JSON.stringify(envelope.record, null, 2)}\n`, 'utf8');
const signature = Buffer.from(envelope.signature, 'base64');
if (!verify(null, signedBytes, createPublicKey(publicKeyPem), signature)) {
throw new Error('Signature does not match. Do not trust this record.');
}
console.log(`Valid license record for ${envelope.record.licensee}`);
console.log(` license: ${envelope.record.licenseId} (${envelope.record.planId})`);
console.log(` products: ${envelope.record.coveredProducts.join(', ')}`);
console.log(` components: ${envelope.record.licensedComponents.join(', ')}`);
console.log(` status: ${envelope.record.status}, term ends ${envelope.record.currentTermEndsAt}`);A record that fails any check is not a record OpenE2EE issued.
Check the file you received
The console shows the SHA-256 of the exact bytes the download serves, and the download repeats it in the X-License-Record-SHA256 header. Compare it with shasum -a 256 open-e2ee-<licenseId>.license.json.
That digest proves the transfer was complete. Only the signature proves the origin, so check the signature as well.
What the signature does not say
The agreement is the authority
A valid signature says the console issued this record, for this licensee, with this scope, at download time. The executed commercial agreement controls the grant, and the entitlement can change afterwards. Download a fresh record when you need the current state.
The SDK does not read license records and does not contact the console during normal cryptographic operation. Verification is for your own procurement, audit, and vendor records.