diff --git a/package.json b/package.json index 228ad9e..5315da8 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "dependencies": { "axios": "^0.19.2", "basic-provider": "^1.1.0", - "eccrypto-js": "^5.2.0", + "eccrypto-js": "^5.3.0", "localStorage": "^1.0.4" } } diff --git a/src/controllers/keyring.ts b/src/controllers/keyring.ts index ad8f861..df38361 100644 --- a/src/controllers/keyring.ts +++ b/src/controllers/keyring.ts @@ -1,9 +1,12 @@ import { generateKeyPair, bufferToHex, - getPublic, hexToBuffer, - generatePrivate, + randomBytes, + pbkdf2, + utf8ToBuffer, + removeHexPrefix, + getPublicCompressed, } from "eccrypto-js"; import { @@ -16,8 +19,7 @@ import { JsonRpcRequest, } from "../typings"; import { STORE_KEYS_ID, WAKU_PREFIX } from "../constants"; -import { uuid, getFirstMatch } from "../helpers"; -import { isKeyPair, isSymKey } from "../helpers/validators"; +import { getFirstMatch, isKeyPair, isSymKey } from "../helpers"; export class WakuKeyring implements IWakuKeyring { private keyMap: KeyMap = {}; @@ -77,7 +79,7 @@ export class WakuKeyring implements IWakuKeyring { } public async newSymKey(): Promise { - const key = this.genSymKey(); + const key = await this.genSymKey(); await this.addKey(key); return key.id; } @@ -86,7 +88,7 @@ export class WakuKeyring implements IWakuKeyring { let key = this.getMatchingKey("symKey", symKey); if (!key) { key = { - id: uuid(), + id: this.getKeyId(symKey), symKey, }; } @@ -94,9 +96,8 @@ export class WakuKeyring implements IWakuKeyring { return key.id; } - public async generateSymKeyFromPassword(): Promise { - // TODO: needs to accept optional "password" argument - const key = this.genSymKey(); + public async generateSymKeyFromPassword(password: string): Promise { + const key = await this.genSymKey(password); await this.addKey(key); return key.id; } @@ -128,28 +129,39 @@ export class WakuKeyring implements IWakuKeyring { private genKeyPair(prvKey?: string): KeyPair { if (prvKey) { return { - id: uuid(), - pubKey: bufferToHex(getPublic(hexToBuffer(prvKey)), true), + id: this.getKeyId(prvKey), + pubKey: this.getPubKey(prvKey), prvKey, }; } else { const key = generateKeyPair(); return { - id: uuid(), + id: this.getKeyId(bufferToHex(key.privateKey)), pubKey: bufferToHex(key.publicKey, true), prvKey: bufferToHex(key.privateKey, true), }; } } - private genSymKey(): SymKey { - const symKey = generatePrivate(); + private async genSymKey(password?: string): Promise { + const symKey = + typeof password === "string" + ? await pbkdf2(utf8ToBuffer(password)) + : randomBytes(32); return { - id: uuid(), + id: this.getKeyId(bufferToHex(symKey)), symKey: bufferToHex(symKey, true), }; } + private getPubKey(prvKey: string): string { + return bufferToHex(getPublicCompressed(hexToBuffer(prvKey)), true); + } + + private getKeyId(prvKey: string): string { + return removeHexPrefix(this.getPubKey(prvKey)).substr(2); + } + private async loadKeys(): Promise { this.keyMap = (await this.store.get(STORE_KEYS_ID)) || {}; } diff --git a/src/helpers/index.ts b/src/helpers/index.ts index e27cc00..709045d 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -1,4 +1,4 @@ export * from "./json"; export * from "./local"; export * from "./misc"; -export * from "./uuid"; +export * from "./validators"; diff --git a/src/helpers/uuid.ts b/src/helpers/uuid.ts deleted file mode 100644 index 870a101..0000000 --- a/src/helpers/uuid.ts +++ /dev/null @@ -1,16 +0,0 @@ -export function uuid(): string { - const result: string = ((a?: any, b?: any) => { - for ( - b = a = ""; - a++ < 36; - b += - (a * 51) & 52 - ? (a ^ 15 ? 8 ^ (Math.random() * (a ^ 20 ? 16 : 4)) : 4).toString(16) - : "-" - ) { - // empty - } - return b; - })(); - return result; -} diff --git a/src/typings/controllers.ts b/src/typings/controllers.ts index a33b889..7ce3ee5 100644 --- a/src/typings/controllers.ts +++ b/src/typings/controllers.ts @@ -20,7 +20,7 @@ export interface IWakuKeyring extends IWakuController { getPrivateKey(id: string): Promise; newSymKey(): Promise; addSymKey(symKey: string): Promise; - generateSymKeyFromPassword(): Promise; + generateSymKeyFromPassword(password: string): Promise; hasSymKey(id: string): Promise; getSymKey(id: string): Promise; deleteSymKey(id: string): Promise; diff --git a/test/client.test.ts b/test/client.test.ts index 6a7c62e..22b9df4 100644 --- a/test/client.test.ts +++ b/test/client.test.ts @@ -57,4 +57,24 @@ describe("Waku", () => { }); expect(prvKey).toBeTruthy(); }); + + it("should create symmetric key", async () => { + const symKey = await waku.request({ + id: 1, + jsonrpc: "2.0", + method: "waku_newSymKey", + params: [], + }); + expect(symKey).toBeTruthy(); + }); + + it("should generate symmetric key from password", async () => { + const symKey = await waku.request({ + id: 1, + jsonrpc: "2.0", + method: "waku_generateSymKeyFromPassword", + params: ["password"], + }); + expect(symKey).toBeTruthy(); + }); }); diff --git a/yarn.lock b/yarn.lock index 2e725b5..5e97e76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2705,15 +2705,16 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -eccrypto-js@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/eccrypto-js/-/eccrypto-js-5.2.0.tgz#eb3b36e9978d316fedf50be46492bb0d3e240cf5" - integrity sha512-pPb6CMapJ1LIzjLWxMqlrnfaEFap7qkk9wcO/b4AVSdxBQYlpOqvlPpq5SpUI4FdmfdhVD34AjN47fM8fryC4A== +eccrypto-js@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/eccrypto-js/-/eccrypto-js-5.3.0.tgz#67417e43691ad78992249097ac558776c9ac5ff3" + integrity sha512-fCPIHNr/RDSCNY9NKkrSsjkurb6Rw/d5TYVdzjJeA3E+HcF+DdaWAvhDdsAcBOGUJ6Ygs8o6b4imuvhx9t7o+Q== dependencies: aes-js "3.1.2" enc-utils "2.1.0" hash.js "1.1.7" js-sha3 "0.8.0" + pbkdf2 "^3.0.17" randombytes "2.1.0" secp256k1 "3.8.0" @@ -5602,7 +5603,7 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pbkdf2@^3.0.3: +pbkdf2@^3.0.17, pbkdf2@^3.0.3: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==