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

Adding an alternative option for browser to generate key pairs (release/21.0.x branch) #749

Merged
merged 4 commits into from
Jun 9, 2020
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
7 changes: 5 additions & 2 deletions src/eosjs-ecc-migration.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import {PrivateKey, PublicKey, Signature} from './eosjs-jssig';
import {generateKeyPair} from './eosjs-key-conversions';
import {KeyType} from './eosjs-numeric';
import {ec as EC} from 'elliptic';

export const ecc = {
initialize: () => console.error('Method deprecated'),
unsafeRandomKey: () => console.error('Method deprecated'),
randomKey: (cpuEntropyBits?: number): Promise<string> => {
randomKey: (
cpuEntropyBits?: number, options: { secureEnv?: boolean, ecOptions?: EC.GenKeyPairOptions } = {}
): Promise<string> => {
if (cpuEntropyBits !== undefined) {
console.warn('Argument `cpuEntropyBits` is deprecated, ' +
'use the options argument instead');
}

const { privateKey } = generateKeyPair(KeyType.k1);
const { privateKey } = generateKeyPair(KeyType.k1, options);
return Promise.resolve(privateKey.toLegacyString());
},
seedPrivate: () => console.error('Method deprecated'),
Expand Down
12 changes: 6 additions & 6 deletions src/eosjs-key-conversions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ export const constructElliptic = (type: KeyType): EC => {
return new EC('p256') as any;
};

export const generateKeyPair = (type: KeyType, options?: EC.GenKeyPairOptions):
export const generateKeyPair = (type: KeyType, options: { secureEnv?: boolean, ecOptions?: EC.GenKeyPairOptions } = {}):
{publicKey: PublicKey, privateKey: PrivateKey} => {
if (process.env.EOSJS_KEYGEN_ALLOWED !== 'true') {
if (!options.secureEnv) {
throw new Error('Key generation is completely INSECURE in production environments in the browser. ' +
'If you are absolutely certain this does NOT describe your environment, add an environment variable ' +
'`EOSJS_KEYGEN_ALLOWED` set to \'true\'. If this does describe your environment and you add the ' +
'environment variable, YOU DO SO AT YOUR OWN RISK AND THE RISK OF YOUR USERS.');
'If you are absolutely certain this does NOT describe your environment, set `secureEnv` in your ' +
'options to `true`. If this does describe your environment and you set `secureEnv` to `true`, ' +
'YOU DO SO AT YOUR OWN RISK AND THE RISK OF YOUR USERS.');
}
let ec;
if (type === KeyType.k1) {
ec = new EC('secp256k1') as any;
} else {
ec = new EC('p256') as any;
}
const ellipticKeyPair = ec.genKeyPair(options);
const ellipticKeyPair = ec.genKeyPair(options.ecOptions);
const publicKey = PublicKey.fromElliptic(ellipticKeyPair, type, ec);
const privateKey = PrivateKey.fromElliptic(ellipticKeyPair, type, ec);
return {publicKey, privateKey};
Expand Down
3 changes: 1 addition & 2 deletions src/tests/eosjs-ecc-migration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ describe('ecc Migration', () => {
});

it('verifies `randomKey` calls generateKeyPair', async () => {
process.env.EOSJS_KEYGEN_ALLOWED = 'true';
console.warn = jest.fn();
const privateKey = await eccMigration.randomKey(0);
const privateKey = await eccMigration.randomKey(0, { secureEnv: true });
expect(console.warn).toHaveBeenCalledWith('Argument `cpuEntropyBits` is deprecated, ' +
'use the options argument instead');
expect(typeof privateKey).toEqual('string');
Expand Down
12 changes: 4 additions & 8 deletions src/tests/eosjs-jssig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,14 @@ describe('JsSignatureProvider', () => {
// These are simplified tests simply to verify a refactor didn't mess with existing code
describe('secp256k1 elliptic', () => {
it('generates a private and public key pair', () => {
process.env.EOSJS_KEYGEN_ALLOWED = 'true';
const {privateKey, publicKey} = generateKeyPair(KeyType.k1);
const {privateKey, publicKey} = generateKeyPair(KeyType.k1, { secureEnv: true });
expect(privateKey).toBeInstanceOf(PrivateKey);
expect(privateKey.isValid()).toBeTruthy();
expect(publicKey).toBeInstanceOf(PublicKey);
expect(publicKey.isValid()).toBeTruthy();
});

it('throws error with no EOSJS_KEYGEN_ALLOWED environment variable', () => {
process.env.EOSJS_KEYGEN_ALLOWED = null;
it('throws error with no options.secureEnv variable', () => {
expect(() => generateKeyPair(KeyType.k1)).toThrowError();
});

Expand Down Expand Up @@ -202,16 +200,14 @@ describe('JsSignatureProvider', () => {

describe('p256 elliptic', () => {
it('generates a private and public key pair', () => {
process.env.EOSJS_KEYGEN_ALLOWED = 'true';
const {privateKey, publicKey} = generateKeyPair(KeyType.r1);
const {privateKey, publicKey} = generateKeyPair(KeyType.r1, { secureEnv: true });
expect(privateKey).toBeInstanceOf(PrivateKey);
expect(privateKey.isValid()).toBeTruthy();
expect(publicKey).toBeInstanceOf(PublicKey);
expect(publicKey.isValid()).toBeTruthy();
});

it('throws error with no EOSJS_KEYGEN_ALLOWED environment variable', () => {
process.env.EOSJS_KEYGEN_ALLOWED = null;
it('throws error with no options.secureEnv variable', () => {
expect(() => generateKeyPair(KeyType.r1)).toThrowError();
});

Expand Down