Skip to content

Commit

Permalink
feat(issuer-sdk, enclave): use ephemeral encryption private keys (#385)
Browse files Browse the repository at this point in the history
Co-authored-by: Paulo Koch <[email protected]>
  • Loading branch information
ditoglez and pkoch authored Dec 13, 2024
1 parent bbff067 commit c9eefb5
Show file tree
Hide file tree
Showing 11 changed files with 38 additions and 32 deletions.
5 changes: 3 additions & 2 deletions apps/idos-enclave/src/lib/enclave.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ export class Enclave {

encrypt(message, receiverPublicKey = this.keyPair.publicKey) {
const nonce = nacl.randomBytes(nacl.box.nonceLength);
const encrypted = nacl.box(message, nonce, receiverPublicKey, this.keyPair.secretKey);
const ephemeralKeyPair = nacl.box.keyPair();
const encrypted = nacl.box(message, nonce, receiverPublicKey, ephemeralKeyPair.secretKey);

if (encrypted === null)
throw Error(
Expand All @@ -191,7 +192,7 @@ export class Enclave {
fullMessage.set(nonce, 0);
fullMessage.set(encrypted, nonce.length);

return fullMessage;
return { content: fullMessage, encryptorPublicKey: ephemeralKeyPair.publicKey };
}

async decrypt(fullMessage, senderPublicKey) {
Expand Down
1 change: 0 additions & 1 deletion examples/issuer-sdk-demo/src/issuer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export async function getIssuerConfig(): Promise<IssuerConfig> {

cachedIssuer = await createIssuerConfig({
nodeUrl: NODE_URL,
encryptionKeyPair: nacl.box.keyPair.fromSecretKey(decode(ENCRYPTION_SECRET_KEY)),
signingKeyPair: nacl.sign.keyPair.fromSecretKey(decode(SIGNING_SECRET_KEY)),
});

Expand Down
7 changes: 5 additions & 2 deletions packages/idos-sdk-js/src/lib/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,10 @@ export class Data {
): Promise<InsertableIDOSCredential> {
const issuerAuthenticationKeyPair = nacl.sign.keyPair();

const content = await this.enclave.encrypt(plaintextContent, receiverEncryptionPublicKey);
const { content, encryptorPublicKey } = await this.enclave.encrypt(
plaintextContent,
receiverEncryptionPublicKey,
);
const publicNotesSignature = nacl.sign.detached(
Utf8Codec.encode(publicNotes),
issuerAuthenticationKeyPair.secretKey,
Expand All @@ -387,7 +390,7 @@ export class Data {
),

issuer_auth_public_key: HexCodec.encode(issuerAuthenticationKeyPair.publicKey, true),
encryption_public_key: isPresent(this.enclave.auth.currentUser.currentUserPublicKey),
encryption_public_key: isPresent(encryptorPublicKey),
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,13 @@ export class IframeEnclave implements EnclaveProvider {
});
}

async encrypt(message: Uint8Array, receiverPublicKey: Uint8Array): Promise<Uint8Array> {
async encrypt(
message: Uint8Array,
receiverPublicKey: Uint8Array,
): Promise<{ content: Uint8Array; encryptorPublicKey: Uint8Array }> {
return this.#requestToEnclave({
encrypt: { message, receiverPublicKey },
}) as Promise<Uint8Array>;
}) as Promise<{ content: Uint8Array; encryptorPublicKey: Uint8Array }>;
}

async decrypt(message: Uint8Array, senderPublicKey: Uint8Array): Promise<Uint8Array> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,13 @@ export class MetaMaskSnapEnclave implements EnclaveProvider {
return this.invokeSnap("confirm", { message });
}

async encrypt(message: Uint8Array, receiverPublicKey: Uint8Array): Promise<Uint8Array> {
// biome-ignore lint/suspicious/noExplicitAny: Types will be added later
const encrypted: any = await this.invokeSnap("encrypt", { message, receiverPublicKey });
async encrypt(
message: Uint8Array,
receiverPublicKey: Uint8Array,
): Promise<{ content: Uint8Array; encryptorPublicKey: Uint8Array }> {
await this.invokeSnap("encrypt", { message, receiverPublicKey });

return Uint8Array.from(Object.values(encrypted));
throw new Error("The Metamask Enclave needs to be updated");
}

async decrypt(message: Uint8Array, senderPublicKey: Uint8Array): Promise<Uint8Array> {
Expand Down
5 changes: 4 additions & 1 deletion packages/idos-sdk-js/src/lib/enclave-providers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ export interface EnclaveProvider {
reset(): Promise<void>;
confirm(message: string): Promise<boolean>;
updateStore(key: string, value: unknown): Promise<void>;
encrypt(message: Uint8Array, receiverPublicKey?: Uint8Array): Promise<Uint8Array>;
encrypt(
message: Uint8Array,
receiverPublicKey?: Uint8Array,
): Promise<{ content: Uint8Array; encryptorPublicKey: Uint8Array }>;
decrypt(message: Uint8Array, senderPublicKey?: Uint8Array): Promise<Uint8Array>;
discoverUserEncryptionKey(humanId: string): Promise<DiscoverEncryptionKeyResponse>;
filterCredentialsByCountries(
Expand Down
18 changes: 12 additions & 6 deletions packages/idos-sdk-js/src/lib/enclave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,21 @@ export class Enclave {
return this.encryptionPublicKey;
}

async encrypt(message: string, receiverPublicKey?: string): Promise<string> {
async encrypt(
message: string,
receiverPublicKey?: string,
): Promise<{ content: string; encryptorPublicKey: string }> {
if (!this.encryptionPublicKey) await this.ready();

return Base64Codec.encode(
await this.provider.encrypt(
Utf8Codec.encode(message),
receiverPublicKey === undefined ? undefined : Base64Codec.decode(receiverPublicKey),
),
const { content, encryptorPublicKey } = await this.provider.encrypt(
Utf8Codec.encode(message),
receiverPublicKey === undefined ? undefined : Base64Codec.decode(receiverPublicKey),
);

return {
content: Base64Codec.encode(content),
encryptorPublicKey: Base64Codec.encode(encryptorPublicKey),
};
}

async decrypt(message: string, senderPublicKey?: string): Promise<string> {
Expand Down
2 changes: 0 additions & 2 deletions packages/issuer-sdk-js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,11 @@ Create an issuer config with your secret key. This config will be used to intera
// issuer-config.js
import { createIssuerConfig } from "@idos-network/issuer-sdk-js";

const encryptionKeyPair = nacl.box.keyPair.fromSecretKey(ISSUER_ENCRYPTION_SECRET_KEY);
const signingKeyPair = nacl.sign.keyPair.fromSecretKey(ISSUER_SIGNING_SECRET_KEY);

const issuerConfig = await createIssuerConfig({
// To use a non-prod environment, pass in "nodes.playground.idos.network".
nodeUrl: "https://nodes.idos.network/",
encryptionKeyPair,
signingKeyPair,
});
```
Expand Down
3 changes: 0 additions & 3 deletions packages/issuer-sdk-js/src/create-issuer-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,10 @@ describe("createIssuerConfig", () => {

it("should correctly initialize and return config", async () => {
const signingKeyPair = nacl.sign.keyPair();
const encryptionKeyPair = nacl.box.keyPair();

const params = {
nodeUrl: "http://mock-node-url",
signingKeyPair,
encryptionKeyPair,
};

const result = await createIssuerConfig(params);
Expand All @@ -69,7 +67,6 @@ describe("createIssuerConfig", () => {
dbid: "mock-dbid",
kwilClient: expect.any(Object),
kwilSigner: expect.any(KwilSigner),
encryptionKeyPair: expect.any(Object),
signingKeyPair: expect.any(Object),
});
});
Expand Down
3 changes: 0 additions & 3 deletions packages/issuer-sdk-js/src/create-issuer-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,13 @@ export interface IssuerConfig {
kwilClient: NodeKwil;
kwilSigner: KwilSigner;
signingKeyPair: nacl.SignKeyPair;
encryptionKeyPair: nacl.SignKeyPair;
}

type CreateIssuerConfigParams = {
chainId?: string;
dbId?: string;
nodeUrl: string;
signingKeyPair: nacl.SignKeyPair;
encryptionKeyPair: nacl.BoxKeyPair;
};

export async function createIssuerConfig(params: CreateIssuerConfigParams): Promise<IssuerConfig> {
Expand All @@ -83,6 +81,5 @@ export async function createIssuerConfig(params: CreateIssuerConfigParams): Prom
}),
kwilSigner: createKwilSigner(params.signingKeyPair),
signingKeyPair: params.signingKeyPair,
encryptionKeyPair: params.encryptionKeyPair,
};
}
9 changes: 3 additions & 6 deletions packages/issuer-sdk-js/src/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,9 @@ const buildInsertableIDOSCredential = (
receiverEncryptionPublicKey: Uint8Array;
},
): InsertableIDOSCredential => {
const ephemeralKeyPair = nacl.box.keyPair();
const content = Base64Codec.decode(
encryptContent(
plaintextContent,
receiverEncryptionPublicKey,
issuerConfig.encryptionKeyPair.secretKey,
),
encryptContent(plaintextContent, receiverEncryptionPublicKey, ephemeralKeyPair.secretKey),
);

const { public_notes, public_notes_signature } = buildUpdateablePublicNotes(issuerConfig, {
Expand All @@ -71,7 +68,7 @@ const buildInsertableIDOSCredential = (
),

issuer_auth_public_key: HexCodec.encode(issuerConfig.signingKeyPair.publicKey, true),
encryption_public_key: Base64Codec.encode(issuerConfig.encryptionKeyPair.publicKey),
encryption_public_key: Base64Codec.encode(ephemeralKeyPair.publicKey),
};
};

Expand Down

0 comments on commit c9eefb5

Please sign in to comment.