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

perf(crypto): replace bs58check with bstring #2673

Merged
merged 2 commits into from
Jun 8, 2019
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import "jest-extended";

import "./mocks/core-container";

import bs58check from "bs58check";
import ByteBuffer from "bytebuffer";

import { Wallets } from "@arkecosystem/core-state";
Expand Down Expand Up @@ -140,7 +139,7 @@ describe("Connection", () => {
// only for transfer right now
writeUint64("amount", +transaction.amount);
writeUint32("expiration", transaction.expiration || 0);
append("recipientId", bs58check.decode(transaction.recipientId));
append("recipientId", Identities.Address.decodeCheck(transaction.recipientId));

// signatures
if (transaction.signature || options.signature) {
Expand Down
5 changes: 2 additions & 3 deletions __tests__/unit/core-transactions/handler-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import "jest-extended";

import { Database, State, TransactionPool } from "@arkecosystem/core-interfaces";
import { Crypto, Enums, Identities, Interfaces, Managers, Transactions, Utils } from "@arkecosystem/crypto";
import bs58check from "bs58check";
import ByteBuffer from "bytebuffer";
import { Errors } from "../../../packages/core-transactions/src";
import { Registry, TransactionHandler } from "../../../packages/core-transactions/src/handlers";
Expand Down Expand Up @@ -43,7 +42,7 @@ class TestTransaction extends Transactions.Transaction {
const buffer = new ByteBuffer(24, true);
buffer.writeUint64(+data.amount);
buffer.writeUint32(data.expiration || 0);
buffer.append(bs58check.decode(data.recipientId));
buffer.append(Identities.Address.decodeCheck(data.recipientId));
buffer.writeInt32(data.asset.test);

return buffer;
Expand All @@ -53,7 +52,7 @@ class TestTransaction extends Transactions.Transaction {
const { data } = this;
data.amount = Utils.BigNumber.make(buf.readUint64().toString());
data.expiration = buf.readUint32();
data.recipientId = bs58check.encode(buf.readBytes(21).toBuffer());
data.recipientId = Identities.Address.encodeCheck(buf.readBytes(21).toBuffer());
data.asset = {
test: buf.readInt32(),
};
Expand Down
13 changes: 7 additions & 6 deletions __tests__/unit/crypto/crypto/bip38.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import "jest-extended";

import bs58check from "bs58check";
import { base58 } from "bstring";
import ByteBuffer from "bytebuffer";
import wif from "wif";
import { bip38 } from "../../../../packages/crypto/src/crypto";
import { Address } from "../../../../packages/crypto/src/identities";

import * as errors from "../../../../packages/crypto/src/errors";
import fixtures from "./fixtures/bip38.json";
Expand All @@ -29,7 +30,7 @@ describe("BIP38", () => {
});

it("should throw if compression flag is different than 0xe0 0xc0", () => {
jest.spyOn(bs58check, "decode").mockImplementation(() => {
jest.spyOn(Address, "decodeCheck").mockImplementation(() => {
const byteBuffer = new ByteBuffer(512, true);
byteBuffer.writeUint8(0x01);
byteBuffer.writeUint8(0x42); // type
Expand Down Expand Up @@ -57,7 +58,7 @@ describe("BIP38", () => {
}

it(`should encrypt '${fixture.description}'`, () => {
const buffer = bs58check.decode(fixture.wif);
const buffer = Address.decodeCheck(fixture.wif);
const actual = bip38.encrypt(buffer.slice(1, 33), !!buffer[33], fixture.passphrase);
expect(actual).toEqual(fixture.bip38);
});
Expand Down Expand Up @@ -86,7 +87,7 @@ describe("BIP38", () => {
});

it("should return false if encrypted WIF flag is different than 0xc0 0xe0", () => {
jest.spyOn(bs58check, "decodeUnsafe").mockImplementation(() => {
jest.spyOn(base58, "decode").mockImplementation(() => {
const byteBuffer = new ByteBuffer(512, true);
byteBuffer.writeUint8(0x01);
byteBuffer.writeUint8(0x42); // type
Expand All @@ -106,15 +107,15 @@ describe("BIP38", () => {
});

it("should return false if encrypted EC mult flag is different than 0x24", () => {
jest.spyOn(bs58check, "decodeUnsafe").mockImplementation(() => {
jest.spyOn(base58, "decode").mockImplementation(() => {
const byteBuffer = new ByteBuffer(512, true);
byteBuffer.writeUint8(0x01);
byteBuffer.writeUint8(0x43); // type
byteBuffer.writeUint8(0x01); // flag

const buffer: any = Buffer.from(byteBuffer.flip().toBuffer());
Object.defineProperty(buffer, "length", {
get: jest.fn(() => 39),
get: jest.fn(() => 43),
set: jest.fn(),
});
return buffer;
Expand Down
1 change: 0 additions & 1 deletion packages/core-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"@hapi/boom": "^7.4.2",
"@hapi/joi": "^15.0.3",
"ajv": "^6.10.0",
"bs58check": "^2.1.2",
"dayjs": "^1.8.14",
"delay": "^4.2.0",
"hapi-pagination": "https://github.com/faustbrian/hapi-pagination",
Expand Down
4 changes: 2 additions & 2 deletions packages/core-api/src/formats.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { app } from "@arkecosystem/core-container";
import { Identities } from "@arkecosystem/crypto";
import { Ajv } from "ajv";
import * as bs58check from "bs58check";
import * as ipAddress from "ip";

export const registerFormats = (ajv: Ajv) => {
Expand All @@ -10,7 +10,7 @@ export const registerFormats = (ajv: Ajv) => {
type: "string",
validate: value => {
try {
return bs58check.decode(value)[0] === config.get("network.pubKeyHash");
return Identities.Address.decodeCheck(value)[0] === config.get("network.pubKeyHash");
} catch (e) {
return false;
}
Expand Down
1 change: 0 additions & 1 deletion packages/core-transaction-pool/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"@types/fs-extra": "^7.0.0",
"@types/pluralize": "^0.0.29",
"better-sqlite3": "^5.4.0",
"bs58check": "^2.1.2",
"dayjs": "^1.8.14",
"delay": "^4.2.0",
"fs-extra": "^8.0.1",
Expand Down
3 changes: 1 addition & 2 deletions packages/core-transactions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
"dependencies": {
"@arkecosystem/core-event-emitter": "^2.4.0-next.11",
"@arkecosystem/core-interfaces": "^2.4.0-next.11",
"@arkecosystem/crypto": "^2.4.0-next.11",
"bs58check": "^2.1.2"
"@arkecosystem/crypto": "^2.4.0-next.11"
},
"engines": {
"node": ">=10.x"
Expand Down
5 changes: 2 additions & 3 deletions packages/core-transactions/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Interfaces, Managers } from "@arkecosystem/crypto";
import bs58check from "bs58check";
import { Identities, Interfaces, Managers } from "@arkecosystem/crypto";

export const isRecipientOnActiveNetwork = (transaction: Interfaces.ITransactionData): boolean => {
return bs58check.decode(transaction.recipientId).readUInt8(0) === Managers.configManager.get("network.pubKeyHash");
return Identities.Address.decodeCheck(transaction.recipientId).readUInt8(0) === Managers.configManager.get("network.pubKeyHash");
};
4 changes: 1 addition & 3 deletions packages/crypto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
"bip32": "^2.0.3",
"bip39": "^3.0.2",
"browserify-aes": "^1.2.0",
"bs58": "^4.0.1",
"bs58check": "^2.1.2",
"bstring": "^0.3.9",
"buffer-xor": "^2.0.2",
"bytebuffer": "^5.0.1",
"dayjs": "^1.8.14",
Expand All @@ -53,7 +52,6 @@
"devDependencies": {
"@types/bip32": "^1.0.2",
"@types/bip39": "^2.4.2",
"@types/bs58": "^4.0.0",
"@types/buffer-xor": "^2.0.0",
"@types/bytebuffer": "^5.0.40",
"@types/hapi__joi": "^15.0.1",
Expand Down
17 changes: 11 additions & 6 deletions packages/crypto/src/crypto/bip38.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import assert from "assert";
import { secp256k1 } from "bcrypto";
import aes from "browserify-aes";
import bs58check from "bs58check";
import xor from "buffer-xor/inplace";
import crypto from "crypto";
import { HashAlgorithms } from "../crypto";
Expand All @@ -18,7 +17,7 @@ import {
Bip38TypeError,
PrivateKeyLengthError,
} from "../errors";
import { Keys } from "../identities";
import { Address, Keys } from "../identities";
import { IDecryptResult } from "../interfaces";

const SCRYPT_PARAMS = {
Expand All @@ -40,11 +39,17 @@ const getAddressPrivate = (privateKey: Buffer, compressed: boolean): string => {
payload.writeUInt8(0x00, 0);
buffer.copy(payload, 1);

return bs58check.encode(payload);
return Address.encodeCheck(payload);
};

export const verify = (bip38: string): boolean => {
const decoded = bs58check.decodeUnsafe(bip38);
let decoded: Buffer;
try {
decoded = Address.decodeCheck(bip38);
} catch {
return false;
}

if (!decoded) {
return false;
}
Expand Down Expand Up @@ -228,9 +233,9 @@ const decryptRaw = (buffer: Buffer, passphrase: string): IDecryptResult => {
};

export const encrypt = (privateKey: Buffer, compressed: boolean, passphrase: string): string => {
return bs58check.encode(encryptRaw(privateKey, compressed, passphrase));
return Address.encodeCheck(encryptRaw(privateKey, compressed, passphrase));
};

export const decrypt = (bip38: string, passphrase): IDecryptResult => {
return decryptRaw(bs58check.decode(bip38), passphrase);
return decryptRaw(Address.decodeCheck(bip38), passphrase);
};
23 changes: 20 additions & 3 deletions packages/crypto/src/identities/address.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import bs58check from "bs58check";
import { base58 } from "bstring";
import { HashAlgorithms } from "../crypto";
import { PublicKeyError } from "../errors";
import { IMultiSignatureAsset } from "../interfaces";
Expand All @@ -25,7 +25,7 @@ export class Address {
payload.writeUInt8(networkVersion, 0);
buffer.copy(payload, 1);

return bs58check.encode(payload);
return this.encodeCheck(payload);
}

public static fromMultiSignatureAsset(asset: IMultiSignatureAsset, networkVersion?: number): string {
Expand All @@ -36,13 +36,30 @@ export class Address {
return Address.fromPublicKey(privateKey.publicKey, networkVersion);
}

public static encodeCheck(buffer: Buffer): string {
const checksum: Buffer = HashAlgorithms.hash256(buffer);
return base58.encode(Buffer.concat([buffer, checksum], buffer.length + 4));
}

public static decodeCheck(address: string): Buffer {
const buffer: Buffer = base58.decode(address);
const payload: Buffer = buffer.slice(0, -4);
const checksum: Buffer = HashAlgorithms.hash256(payload);

if (checksum.readUInt32LE(0) !== buffer.slice(-4).readUInt32LE(0)) {
throw new Error("Invalid checksum");
}

return payload;
}

public static validate(address: string, networkVersion?: number): boolean {
if (!networkVersion) {
networkVersion = configManager.get("network.pubKeyHash");
}

try {
return bs58check.decode(address)[0] === networkVersion;
return this.decodeCheck(address)[0] === networkVersion;
} catch (err) {
return false;
}
Expand Down
4 changes: 1 addition & 3 deletions packages/crypto/src/transactions/serializer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/* tslint:disable:no-shadowed-variable */

import bs58check from "bs58check";
import ByteBuffer from "bytebuffer";
import { Utils } from "..";
import { TransactionTypes } from "../enums";
Expand Down Expand Up @@ -122,7 +120,7 @@ export class Serializer {
if (isBrokenTransaction || (transaction.recipientId && transaction.type !== 1 && transaction.type !== 4)) {
const recipientId =
transaction.recipientId || Address.fromPublicKey(transaction.senderPublicKey, transaction.network);
const recipient = bs58check.decode(recipientId);
const recipient = Address.decodeCheck(recipientId);
for (const byte of recipient) {
bb.writeByte(byte);
}
Expand Down
6 changes: 3 additions & 3 deletions packages/crypto/src/transactions/types/ipfs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import bs58 from "bs58";
import { base58 } from "bstring";
import ByteBuffer from "bytebuffer";
import { TransactionTypes } from "../../enums";
import { ISerializeOptions } from "../../interfaces";
Expand All @@ -15,7 +15,7 @@ export class IpfsTransaction extends Transaction {
public serialize(options?: ISerializeOptions): ByteBuffer {
const { data } = this;

const ipfsBuffer: Buffer = bs58.decode(data.asset.ipfs);
const ipfsBuffer: Buffer = base58.decode(data.asset.ipfs);
const buffer: ByteBuffer = new ByteBuffer(ipfsBuffer.length, true);

buffer.append(ipfsBuffer, "hex");
Expand All @@ -36,7 +36,7 @@ export class IpfsTransaction extends Transaction {
buffer.fill(ipfsHash, 2);

data.asset = {
ipfs: bs58.encode(buffer),
ipfs: base58.encode(buffer),
};
}
}
6 changes: 3 additions & 3 deletions packages/crypto/src/transactions/types/multi-payment.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import bs58check from "bs58check";
import ByteBuffer from "bytebuffer";
import { TransactionTypes } from "../../enums";
import { Address } from "../../identities";
import { IMultiPaymentItem, ISerializeOptions } from "../../interfaces";
import { BigNumber } from "../../utils";
import * as schemas from "./schemas";
Expand All @@ -21,7 +21,7 @@ export class MultiPaymentTransaction extends Transaction {

for (const p of data.asset.payments) {
buffer.writeUint64(+BigNumber.make(p.amount).toFixed());
buffer.append(bs58check.decode(p.recipientId));
buffer.append(Address.decodeCheck(p.recipientId));
}

return buffer;
Expand All @@ -35,7 +35,7 @@ export class MultiPaymentTransaction extends Transaction {
for (let j = 0; j < total; j++) {
payments.push({
amount: BigNumber.make(buf.readUint64().toString()),
recipientId: bs58check.encode(buf.readBytes(21).toBuffer()),
recipientId: Address.encodeCheck(buf.readBytes(21).toBuffer()),
});
}

Expand Down
6 changes: 3 additions & 3 deletions packages/crypto/src/transactions/types/timelock-transfer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import bs58check from "bs58check";
import ByteBuffer from "bytebuffer";
import { TransactionTypes } from "../../enums";
import { Address } from "../../identities";
import { ISerializeOptions } from "../../interfaces";
import { BigNumber } from "../../utils";
import * as schemas from "./schemas";
Expand All @@ -20,7 +20,7 @@ export class TimelockTransferTransaction extends Transaction {
buffer.writeUint64(+data.amount.toFixed());
buffer.writeByte(data.timelockType);
buffer.writeUint64(data.timelock);
buffer.append(bs58check.decode(data.recipientId));
buffer.append(Address.decodeCheck(data.recipientId));
return buffer;
}

Expand All @@ -29,6 +29,6 @@ export class TimelockTransferTransaction extends Transaction {
data.amount = BigNumber.make(buf.readUint64().toString());
data.timelockType = buf.readUint8();
data.timelock = buf.readUint64().toNumber();
data.recipientId = bs58check.encode(buf.readBytes(21).toBuffer());
data.recipientId = Address.encodeCheck(buf.readBytes(21).toBuffer());
}
}
6 changes: 3 additions & 3 deletions packages/crypto/src/transactions/types/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import bs58check from "bs58check";
import ByteBuffer from "bytebuffer";
import { TransactionTypes } from "../../enums";
import { Address } from "../../identities";
import { ISerializeOptions } from "../../interfaces";
import { BigNumber } from "../../utils";
import * as schemas from "./schemas";
Expand All @@ -22,7 +22,7 @@ export class TransferTransaction extends Transaction {
const buffer: ByteBuffer = new ByteBuffer(24, true);
buffer.writeUint64(+data.amount);
buffer.writeUint32(data.expiration || 0);
buffer.append(bs58check.decode(data.recipientId));
buffer.append(Address.decodeCheck(data.recipientId));

return buffer;
}
Expand All @@ -31,6 +31,6 @@ export class TransferTransaction extends Transaction {
const { data } = this;
data.amount = BigNumber.make(buf.readUint64().toString());
data.expiration = buf.readUint32();
data.recipientId = bs58check.encode(buf.readBytes(21).toBuffer());
data.recipientId = Address.encodeCheck(buf.readBytes(21).toBuffer());
}
}
Loading