Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update ethereum-cryptography dep #28

Merged
merged 1 commit into from
Feb 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@
},
"dependencies": {
"ajv": "^6.12.2",
"buffer": "^5.4.3",
"ethereum-cryptography": "^0.1.3",
"ethereum-cryptography": "^1.0.0",
"uuid": "^3.3.3"
}
}
12 changes: 6 additions & 6 deletions src/checksum.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Buffer } from "buffer";
import { sha256 } from "ethereum-cryptography/sha256";
import { concatBytes, equalsBytes, hexToBytes } from "ethereum-cryptography/utils";

import { IChecksumModule } from "./types";

Expand All @@ -13,21 +13,21 @@ export function defaultSha256Module(): Pick<IChecksumModule, "function"> {

// checksum operations

function checksumData(key: Buffer, ciphertext: Buffer): Buffer {
return Buffer.concat([key.slice(16), ciphertext]);
function checksumData(key: Uint8Array, ciphertext: Uint8Array): Uint8Array {
return concatBytes(key.slice(16), ciphertext);
}

export function checksum(mod: IChecksumModule, key: Buffer, ciphertext: Buffer): Promise<Buffer> {
export function checksum(mod: IChecksumModule, key: Uint8Array, ciphertext: Uint8Array): Promise<Uint8Array> {
if (mod.function === "sha256") {
return Promise.resolve(sha256(checksumData(key, ciphertext)));
} else {
throw new Error("Invalid checksum type");
}
}

export async function verifyChecksum(mod: IChecksumModule, key: Buffer, ciphertext: Buffer): Promise<boolean> {
export async function verifyChecksum(mod: IChecksumModule, key: Uint8Array, ciphertext: Uint8Array): Promise<boolean> {
if (mod.function === "sha256") {
return Buffer.from(mod.message, "hex").equals(sha256(checksumData(key, ciphertext)));
return equalsBytes(hexToBytes(mod.message), sha256(checksumData(key, ciphertext)));
} else {
throw new Error("Invalid checksum type");
}
Expand Down
16 changes: 8 additions & 8 deletions src/cipher.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { Buffer } from "buffer";
import { getRandomBytesSync } from "ethereum-cryptography/random";
import { encrypt as aesEncrypt, decrypt as aesDecrypt } from "ethereum-cryptography/aes";

import { ICipherModule } from "./types";
import { bytesToHex, hexToBytes } from "ethereum-cryptography/utils";

export function defaultAes128CtrModule(): Pick<ICipherModule, "function" | "params"> {
return {
function: "aes-128-ctr",
params: {
iv: getRandomBytesSync(16).toString("hex"),
iv: bytesToHex(getRandomBytesSync(16)),
},
};
}

export async function cipherEncrypt(mod: ICipherModule, key: Buffer, data: Uint8Array): Promise<Buffer> {
export async function cipherEncrypt(mod: ICipherModule, key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
if (mod.function === "aes-128-ctr") {
try {
return await aesEncrypt(
Buffer.from(data),
data,
key,
Buffer.from(mod.params.iv, "hex"),
hexToBytes(mod.params.iv),
mod.function,
false,
);
Expand All @@ -31,13 +31,13 @@ export async function cipherEncrypt(mod: ICipherModule, key: Buffer, data: Uint8
}
}

export async function cipherDecrypt(mod: ICipherModule, key: Buffer): Promise<Buffer> {
export async function cipherDecrypt(mod: ICipherModule, key: Uint8Array): Promise<Uint8Array> {
if (mod.function === "aes-128-ctr") {
try {
return await aesDecrypt(
Buffer.from(mod.message, "hex"),
hexToBytes(mod.message),
key,
Buffer.from(mod.params.iv, "hex"),
hexToBytes(mod.params.iv),
mod.function,
false,
);
Expand Down
2 changes: 1 addition & 1 deletion src/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class Keystore implements IKeystore {
/**
* Decrypt a keystore, returns the secret key or throws on invalid password
*/
async decrypt(password: string | Uint8Array): Promise<Buffer> {
async decrypt(password: string | Uint8Array): Promise<Uint8Array> {
return decrypt(this, password);
}

Expand Down
14 changes: 7 additions & 7 deletions src/functional.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Ajv = require("ajv");
import { Buffer } from "buffer";
import {v4 as uuidV4} from "uuid";
import schema = require("./schema.json");

Expand All @@ -8,6 +7,7 @@ import { kdf, defaultPbkdfModule, defaultScryptModule } from "./kdf";
import { checksum, verifyChecksum, defaultSha256Module } from "./checksum";
import { cipherEncrypt, cipherDecrypt, defaultAes128CtrModule } from "./cipher";
import { normalizePassword } from "./password";
import { bytesToHex, hexToBytes } from "ethereum-cryptography/utils";

export {
defaultPbkdfModule,
Expand Down Expand Up @@ -44,7 +44,7 @@ export async function create(
uuid: uuidV4(),
description: description || undefined,
path: path,
pubkey: Buffer.from(pubkey).toString("hex"),
pubkey: bytesToHex(pubkey),
crypto: {
kdf: {
function: kdfMod.function,
Expand All @@ -56,14 +56,14 @@ export async function create(
checksum: {
function: checksumMod.function,
params: {},
message: (await checksum(checksumMod as IChecksumModule, encryptionKey, ciphertext)).toString("hex"),
message: bytesToHex(await checksum(checksumMod as IChecksumModule, encryptionKey, ciphertext)),
},
cipher: {
function: cipherMod.function,
params: {
...cipherMod.params,
},
message: ciphertext.toString("hex"),
message: bytesToHex(ciphertext),
},
},
};
Expand All @@ -74,16 +74,16 @@ export async function create(
*/
export async function verifyPassword(keystore: IKeystore, password: string | Uint8Array): Promise<boolean> {
const decryptionKey = await kdf(keystore.crypto.kdf, normalizePassword(password));
const ciphertext = Buffer.from(keystore.crypto.cipher.message, "hex");
const ciphertext = hexToBytes(keystore.crypto.cipher.message);
return verifyChecksum(keystore.crypto.checksum, decryptionKey, ciphertext);
}

/**
* Decrypt a keystore, returns the secret key or throws on invalid password
*/
export async function decrypt(keystore: IKeystore, password: string | Uint8Array): Promise<Buffer> {
export async function decrypt(keystore: IKeystore, password: string | Uint8Array): Promise<Uint8Array> {
const decryptionKey = await kdf(keystore.crypto.kdf, normalizePassword(password));
const ciphertext = Buffer.from(keystore.crypto.cipher.message, "hex");
const ciphertext = hexToBytes(keystore.crypto.cipher.message);
if (!(await verifyChecksum(keystore.crypto.checksum, decryptionKey, ciphertext))) {
throw new Error("Invalid password");
}
Expand Down
16 changes: 8 additions & 8 deletions src/kdf.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Buffer } from "buffer";
import { getRandomBytesSync } from "ethereum-cryptography/random";
import { pbkdf2 } from "ethereum-cryptography/pbkdf2";
import { scrypt } from "ethereum-cryptography/scrypt";
import { bytesToHex, hexToBytes } from "ethereum-cryptography/utils"

import { IKdfModule, IPbkdf2KdfModule, IScryptKdfModule } from "./types";

Expand All @@ -14,7 +14,7 @@ export function defaultPbkdfModule(): Pick<IPbkdf2KdfModule, "function" | "param
dklen: 32,
c: 262144,
prf: "hmac-sha256",
salt: getRandomBytesSync(32).toString("hex"),
salt: bytesToHex(getRandomBytesSync(32)),
},
};
}
Expand All @@ -27,14 +27,14 @@ export function defaultScryptModule(): Pick<IScryptKdfModule, "function" | "para
n: 262144,
r: 8,
p: 1,
salt: getRandomBytesSync(32).toString("hex"),
salt: bytesToHex(getRandomBytesSync(32)),
},
};
}

// kdf operations

export async function kdf(mod: IKdfModule, password: Buffer): Promise<Buffer> {
export async function kdf(mod: IKdfModule, password: Uint8Array): Promise<Uint8Array> {
if (mod.function === "pbkdf2") {
return await doPbkdf2(mod.params, password);
} else if (mod.function === "scrypt") {
Expand All @@ -43,20 +43,20 @@ export async function kdf(mod: IKdfModule, password: Buffer): Promise<Buffer> {
throw new Error("Invalid kdf type");
}
}
async function doPbkdf2(params: IPbkdf2KdfModule["params"], password: Buffer): Promise<Buffer> {
async function doPbkdf2(params: IPbkdf2KdfModule["params"], password: Uint8Array): Promise<Uint8Array> {
return pbkdf2(
password,
Buffer.from(params.salt, "hex"),
hexToBytes(params.salt),
params.c,
params.dklen,
params.prf.slice(5),
);
}

async function doScrypt(params: IScryptKdfModule["params"], password: Buffer): Promise<Buffer> {
async function doScrypt(params: IScryptKdfModule["params"], password: Uint8Array): Promise<Uint8Array> {
return scrypt(
password,
Buffer.from(params.salt, "hex"),
hexToBytes(params.salt),
params.n,
params.p,
params.r,
Expand Down
8 changes: 4 additions & 4 deletions src/password.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Buffer } from "buffer";
import { utf8ToBytes } from "ethereum-cryptography/utils";

export function normalizePassword(password: string | Uint8Array): Buffer {
export function normalizePassword(password: string | Uint8Array): Uint8Array {
if (typeof password === "string") {
return Buffer.from(password.normalize("NFKD"), "utf8");
return utf8ToBytes(password.normalize("NFKD"));
} else {
return Buffer.from(password);
return password;
}
}
14 changes: 8 additions & 6 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import { expect } from "chai";
import { Buffer } from "buffer";
import { hexToBytes } from "ethereum-cryptography/utils";

import { create, decrypt, verifyPassword, isValidKeystore, validateKeystore } from "../src"

describe("BLS12-381 Keystore Test", () => {
it("Roundtrip should work", async () => {
const testKeystore = await create("test", Buffer.alloc(32), Buffer.alloc(48), "");
it("Roundtrip should work", async function () {
this.timeout(10000)
const testKeystore = await create("test", new Uint8Array(32), new Uint8Array(48), "");
expect(isValidKeystore(testKeystore)).to.be.true;
expect(await verifyPassword(testKeystore, "test")).to.be.true;
});
});

describe("Known Test Vectors", () => {
it("Should be able to encrypt/decrypt Pbkdf2 keystores", async () => {
it("Should be able to encrypt/decrypt Pbkdf2 keystores", async function () {
this.timeout(100000)
const keystores = [
require('./vectors/pbkdf2-0.json'),
require('./vectors/pbkdf2-0.json'),
];
for (const keystore of keystores) {
const password = keystore.password;
const secret = Buffer.from(keystore.secret.slice(2), "hex");
const secret = hexToBytes(keystore.secret.slice(2));

expect(isValidKeystore(keystore)).to.be.true;
expect(await verifyPassword(keystore, password)).to.be.true;
Expand All @@ -35,7 +37,7 @@ describe("Known Test Vectors", () => {
];
for (const keystore of keystores) {
const password = keystore.password;
const secret = Buffer.from(keystore.secret.slice(2), "hex");
const secret = hexToBytes(keystore.secret.slice(2));

expect(isValidKeystore(keystore)).to.be.true;
expect(await verifyPassword(keystore, password)).to.be.true;
Expand Down
Loading