Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Release for 21.0.3 #788

Merged
merged 11 commits into from
Aug 12, 2020
16 changes: 8 additions & 8 deletions docs.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
{
"name": "eosjs",
"generators": [
{
{
"name": "collate_markdown",
"options": {
"docs_dir": "docs"
"options": {
"docs_dir": "docs"
}
},
{
"name": "typedoc",
"options": {
"disable_filters": true
},
"filters": [
{ "name": "remove_extension" }
]
"disable_default_filters": true,
"filters": [
{ "name": "remove_extension" }
]
}
}
]
}
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eosjs",
"version": "21.0.2",
"version": "21.0.3",
"description": "Talk to eos API",
"main": "dist/index.js",
"scripts": {
Expand Down Expand Up @@ -33,18 +33,18 @@
"devDependencies": {
"@blockone/eslint-config-blockone": "^3.0.0",
"@types/elliptic": "^6.4.12",
"@types/jest": "^26.0.4",
"@types/node": "^14.0.23",
"@types/jest": "^26.0.9",
"@types/node": "^14.0.27",
"@types/pako": "^1.0.1",
"cypress": "^4.10.0",
"cypress": "^4.12.1",
"eosjs-ecc": "^4.0.7",
"eslint": "^6.8.0",
"jest": "^26.1.0",
"jest": "^26.3.0",
"jest-fetch-mock": "^3.0.3",
"ts-jest": "^26.1.2",
"ts-jest": "^26.2.0",
"ts-loader": "^7.0.5",
"typescript": "^3.9.6",
"webpack": "^4.43.0",
"typescript": "^3.9.7",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12"
},
"resolutions": {
Expand Down
7 changes: 5 additions & 2 deletions src/PrivateKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ export class PrivateKey {
}

/** Sign a message or hashed message digest with private key */
public sign(data: BNInput, shouldHash: boolean = true, encoding: string = 'utf8'): Signature {
public sign(data: BNInput, shouldHash: boolean = true, encoding: BufferEncoding = 'utf8'): Signature {
if (shouldHash) {
data = this.ec.hash().update(data, encoding).digest();
if (typeof data === 'string') {
data = Buffer.from(data, encoding);
}
data = this.ec.hash().update(data).digest();
}
let tries = 0;
let signature: Signature;
Expand Down
14 changes: 10 additions & 4 deletions src/Signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,25 @@ export class Signature {
}

/** Verify a signature with a message or hashed message digest and public key */
public verify(data: BNInput, publicKey: PublicKey, shouldHash: boolean = true, encoding: string = 'utf8'): boolean {
public verify(data: BNInput, publicKey: PublicKey, shouldHash: boolean = true, encoding: BufferEncoding = 'utf8'): boolean {
if (shouldHash) {
data = this.ec.hash().update(data, encoding).digest();
if (typeof data === 'string') {
data = Buffer.from(data, encoding);
}
data = this.ec.hash().update(data).digest();
}
const ellipticSignature = this.toElliptic();
const ellipticPublicKey = publicKey.toElliptic();
return this.ec.verify(data, ellipticSignature, ellipticPublicKey, encoding);
}

/** Recover a public key from a message or hashed message digest and signature */
public recover(data: BNInput, shouldHash: boolean = true, encoding: string = 'utf8'): PublicKey {
public recover(data: BNInput, shouldHash: boolean = true, encoding: BufferEncoding = 'utf8'): PublicKey {
if (shouldHash) {
data = this.ec.hash().update(data, encoding).digest();
if (typeof data === 'string') {
data = Buffer.from(data, encoding);
}
data = this.ec.hash().update(data).digest();
}
const ellipticSignature = this.toElliptic();
const recoveredPublicKey = this.ec.recoverPubKey(
Expand Down
10 changes: 5 additions & 5 deletions src/eosjs-ecc-migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,29 +49,29 @@ export const ecc = {
return false;
}
},
sign: (data: string|Buffer, privateKey: string|PrivateKey, encoding: string = 'utf8'): string => {
sign: (data: string|Buffer, privateKey: string|PrivateKey, encoding: BufferEncoding = 'utf8'): string => {
const privKey = typeof privateKey === 'string' ? PrivateKey.fromString(privateKey) : privateKey;
const signature = privKey.sign(data, true, encoding);
return signature.toString();
},
signHash: (dataSha256: string|Buffer, privateKey: string|PrivateKey, encoding: string = 'hex') => {
signHash: (dataSha256: string|Buffer, privateKey: string|PrivateKey, encoding: BufferEncoding = 'hex') => {
const privKey = typeof privateKey === 'string' ? PrivateKey.fromString(privateKey) : privateKey;
const signature = privKey.sign(dataSha256, false, encoding);
return signature.toString();
},
verify: (
signature: string, data: string, pubKey: string|PublicKey, encoding: string = 'utf8', hashData: boolean = true
signature: string, data: string, pubKey: string|PublicKey, encoding: BufferEncoding = 'utf8', hashData: boolean = true
): boolean => {
const publicKey = typeof pubKey === 'string' ? PublicKey.fromString(pubKey) : pubKey;
const sig = Signature.fromString(signature);
return sig.verify(data, publicKey, hashData, encoding);
},
recover: (signature: string, data: string, encoding: string = 'utf8'): string => {
recover: (signature: string, data: string, encoding: BufferEncoding = 'utf8'): string => {
const sig = Signature.fromString(signature);
const publicKey = sig.recover(data, true, encoding);
return publicKey.toLegacyString();
},
recoverHash: (signature: string, dataSha256: string|Buffer, encoding: string = 'hex'): string => {
recoverHash: (signature: string, dataSha256: string|Buffer, encoding: BufferEncoding = 'hex'): string => {
const sig = Signature.fromString(signature);
const publicKey = sig.recover(dataSha256, false, encoding);
return publicKey.toLegacyString();
Expand Down
20 changes: 10 additions & 10 deletions src/tests/eosjs-ecc-migration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,35 +91,35 @@ describe('ecc Migration', () => {

it('verifies `sign`, `recover`, and `verify` functions are consistent between ecc objects', () => {
const dataAsString = 'some string';
const eccSig = ecc.sign(dataAsString, privateKeys[0]);
const eccMigrationSig = eccMigration.sign(dataAsString, privateKeys[0]);
const eccSig = ecc.sign(dataAsString, privateKeys[0], 'utf8');
const eccMigrationSig = eccMigration.sign(dataAsString, privateKeys[0], 'utf8');

// signatures are different
expect(eccSig).not.toEqual(eccMigrationSig);

const eccKPub = ecc.recover(eccSig, dataAsString);
const eccMigrationKPub = eccMigration.recover(eccMigrationSig, dataAsString);
const eccKPub = ecc.recover(eccSig, dataAsString, 'utf8');
const eccMigrationKPub = eccMigration.recover(eccMigrationSig, dataAsString, 'utf8');
expect(eccKPub).toEqual(eccMigrationKPub);
});

it('verifies `signHash`, `recoverHash`, and `sha256` functions are consistent between ecc objects', () => {
console.warn = jest.fn();
const dataAsString = 'some string';

const eccHash = Buffer.from(ecc.sha256(dataAsString, 'hex', 'utf8'), 'hex');
const eccMigrationHash = Buffer.from(eccMigration.sha256(dataAsString, 'hex', 'utf8') as Buffer);
const eccHash = Buffer.from(ecc.sha256(dataAsString), 'hex');
const eccMigrationHash = Buffer.from(eccMigration.sha256(dataAsString, 'hex', 'utf8') as string, 'hex');
expect(console.warn).toBeCalledWith('Argument `encoding` is deprecated');
expect(console.warn).toBeCalledWith('Argument `resultEncoding` is deprecated');
expect(eccHash).toEqual(eccMigrationHash);

const eccSig = ecc.signHash(eccHash, privateKeys[0]);
const eccMigrationSig = eccMigration.signHash(eccMigrationHash, privateKeys[0]);
const eccSig = ecc.signHash(eccHash, privateKeys[0], 'utf8');
const eccMigrationSig = eccMigration.signHash(eccMigrationHash, privateKeys[0], 'utf8');

// signatures are different
expect(eccSig).not.toEqual(eccMigrationSig);

const eccKPub = ecc.recoverHash(eccSig, eccHash);
const eccMigrationKPub = eccMigration.recoverHash(eccSig, eccMigrationHash);
const eccKPub = ecc.recoverHash(eccSig, eccHash, 'utf8');
const eccMigrationKPub = eccMigration.recoverHash(eccSig, eccMigrationHash, 'utf8');
expect(eccKPub).toEqual(eccMigrationKPub);
});
});
82 changes: 67 additions & 15 deletions src/tests/eosjs-ecc-verification.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const ecc = require('eosjs-ecc');

const { ec } = require('elliptic');

const { Signature, PrivateKey, PublicKey } = require('../eosjs-key-conversions');
const { Signature, PrivateKey, PublicKey, sha256 } = require('../eosjs-key-conversions');
const {
JsSignatureProvider,
} = require('../eosjs-jssig');
Expand Down Expand Up @@ -52,23 +52,25 @@ describe('JsSignatureProvider', () => {
const ellipticHashedStringAsBuffer = Buffer.from(ellipticEc.hash().update(dataAsString).digest(), 'hex');
expect(eccHashedString).toEqual(ellipticHashedStringAsBuffer);

const eccSig = ecc.sign(dataAsString, KPriv);
const ellipticSig = KPrivElliptic.sign(ellipticHashedStringAsBuffer);
const eccSig = ecc.sign(dataAsString, KPriv, 'utf8');
const ellipticSig = KPrivElliptic.sign(ellipticHashedStringAsBuffer, 'utf8');

const eccKPub = ecc.recover(eccSig, dataAsString);
const eccKPub = ecc.recover(eccSig, dataAsString, 'utf8');
const ellipticRecoveredKPub = ellipticEc.recoverPubKey(
ellipticHashedStringAsBuffer,
ellipticSig,
ellipticSig.recoveryParam
ellipticSig.recoveryParam,
'utf8'
);
const ellipticKPub = ellipticEc.keyFromPublic(ellipticRecoveredKPub);
expect(PublicKey.fromElliptic(ellipticKPub, KeyType.k1).toString()).toEqual(k1FormatPublicKeys[idx]);

const eccValid = ecc.verify(eccSig, dataAsString, eccKPub);
const eccValid = ecc.verify(eccSig, dataAsString, eccKPub, 'utf8');
const ellipticValid = ellipticEc.verify(
ellipticHashedStringAsBuffer,
ellipticSig,
ellipticEc.keyFromPublic(ellipticKPub)
ellipticEc.keyFromPublic(ellipticKPub),
'utf8'
);
expect(eccValid).toEqual(true);
expect(ellipticValid).toEqual(true);
Expand All @@ -88,14 +90,15 @@ describe('JsSignatureProvider', () => {
const ellipticHashedStringAsBuffer = Buffer.from(ellipticEc.hash().update(dataAsString).digest(), 'hex');
expect(eccHashedString).toEqual(ellipticHashedStringAsBuffer);

const eccSig = ecc.sign(dataAsString, KPriv);
const eccSig = ecc.sign(dataAsString, KPriv, 'utf8');

const ellipticSig = Signature.fromString(eccSig).toElliptic();
const recoveredKPub = ecc.recover(eccSig, dataAsString);
const recoveredKPub = ecc.recover(eccSig, dataAsString, 'utf8');
const ellipticRecoveredKPub = ellipticEc.recoverPubKey(
ellipticHashedStringAsBuffer,
ellipticSig,
ellipticSig.recoveryParam
ellipticSig.recoveryParam,
'utf8'
);

const ellipticKPub = ellipticEc.keyFromPublic(ellipticRecoveredKPub);
Expand All @@ -105,7 +108,8 @@ describe('JsSignatureProvider', () => {
const ellipticValid = ellipticEc.verify(
ellipticHashedStringAsBuffer,
ellipticSig,
ellipticEc.keyFromPublic(ellipticKPub)
ellipticEc.keyFromPublic(ellipticKPub),
'utf8'
);
expect(ellipticValid).toEqual(true);
}
Expand All @@ -122,19 +126,67 @@ describe('JsSignatureProvider', () => {

const ellipticHashedStringAsBuffer = Buffer.from(ellipticEc.hash().update(dataAsString).digest(), 'hex');

const ellipticSig = KPrivElliptic.sign(ellipticHashedStringAsBuffer);
const ellipticSig = KPrivElliptic.sign(ellipticHashedStringAsBuffer, 'utf8');
const ellipticSigAsString = Signature.fromElliptic(ellipticSig, KeyType.k1).toString();

const recoveredKPub = ecc.recover(ellipticSigAsString, dataAsString);
const recoveredKPub = ecc.recover(ellipticSigAsString, dataAsString, 'utf8');
const ellipticRecoveredKPub = ellipticEc.recoverPubKey(
ellipticHashedStringAsBuffer,
ellipticSig,
ellipticSig.recoveryParam
ellipticSig.recoveryParam,
'utf8'
);
const ellipticKPub = ellipticEc.keyFromPublic(ellipticRecoveredKPub);
expect(PublicKey.fromElliptic(ellipticKPub, KeyType.k1).toString()).toEqual(k1FormatPublicKeys[idx]);

const eccValid = ecc.verify(ellipticSigAsString, dataAsString, recoveredKPub);
const eccValid = ecc.verify(ellipticSigAsString, dataAsString, recoveredKPub, 'utf8');
expect(eccValid).toEqual(true);
}
});

it('ensure eosjs verifies eosjs-ecc\'s Sigs', () => {
for (let idx=0; idx<privateKeys.length; idx++) {
const KPriv = privateKeys[idx];
const privateKey = PrivateKey.fromString(KPriv);

const dataAsString = 'some string';

const eccHashedString = Buffer.from(ecc.sha256(dataAsString), 'hex');
const eosjsHashedStringAsBuffer = Buffer.from(sha256(dataAsString), 'hex');
expect(eccHashedString).toEqual(eosjsHashedStringAsBuffer);

const eccSig = ecc.sign(dataAsString, KPriv, 'utf8');

const eosjsSig = Signature.fromString(eccSig);
const recoveredKPub = ecc.recover(eccSig, dataAsString, 'utf8');
const eosjsRecoveredKPub = eosjsSig.recover(dataAsString, true, 'utf8');

expect(eosjsRecoveredKPub.toLegacyString()).toEqual(recoveredKPub);
expect(eosjsRecoveredKPub.toString()).toEqual(k1FormatPublicKeys[idx]);

const eosjsValid = eosjsSig.verify(dataAsString, eosjsRecoveredKPub, true, 'utf8');
expect(eosjsValid).toEqual(true);
}
});

it('ensure ecc verifies eosjs\'s Sigs', () => {
for (let idx=0; idx<privateKeys.length; idx++) {
const KPriv = privateKeys[idx];
const privateKey = PrivateKey.fromString(KPriv);

const dataAsString = 'some string';

const eosjsHashedStringAsBuffer = Buffer.from(sha256(dataAsString), 'hex');

const eosjsSig = privateKey.sign(eosjsHashedStringAsBuffer, false, 'utf8');
const eosjsSigAsString = eosjsSig.toString();

const recoveredKPub = ecc.recover(eosjsSigAsString, dataAsString, 'utf8');
const eosjsRecoveredKPub = eosjsSig.recover(dataAsString, true, 'utf8');
expect(eosjsRecoveredKPub.toLegacyString()).toEqual(recoveredKPub);
expect(eosjsRecoveredKPub.toString()).toEqual(k1FormatPublicKeys[idx]);

const eccValid = ecc.verify(eosjsSigAsString, dataAsString, recoveredKPub, 'utf8');
expect(eccValid).toEqual(true);
}
});
Expand Down
26 changes: 26 additions & 0 deletions src/tests/eosjs-jssig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,19 @@ describe('JsSignatureProvider', () => {
const valid = sig.verify(dataAsString, KPub, true);
expect(valid).toEqual(true);
});

it('Ensure elliptic sign, recover, verify flow works with shouldHash and encoding', () => {
const KPrivStr = privateKeys[0];
const KPriv = PrivateKey.fromString(KPrivStr);

const dataAsString = 'some string';
const sig = KPriv.sign(dataAsString, true, 'utf8');
const KPub = sig.recover(dataAsString, true, 'utf8');

expect(KPub.toString()).toEqual(k1FormatPublicKeys[0]);
const valid = sig.verify(dataAsString, KPub, true, 'utf8');
expect(valid).toEqual(true);
});
});

describe('p256 elliptic', () => {
Expand Down Expand Up @@ -338,5 +351,18 @@ describe('JsSignatureProvider', () => {
const valid = sig.verify(dataAsString, KPub, true);
expect(valid).toEqual(true);
});

it('Ensure elliptic sign, recover, verify flow works with shouldHash and encoding', () => {
const KPrivStr = privateKeysR1[0];
const KPriv = PrivateKey.fromString(KPrivStr);

const dataAsString = 'some string';
const sig = KPriv.sign(dataAsString, true, 'utf8');
const KPub = sig.recover(dataAsString, true, 'utf8');

expect(KPub.toString()).toEqual(r1FormatPublicKeys[0]);
const valid = sig.verify(dataAsString, KPub, true, 'utf8');
expect(valid).toEqual(true);
});
});
});
Loading