From 763342cd9cd6a48f2fd04cb48866b95806cc1e89 Mon Sep 17 00:00:00 2001 From: Mohammed-Mamoun98 Date: Wed, 13 Nov 2024 00:00:55 +0200 Subject: [PATCH 1/5] remove the need for passing issuer's encryption public key at credential creation --- .../issuer-sdk-js/src/create-issuer-config.ts | 6 ++- packages/issuer-sdk-js/src/credentials.ts | 43 ++++++++++++------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/packages/issuer-sdk-js/src/create-issuer-config.ts b/packages/issuer-sdk-js/src/create-issuer-config.ts index cb4780a63..127fd2626 100644 --- a/packages/issuer-sdk-js/src/create-issuer-config.ts +++ b/packages/issuer-sdk-js/src/create-issuer-config.ts @@ -1,7 +1,9 @@ import { KwilSigner, NodeKwil } from "@kwilteam/kwil-js"; +import * as Base64Codec from "@stablelib/base64"; import { Wallet } from "ethers"; import { KeyPair } from "near-api-js"; import invariant from "tiny-invariant"; +import nacl from "tweetnacl"; import { implicitAddressFromPublicKey, kwilNep413Signer } from "../../kwil-nep413-signer/src"; export interface CreateIssuerConfigParams { @@ -48,8 +50,10 @@ export async function createIssuerConfig(params: CreateIssuerConfigParams) { }); const signer = createKwilSigner(params.signer); + const secretKey = Base64Codec.decode(params.encryptionSecret); + const keyPair = nacl.box.keyPair.fromSecretKey(secretKey); - return { chainId, dbid, kwilClient, signer, encryptionSecret: params.encryptionSecret }; + return { chainId, dbid, kwilClient, signer, keyPair }; } export type IssuerConfig = Awaited>; diff --git a/packages/issuer-sdk-js/src/credentials.ts b/packages/issuer-sdk-js/src/credentials.ts index 3e83c9708..fb60c2287 100644 --- a/packages/issuer-sdk-js/src/credentials.ts +++ b/packages/issuer-sdk-js/src/credentials.ts @@ -5,29 +5,32 @@ import type { IssuerConfig } from "./create-issuer-config"; import { createActionInput, encryptContent, ensureEntityId } from "./internal"; // Base interface for credential parameters -interface BaseCredentialParams extends Omit { +interface BaseCredentialParams + extends Omit { id?: string; } -interface HasUserEncryptionPublicKey { +interface HasEncryptionPublicKey { userEncryptionPublicKey: string; } -interface CreateCredentialPermissionedParams - extends BaseCredentialParams, - HasUserEncryptionPublicKey {} +interface CreateCredentialPermissionedParams extends BaseCredentialParams, HasEncryptionPublicKey {} export async function createCredentialPermissioned( - { dbid, kwilClient, encryptionSecret, signer }: IssuerConfig, + { dbid, kwilClient, keyPair, signer }: IssuerConfig, params: CreateCredentialPermissionedParams, ): Promise { const encryptedContent = await encryptContent( Utf8Codec.encode(params.content), Base64Codec.decode(params.userEncryptionPublicKey), - Base64Codec.decode(encryptionSecret), + keyPair.secretKey, ); - const payload = { ...ensureEntityId(params), content: encryptedContent }; + const payload = { + ...ensureEntityId(params), + content: encryptedContent, + encryption_public_key: Base64Codec.encode(keyPair.publicKey), + }; await kwilClient.execute( { name: "upsert_credential_as_inserter", @@ -44,19 +47,23 @@ export async function createCredentialPermissioned( }; } -interface CreateCredentialByGrantParams extends BaseCredentialParams, HasUserEncryptionPublicKey {} +interface CreateCredentialByGrantParams extends BaseCredentialParams, HasEncryptionPublicKey {} export async function createCredentialByGrant( - { dbid, kwilClient, encryptionSecret, signer }: IssuerConfig, + { dbid, kwilClient, keyPair, signer }: IssuerConfig, params: CreateCredentialByGrantParams, ): Promise { const encryptedContent = await encryptContent( Utf8Codec.encode(params.content), Base64Codec.decode(params.userEncryptionPublicKey), - Base64Codec.decode(encryptionSecret), + keyPair.secretKey, ); - const payload = { ...ensureEntityId(params), content: encryptedContent }; + const payload = { + ...ensureEntityId(params), + content: encryptedContent, + encryption_public_key: Base64Codec.encode(keyPair.publicKey), + }; await kwilClient.execute( { name: "add_credential_by_write_grant", @@ -73,23 +80,27 @@ export async function createCredentialByGrant( }; } -interface ShareCredentialByGrantParams extends BaseCredentialParams, HasUserEncryptionPublicKey { +interface ShareCredentialByGrantParams extends BaseCredentialParams, HasEncryptionPublicKey { grantee: string; locked_until: number; original_credential_id: string; } export async function shareCredentialByGrant( - { dbid, kwilClient, encryptionSecret, signer }: IssuerConfig, + { dbid, kwilClient, keyPair, signer }: IssuerConfig, params: ShareCredentialByGrantParams, ): Promise { const encryptedContent = await encryptContent( Utf8Codec.encode(params.content), Base64Codec.decode(params.userEncryptionPublicKey), - Base64Codec.decode(encryptionSecret), + keyPair.secretKey, ); - const payload = { ...ensureEntityId(params), content: encryptedContent }; + const payload = { + ...ensureEntityId(params), + content: encryptedContent, + encryption_public_key: Base64Codec.encode(keyPair.publicKey), + }; await kwilClient.execute( { name: "share_credential_by_write_grant", From 8fabab3e6f4b58dd175a92933109c2d9bf49e0ac Mon Sep 17 00:00:00 2001 From: Mohammed-Mamoun98 Date: Wed, 13 Nov 2024 11:48:58 +0200 Subject: [PATCH 2/5] remove unnecessary interfaces + update related docs --- packages/issuer-sdk-js/README.md | 5 +---- packages/issuer-sdk-js/src/credentials.ts | 18 +++++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/issuer-sdk-js/README.md b/packages/issuer-sdk-js/README.md index cb876f899..2c09391ec 100644 --- a/packages/issuer-sdk-js/README.md +++ b/packages/issuer-sdk-js/README.md @@ -182,9 +182,6 @@ const credential = { // `createCredentialByGrant` will encrypt this for us, using the Issuer's secret encryption key, along with the user's public encryption key. content: "VERIFIABLE_CREDENTIAL_CONTENT", - // The public encryption key of the issuer. - encryption_public_key: issuerConfig.issuerPublicEncryptionKey, - // The public encryption key of the user who is creating the credential. userEncryptionPublicKey: session.user.userEncryptionPublicKey, } @@ -220,7 +217,7 @@ const credential = { issuer: "ISSUER_NAME", content: "VERIFIABLE_CREDENTIAL_CONTENT", human_id: session.user.humanId, - encryption_public_key: issuerConfig.issuerPublicEncryptionKey, + userEncryptionPublicKey: session.user.userEncryptionPublicKey, } await createCredentialPermissioned(issuerConfig, credential); diff --git a/packages/issuer-sdk-js/src/credentials.ts b/packages/issuer-sdk-js/src/credentials.ts index fb60c2287..bf96ca615 100644 --- a/packages/issuer-sdk-js/src/credentials.ts +++ b/packages/issuer-sdk-js/src/credentials.ts @@ -4,17 +4,21 @@ import type { idOSCredential } from "../../types"; import type { IssuerConfig } from "./create-issuer-config"; import { createActionInput, encryptContent, ensureEntityId } from "./internal"; -// Base interface for credential parameters +/** + * Interface for BaseCredentialParams. + * + * `id` could be provided manually, but it is randomly generated internally. + * `encryption_public_key` is **excluded** because it is derived internally + * from the issuer's secret key and should not be provided manually. + * + */ interface BaseCredentialParams extends Omit { id?: string; -} - -interface HasEncryptionPublicKey { userEncryptionPublicKey: string; } -interface CreateCredentialPermissionedParams extends BaseCredentialParams, HasEncryptionPublicKey {} +interface CreateCredentialPermissionedParams extends BaseCredentialParams {} export async function createCredentialPermissioned( { dbid, kwilClient, keyPair, signer }: IssuerConfig, @@ -47,7 +51,7 @@ export async function createCredentialPermissioned( }; } -interface CreateCredentialByGrantParams extends BaseCredentialParams, HasEncryptionPublicKey {} +interface CreateCredentialByGrantParams extends BaseCredentialParams {} export async function createCredentialByGrant( { dbid, kwilClient, keyPair, signer }: IssuerConfig, @@ -80,7 +84,7 @@ export async function createCredentialByGrant( }; } -interface ShareCredentialByGrantParams extends BaseCredentialParams, HasEncryptionPublicKey { +interface ShareCredentialByGrantParams extends BaseCredentialParams { grantee: string; locked_until: number; original_credential_id: string; From 95ed23ee5680016355a5b875dc4dcdafbef8d153 Mon Sep 17 00:00:00 2001 From: Mohammed-Mamoun98 Date: Wed, 13 Nov 2024 12:14:54 +0200 Subject: [PATCH 3/5] fix test file --- packages/issuer-sdk-js/src/create-issuer-config.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/issuer-sdk-js/src/create-issuer-config.test.ts b/packages/issuer-sdk-js/src/create-issuer-config.test.ts index a771616d6..9e56a9aa4 100644 --- a/packages/issuer-sdk-js/src/create-issuer-config.test.ts +++ b/packages/issuer-sdk-js/src/create-issuer-config.test.ts @@ -1,5 +1,7 @@ import { KwilSigner, NodeKwil } from "@kwilteam/kwil-js"; +import * as Base64Codec from "@stablelib/base64"; import { Wallet } from "ethers"; +import nacl from "tweetnacl"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { createIssuerConfig } from "./index"; @@ -40,10 +42,12 @@ describe("createIssuerConfig", () => { const mockWallet = new Wallet( "dcdda6663be8dfa23d0e54a31ff6fddba2fdf8a1f0eae985c59857031e6da169", ); + const mockSecretKey = nacl.randomBytes(32); + const params = { nodeUrl: "http://mock-node-url", signer: mockWallet, - encryptionSecret: "mock-secret-key", + encryptionSecret: Base64Codec.encode(mockSecretKey), }; const result = await createIssuerConfig(params); @@ -70,7 +74,7 @@ describe("createIssuerConfig", () => { dbid: "mock-dbid", kwilClient: expect.any(Object), signer: expect.any(Object), - encryptionSecret: params.encryptionSecret, + keyPair: nacl.box.keyPair.fromSecretKey(Base64Codec.decode(params.encryptionSecret)), }); }); }); From 0213c03fe2cc5ba8bb4df7a22cad7eb397416837 Mon Sep 17 00:00:00 2001 From: Mohammed-Mamoun98 Date: Wed, 13 Nov 2024 12:23:22 +0200 Subject: [PATCH 4/5] use box.keyPair().secretKey instead of randomBytes(32) --- packages/issuer-sdk-js/src/create-issuer-config.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/issuer-sdk-js/src/create-issuer-config.test.ts b/packages/issuer-sdk-js/src/create-issuer-config.test.ts index 9e56a9aa4..8083ffc38 100644 --- a/packages/issuer-sdk-js/src/create-issuer-config.test.ts +++ b/packages/issuer-sdk-js/src/create-issuer-config.test.ts @@ -42,7 +42,7 @@ describe("createIssuerConfig", () => { const mockWallet = new Wallet( "dcdda6663be8dfa23d0e54a31ff6fddba2fdf8a1f0eae985c59857031e6da169", ); - const mockSecretKey = nacl.randomBytes(32); + const mockSecretKey = nacl.box.keyPair().secretKey; const params = { nodeUrl: "http://mock-node-url", From 00f80ff6b6c4d07812d98754b52c00cfbc579fe6 Mon Sep 17 00:00:00 2001 From: Mohammed-Mamoun98 Date: Wed, 13 Nov 2024 12:30:37 +0200 Subject: [PATCH 5/5] pkoch PR notes --- .../src/create-issuer-config.test.ts | 4 +++- .../issuer-sdk-js/src/create-issuer-config.ts | 6 ++--- packages/issuer-sdk-js/src/credentials.ts | 24 +++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/issuer-sdk-js/src/create-issuer-config.test.ts b/packages/issuer-sdk-js/src/create-issuer-config.test.ts index 8083ffc38..b83e30cf1 100644 --- a/packages/issuer-sdk-js/src/create-issuer-config.test.ts +++ b/packages/issuer-sdk-js/src/create-issuer-config.test.ts @@ -74,7 +74,9 @@ describe("createIssuerConfig", () => { dbid: "mock-dbid", kwilClient: expect.any(Object), signer: expect.any(Object), - keyPair: nacl.box.keyPair.fromSecretKey(Base64Codec.decode(params.encryptionSecret)), + encryptionKeyPair: nacl.box.keyPair.fromSecretKey( + Base64Codec.decode(params.encryptionSecret), + ), }); }); }); diff --git a/packages/issuer-sdk-js/src/create-issuer-config.ts b/packages/issuer-sdk-js/src/create-issuer-config.ts index 127fd2626..339da13bf 100644 --- a/packages/issuer-sdk-js/src/create-issuer-config.ts +++ b/packages/issuer-sdk-js/src/create-issuer-config.ts @@ -50,10 +50,10 @@ export async function createIssuerConfig(params: CreateIssuerConfigParams) { }); const signer = createKwilSigner(params.signer); - const secretKey = Base64Codec.decode(params.encryptionSecret); - const keyPair = nacl.box.keyPair.fromSecretKey(secretKey); + const encryptionSecretKey = Base64Codec.decode(params.encryptionSecret); + const encryptionKeyPair = nacl.box.keyPair.fromSecretKey(encryptionSecretKey); - return { chainId, dbid, kwilClient, signer, keyPair }; + return { chainId, dbid, kwilClient, signer, encryptionKeyPair }; } export type IssuerConfig = Awaited>; diff --git a/packages/issuer-sdk-js/src/credentials.ts b/packages/issuer-sdk-js/src/credentials.ts index bf96ca615..cbee0223d 100644 --- a/packages/issuer-sdk-js/src/credentials.ts +++ b/packages/issuer-sdk-js/src/credentials.ts @@ -7,9 +7,9 @@ import { createActionInput, encryptContent, ensureEntityId } from "./internal"; /** * Interface for BaseCredentialParams. * - * `id` could be provided manually, but it is randomly generated internally. - * `encryption_public_key` is **excluded** because it is derived internally - * from the issuer's secret key and should not be provided manually. + * `id` can be manually provided. If it isn't provided, it will be randomly generated. + * `encryption_public_key` is omitted because it is derived internally + * from the issuer's encryption secret key. * */ interface BaseCredentialParams @@ -21,19 +21,19 @@ interface BaseCredentialParams interface CreateCredentialPermissionedParams extends BaseCredentialParams {} export async function createCredentialPermissioned( - { dbid, kwilClient, keyPair, signer }: IssuerConfig, + { dbid, kwilClient, encryptionKeyPair, signer }: IssuerConfig, params: CreateCredentialPermissionedParams, ): Promise { const encryptedContent = await encryptContent( Utf8Codec.encode(params.content), Base64Codec.decode(params.userEncryptionPublicKey), - keyPair.secretKey, + encryptionKeyPair.secretKey, ); const payload = { ...ensureEntityId(params), content: encryptedContent, - encryption_public_key: Base64Codec.encode(keyPair.publicKey), + encryption_public_key: Base64Codec.encode(encryptionKeyPair.publicKey), }; await kwilClient.execute( { @@ -54,19 +54,19 @@ export async function createCredentialPermissioned( interface CreateCredentialByGrantParams extends BaseCredentialParams {} export async function createCredentialByGrant( - { dbid, kwilClient, keyPair, signer }: IssuerConfig, + { dbid, kwilClient, encryptionKeyPair, signer }: IssuerConfig, params: CreateCredentialByGrantParams, ): Promise { const encryptedContent = await encryptContent( Utf8Codec.encode(params.content), Base64Codec.decode(params.userEncryptionPublicKey), - keyPair.secretKey, + encryptionKeyPair.secretKey, ); const payload = { ...ensureEntityId(params), content: encryptedContent, - encryption_public_key: Base64Codec.encode(keyPair.publicKey), + encryption_public_key: Base64Codec.encode(encryptionKeyPair.publicKey), }; await kwilClient.execute( { @@ -91,19 +91,19 @@ interface ShareCredentialByGrantParams extends BaseCredentialParams { } export async function shareCredentialByGrant( - { dbid, kwilClient, keyPair, signer }: IssuerConfig, + { dbid, kwilClient, encryptionKeyPair, signer }: IssuerConfig, params: ShareCredentialByGrantParams, ): Promise { const encryptedContent = await encryptContent( Utf8Codec.encode(params.content), Base64Codec.decode(params.userEncryptionPublicKey), - keyPair.secretKey, + encryptionKeyPair.secretKey, ); const payload = { ...ensureEntityId(params), content: encryptedContent, - encryption_public_key: Base64Codec.encode(keyPair.publicKey), + encryption_public_key: Base64Codec.encode(encryptionKeyPair.publicKey), }; await kwilClient.execute( {