Skip to content
This repository has been archived by the owner on Jan 24, 2023. It is now read-only.

Commit

Permalink
replace pbkdf2 package with async pbkdf2-hmac
Browse files Browse the repository at this point in the history
  • Loading branch information
kwypchlo committed May 25, 2022
1 parent 2ffc356 commit 2ba6606
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 147 deletions.
2 changes: 1 addition & 1 deletion integration/file.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe(`File API integration tests for portal '${portal}'`, () => {
});

it("getEntryData should return null for non-existent File API entry data", async () => {
const { publicKey: userID } = genKeyPairAndSeed();
const { publicKey: userID } = await genKeyPairAndSeed();
const { data: received } = await client.file.getEntryData(userID, path);
expect(received).toBeNull();
});
Expand Down
10 changes: 5 additions & 5 deletions integration/registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe(`Registry end to end integration tests for portal '${portal}'`, () => {
const data = stringToUint8ArrayUtf8(skylink);

it("Should return null for an inexistent entry", async () => {
const { publicKey } = genKeyPairAndSeed();
const { publicKey } = await genKeyPairAndSeed();

// Try getting an inexistent entry.
const { entry, signature } = await client.registry.getEntry(publicKey, "foo");
Expand All @@ -16,7 +16,7 @@ describe(`Registry end to end integration tests for portal '${portal}'`, () => {
});

it("Should set and get string entries correctly", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

const entry = {
dataKey,
Expand All @@ -33,7 +33,7 @@ describe(`Registry end to end integration tests for portal '${portal}'`, () => {
});

it("Should set and get unicode entries correctly", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

const entry = {
dataKey,
Expand All @@ -50,7 +50,7 @@ describe(`Registry end to end integration tests for portal '${portal}'`, () => {
});

it("Should set and get an entry with empty data correctly", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

const entry = {
dataKey,
Expand All @@ -67,7 +67,7 @@ describe(`Registry end to end integration tests for portal '${portal}'`, () => {
});

it("Should fail to set an entry with a revision number that's too low", async () => {
const { privateKey } = genKeyPairAndSeed();
const { privateKey } = await genKeyPairAndSeed();

const entry = {
dataKey,
Expand Down
20 changes: 10 additions & 10 deletions integration/skydb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
});

it("Should return null for an inexistent entry", async () => {
const { publicKey } = genKeyPairAndSeed();
const { publicKey } = await genKeyPairAndSeed();

// Try getting an inexistent entry.
const { data, dataLink } = await client.db.getJSON(publicKey, "foo");
Expand All @@ -69,7 +69,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
});

it("Should set and get new entries", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const json = { data: "thisistext" };
const json2 = { data: "foo2" };

Expand All @@ -94,7 +94,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
const dataKeys = [".", "..", "http://localhost:8000/", ""];

it.each(dataKeys)("Should set and get new entry with dataKey '%s'", async (dataKey) => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const json = { data: "thisistext" };

await client.db.setJSON(privateKey, dataKey, json);
Expand All @@ -106,7 +106,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
});

it("Should be able to delete an existing entry", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const json = { data: "thisistext" };

await client.db.setJSON(privateKey, dataKey, json);
Expand All @@ -125,7 +125,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
});

it("Should be able to set a new entry as deleted and then write over it", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

await client.db.deleteJSON(privateKey, dataKey);

Expand Down Expand Up @@ -162,7 +162,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
});

it("Should correctly set a data link", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const dataLink = "AAAVyJktMuK-7WRCNUvYcYq7izvhCbgDLXlT4YgechblJw";
const dataLinkBytes = decodeSkylinkBase64(dataLink);

Expand All @@ -177,7 +177,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
});

it("should set and get entry data", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const data = new Uint8Array([1, 2, 3]);

// Set the entry data.
Expand All @@ -191,7 +191,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
});

it("should set and delete entry data", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const data = new Uint8Array([1, 2, 3]);

// Set the entry data.
Expand All @@ -208,7 +208,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
it("should be able to delete a new entry and then write over it", async () => {
const data = new Uint8Array([1, 2, 3]);

const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

// Delete the entry data.
await client.db.deleteEntryData(privateKey, dataKey);
Expand All @@ -228,7 +228,7 @@ describe(`SkyDB end to end integration tests for portal '${portal}'`, () => {
});

it("Should correctly handle the hashedDataKeyHex option", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const dataKey = "test";
const hashedDataKeyHex = toHexString(hashDataKey(dataKey));
const json = { message: "foo" };
Expand Down
22 changes: 11 additions & 11 deletions integration/skydb_v2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("Should return null for an inexistent entry", async () => {
const { publicKey } = genKeyPairAndSeed();
const { publicKey } = await genKeyPairAndSeed();

// Try getting an inexistent entry.
const { data, dataLink } = await client.dbV2.getJSON(publicKey, "foo");
Expand All @@ -69,7 +69,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("Should set and get new entries", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const json = { data: "thisistext" };
const json2 = { data: "foo2" };

Expand All @@ -94,7 +94,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
const dataKeys = [".", "..", "http://localhost:8000/", ""];

it.each(dataKeys)("Should set and get new entry with dataKey '%s'", async (dataKey) => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const json = { data: "thisistext" };

await client.dbV2.setJSON(privateKey, dataKey, json);
Expand All @@ -106,7 +106,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("Should be able to delete an existing entry", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const json = { data: "thisistext" };

await client.dbV2.setJSON(privateKey, dataKey, json);
Expand All @@ -125,7 +125,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("Should be able to set a new entry as deleted and then write over it", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

await client.dbV2.deleteJSON(privateKey, dataKey);

Expand Down Expand Up @@ -162,7 +162,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("Should correctly set a data link", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const dataLink = "AAAVyJktMuK-7WRCNUvYcYq7izvhCbgDLXlT4YgechblJw";
const dataLinkBytes = decodeSkylinkBase64(dataLink);

Expand All @@ -177,7 +177,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("should set and get entry data", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const data = new Uint8Array([1, 2, 3]);

// Set the entry data.
Expand All @@ -191,7 +191,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("should set and delete entry data", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const data = new Uint8Array([1, 2, 3]);

// Set the entry data.
Expand All @@ -208,7 +208,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
it("should be able to delete a new entry and then write over it", async () => {
const data = new Uint8Array([1, 2, 3]);

const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

// Delete the entry data.
await client.dbV2.deleteEntryData(privateKey, dataKey);
Expand All @@ -228,7 +228,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("Should correctly handle the hashedDataKeyHex option", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const dataKey = "test";
const hashedDataKeyHex = toHexString(hashDataKey(dataKey));
const json = { message: "foo" };
Expand All @@ -243,7 +243,7 @@ describe(`SkyDBV2 end to end integration tests for portal '${portal}'`, () => {
});

it("Should update the revision number cache", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();
const json = { message: 1 };

await client.dbV2.setJSON(privateKey, dataKey, json);
Expand Down
8 changes: 4 additions & 4 deletions integration/skydb_v2_data_race.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ describe.skip(`SkyDBV2 end to end integration getJSON/setJSON data race regressi
it.each(delays)(
"should not get old data when getJSON is called after setJSON on a single client with a '%s' ms delay and getJSON doesn't fail",
async (delay) => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

// Set the data.
await client.dbV2.setJSON(privateKey, dataKey, jsonOld);
Expand Down Expand Up @@ -86,7 +86,7 @@ describe.skip(`SkyDBV2 end to end integration getJSON/setJSON data race regressi
// Create two new clients with a fresh revision cache.
const client1 = new SkynetClient(portal, customOptions);
const client2 = new SkynetClient(portal, customOptions);
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

// Get revision entry cache handles.
const cachedRevisionEntry1 = await client1.dbV2.revisionNumberCache.getRevisionAndMutexForEntry(
Expand Down Expand Up @@ -171,7 +171,7 @@ describe.skip(`SkyDBV2 end to end integration getJSON/setJSON data race regressi
it.each(delays)(
"should make sure that two concurrent setJSON calls on a single client with a '%s' ms delay either fail with the right error or succeed ",
async (delay) => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

// Try to invoke two concurrent setJSON calls.
try {
Expand Down Expand Up @@ -205,7 +205,7 @@ describe.skip(`SkyDBV2 end to end integration getJSON/setJSON data race regressi
// Create two new clients with a fresh revision cache.
const client1 = new SkynetClient(portal, customOptions);
const client2 = new SkynetClient(portal, customOptions);
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

// Try to invoke two concurrent setJSON calls.
try {
Expand Down
2 changes: 1 addition & 1 deletion integration/upload_download.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ describe(`Upload and download end-to-end tests for portal '${portal}'`, () => {
});

it("Should update an etag for a resolver skylink after changing its data", async () => {
const { publicKey, privateKey } = genKeyPairAndSeed();
const { publicKey, privateKey } = await genKeyPairAndSeed();

// Generate random file data.
const [data1, data2] = [randomUnicodeString(4096), randomUnicodeString(4096)];
Expand Down
16 changes: 16 additions & 0 deletions jest-environment-jsdom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* eslint-disable */

const Environment = require("jest-environment-jsdom");

module.exports = class CustomTestEnvironment extends Environment {
async setup() {
await super.setup();

// https://github.com/jsdom/jsdom/issues/2524
if (typeof this.global.TextEncoder === "undefined") {
const { TextEncoder, TextDecoder } = require("util");
this.global.TextEncoder = TextEncoder;
this.global.TextDecoder = TextDecoder;
}
}
};
2 changes: 1 addition & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ const config: Config.InitialOptions = {
// snapshotSerializers: [],

// The test environment that will be used for testing
testEnvironment: "jsdom",
testEnvironment: "./jest-environment-jsdom.js",

// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"buffer-from": "^1.1.2",
"mime": "^3.0.0",
"path-browserify": "^1.0.1",
"pbkdf2": "^3.1.2",
"pbkdf2-hmac": "^1.0.4",
"post-me": "^0.4.5",
"skynet-mysky-utils": "^0.3.0",
"tweetnacl": "^1.0.3",
Expand Down
8 changes: 4 additions & 4 deletions src/crypto.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,24 @@ describe("deriveChildSeed", () => {
});

describe("genKeyPairAndSeed", () => {
it("should create a seed of the given length, hex-encoded", () => {
it("should create a seed of the given length, hex-encoded", async () => {
const length = 8;
const { seed } = genKeyPairAndSeed(length);
const { seed } = await genKeyPairAndSeed(length);
// The length is specified in bytes and seed.length gives us the length of
// the string representation of the seed bytes, which is hex encoded.
expect(seed.length).toEqual(length * 2);
});
});

describe("genKeyPairFromSeed", () => {
it("should create an expected keypair from a given seed", () => {
it("should create an expected keypair from a given seed", async () => {
// Hard-code expected values to catch any breaking changes.
const seed = "c1197e1275fbf570d21dde01a00af83ed4a743d1884e4a09cebce0dd21ae254c";
const expectedPublicKey = "f8a7da8324fabb9d57bb32c59c48d4ba304d08ee5f1297a46836cf841da71c80";
const expectedPrivateKey =
"c404ff07fba961000dfb25ece7477f45b109b50a5169a45f3fb239343002c1cff8a7da8324fabb9d57bb32c59c48d4ba304d08ee5f1297a46836cf841da71c80";

const { publicKey, privateKey } = genKeyPairFromSeed(seed);
const { publicKey, privateKey } = await genKeyPairFromSeed(seed);
expect(publicKey).toEqual(expectedPublicKey);
expect(privateKey).toEqual(expectedPrivateKey);
});
Expand Down
12 changes: 6 additions & 6 deletions src/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { blake2bFinal, blake2bInit, blake2bUpdate } from "blakejs";
import { hash, sign, randomBytes } from "tweetnacl";
import bufferFrom from "buffer-from";
import { pbkdf2Sync } from "pbkdf2";
import pbkdf2Hmac from "pbkdf2-hmac";

import { RegistryEntry } from "./registry";
import { hexToUint8Array, stringToUint8ArrayUtf8, toHexString } from "./utils/string";
Expand Down Expand Up @@ -68,11 +68,11 @@ export function deriveChildSeed(masterSeed: string, seed: string): string {
* @param [length=64] - The number of random bytes for the seed. Note that the string seed will be converted to hex representation, making it twice this length.
* @returns - The generated key pair and seed.
*/
export function genKeyPairAndSeed(length = 64): KeyPairAndSeed {
export async function genKeyPairAndSeed(length = 64): Promise<KeyPairAndSeed> {
validateNumber("length", length, "parameter");

const seed = genRandomSeed(length);
return { ...genKeyPairFromSeed(seed), seed };
return { ...(await genKeyPairFromSeed(seed)), seed };
}

/**
Expand All @@ -82,12 +82,12 @@ export function genKeyPairAndSeed(length = 64): KeyPairAndSeed {
* @returns - The generated key pair.
* @throws - Will throw if the input is not a string.
*/
export function genKeyPairFromSeed(seed: string): KeyPair {
export async function genKeyPairFromSeed(seed: string): Promise<KeyPair> {
validateString("seed", seed, "parameter");

// Get a 32-byte key.
const derivedKey = pbkdf2Sync(seed, "", 1000, 32, "sha256");
const { publicKey, secretKey } = sign.keyPair.fromSeed(Uint8Array.from(derivedKey));
const derivedKey = await pbkdf2Hmac(seed, "", 1000, 32, "SHA-256");
const { publicKey, secretKey } = sign.keyPair.fromSeed(new Uint8Array(derivedKey));

return { publicKey: toHexString(publicKey), privateKey: toHexString(secretKey) };
}
Expand Down
Loading

0 comments on commit 2ba6606

Please sign in to comment.