Skip to content

Commit

Permalink
perf(crypto): replace bs58check with bstring (#2673)
Browse files Browse the repository at this point in the history
  • Loading branch information
spkjp authored and faustbrian committed Jun 8, 2019
1 parent 1209a36 commit 50ded58
Show file tree
Hide file tree
Showing 17 changed files with 76 additions and 63 deletions.
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

0 comments on commit 50ded58

Please sign in to comment.