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

Commit

Permalink
adding optional arg to pass in an ecurve
Browse files Browse the repository at this point in the history
fixed the typing on the key store in SigProvider
integrating PR feedback
relocating default init of ec
further optimizing ec object passing around; removing function from its original location, I already moved
  • Loading branch information
Mike Manfredi committed Oct 15, 2019
1 parent 24a22a9 commit 2b0ca58
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 64 deletions.
18 changes: 9 additions & 9 deletions src/PrivateKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {

/** Represents/stores a private key and provides easy conversion for use with `elliptic` lib */
export class PrivateKey {

constructor(private key: Key) {}

/** Instantiate private key from an `elliptic`-format private key */
Expand All @@ -30,15 +29,16 @@ export class PrivateKey {
}

/** Export private key as `elliptic`-format private key */
public toElliptic() {
/** expensive to construct; so we do it when needed */
let e: ec;
if (this.key.type === KeyType.r1) {
e = new ec('secp256r1') as any;
} else {
e = new ec('secp256k1') as any;
public toElliptic(ecurve?: ec) {
/** expensive to construct; so we do it only as needed */
if (!ecurve) {
if (this.key.type === KeyType.r1) {
ecurve = new ec('secp256r1') as any;
} else {
ecurve = new ec('secp256k1') as any;
}
}
return e.keyFromPrivate(this.key.data);
return ecurve.keyFromPrivate(this.key.data);
}

/** Export private key as EOSIO-format private key */
Expand Down
20 changes: 11 additions & 9 deletions src/PublicKey.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ec, curve } from 'elliptic';
import { ec } from 'elliptic';
import {
Key,
KeyType,
Expand All @@ -8,9 +8,6 @@ import {

/** Represents/stores a public key and provides easy conversion for use with `elliptic` lib */
export class PublicKey {
/** expensive to construct; so we do it once and reuse it */
private e = new ec('secp256k1');

constructor(private key: Key) {}

/** Instantiate public key from an EOSIO-format public key */
Expand All @@ -22,9 +19,6 @@ export class PublicKey {
public static fromElliptic(publicKey: ec.KeyPair, keyType: KeyType = KeyType.k1): PublicKey {
const x = publicKey.getPublic().getX().toArray();
const y = publicKey.getPublic().getY().toArray();
if (!keyType) {
keyType = KeyType.k1;
}
return new PublicKey({
type: keyType,
data: new Uint8Array([(y[31] & 1) ? 3 : 2].concat(x)),
Expand All @@ -37,8 +31,16 @@ export class PublicKey {
}

/** Export public key as `elliptic`-format public key */
public toElliptic(): ec.KeyPair {
return this.e.keyPair({
public toElliptic(ecurve?: ec): ec.KeyPair {
/** expensive to construct; so we do it only as needed */
if (!ecurve) {
if (this.key.type === KeyType.r1) {
ecurve = new ec('secp256r1') as any;
} else {
ecurve = new ec('secp256k1') as any;
}
}
return ecurve.keyPair({
pub: new Buffer(this.key.data),
});
}
Expand Down
14 changes: 10 additions & 4 deletions src/Signature.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import * as EC from 'elliptic';
import { ec } from 'elliptic';
import BN = require('bn.js');

import {
Key,
KeyType,
signatureToString,
stringToSignature,
} from './eosjs-numeric';
import BN = require('bn.js');

/** Represents/stores a Signature and provides easy conversion for use with `elliptic` lib */
export class Signature {
Expand All @@ -18,7 +19,7 @@ export class Signature {
}

/** Instantiate Signature from an `elliptic`-format Signature */
public static fromElliptic(ellipticSig: any): Signature {
public static fromElliptic(ellipticSig: ec.Signature): Signature {
const r = ellipticSig.r.toArray();
const s = ellipticSig.s.toArray();
const sigData = new Uint8Array([ellipticSig.recoveryParam + 27 + 4].concat(r, s));
Expand All @@ -28,7 +29,12 @@ export class Signature {
});
}

/** Export Signature as `elliptic`-format Signature */
/** Export Signature as `elliptic`-format Signature
* NOTE: This isn't an actual elliptic-format Signature, as ec.Signature is not exported by the library.
* That's also why the return type is `any`. We're *actually* returning an object with the 3 params
* not an ec.Signature.
* Further NOTE: @types/elliptic shows ec.Signature as exported; it is *not*. Hence the `any`.
*/
public toElliptic(): any {
const lengthOfR = 32;
const lengthOfS = 32;
Expand Down
1 change: 0 additions & 1 deletion src/eosjs-ecc.d.ts

This file was deleted.

46 changes: 35 additions & 11 deletions src/eosjs-jssig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*/
// copyright defined in eosjs/LICENSE.txt

import { ec } from 'elliptic';

import { SignatureProvider, SignatureProviderArgs } from './eosjs-api-interfaces';
import {
PrivateKey,
Expand All @@ -11,28 +13,42 @@ import {
} from './eosjs-key-conversions';
import {
convertLegacyPublicKey,
digestFromSerializedData,
KeyType,
} from './eosjs-numeric';

import { ec } from 'elliptic';
/** expensive to construct; so we do it once and reuse it */
const defaultEc = new ec('secp256k1') as any;

/** Construct the digest from transaction details */
function digestFromSerializedData(
chainId: string,
serializedTransaction: Uint8Array,
serializedContextFreeData?: Uint8Array,
e = defaultEc) {
const signBuf = Buffer.concat([
new Buffer(chainId, 'hex'),
new Buffer(serializedTransaction),
new Buffer(
serializedContextFreeData ?
new Uint8Array(e.hash(serializedContextFreeData).update(serializedContextFreeData).digest()) :
new Uint8Array(32)
),
]);
return e.hash().update(signBuf).digest();
}

/** Signs transactions using in-process private keys */
export class JsSignatureProvider implements SignatureProvider {
class JsSignatureProvider implements SignatureProvider {
/** map public to private keys */
public keys = new Map<string, string>();
public keys = new Map<string, ec.KeyPair>();

/** public keys */
public availableKeys = [] as string[];

/** expensive to construct; so we do it once and reuse it */
private e = new ec('secp256k1') as any;

/** @param privateKeys private keys to sign with */
constructor(privateKeys: string[]) {
for (const k of privateKeys) {
// What is there to do about this 'as any'?
const priv = PrivateKey.fromString(k).toElliptic() as any;
const priv = PrivateKey.fromString(k).toElliptic(defaultEc);
const pubStr = PublicKey.fromElliptic(priv, KeyType.k1).toString();
this.keys.set(pubStr, priv);
this.availableKeys.push(pubStr);
Expand All @@ -48,11 +64,11 @@ export class JsSignatureProvider implements SignatureProvider {
public async sign(
{ chainId, requiredKeys, serializedTransaction, serializedContextFreeData }: SignatureProviderArgs,
) {
const digest = digestFromSerializedData( chainId, serializedTransaction, serializedContextFreeData, this.e);
const digest = digestFromSerializedData( chainId, serializedTransaction, serializedContextFreeData, defaultEc);

const signatures = [] as string[];
for (const key of requiredKeys) {
const privKey = this.keys.get(convertLegacyPublicKey(key)) as any;
const privKey = this.keys.get(convertLegacyPublicKey(key));
let tries = 0;
let sig: Signature;
const isCanonical = (sigData: Uint8Array) =>
Expand All @@ -70,3 +86,11 @@ export class JsSignatureProvider implements SignatureProvider {
return { signatures, serializedTransaction, serializedContextFreeData };
}
}

export {
PrivateKey,
PublicKey,
Signature,
digestFromSerializedData,
JsSignatureProvider,
};
19 changes: 0 additions & 19 deletions src/eosjs-numeric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/
// copyright defined in eosjs/LICENSE.txt

import { ec } from 'elliptic';
const ripemd160 = require('./ripemd').RIPEMD160.hash as (a: Uint8Array) => ArrayBuffer;

const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
Expand Down Expand Up @@ -266,24 +265,6 @@ export interface Key {
data: Uint8Array;
}

/** Construct the digest from transaction details */
export function digestFromSerializedData(
chainId: string,
serializedTransaction: Uint8Array,
serializedContextFreeData?: Uint8Array,
e = new ec('secp256k1')) {
const signBuf = Buffer.concat([
new Buffer(chainId, 'hex'),
new Buffer(serializedTransaction),
new Buffer(
serializedContextFreeData ?
new Uint8Array(e.hash(serializedContextFreeData).update(serializedContextFreeData).digest()) :
new Uint8Array(32)
),
]);
return e.hash().update(signBuf).digest();
}

function digestSuffixRipemd160(data: Uint8Array, suffix: string) {
const d = new Uint8Array(data.length + suffix.length);
for (let i = 0; i < data.length; ++i) {
Expand Down
27 changes: 17 additions & 10 deletions src/tests/eosjs-jssig.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { JsSignatureProvider } from '../eosjs-jssig';
import { ec } from 'elliptic';

import { Signature, PrivateKey, PublicKey } from '../eosjs-key-conversions';
import { digestFromSerializedData } from '../eosjs-numeric';
import {
JsSignatureProvider,
digestFromSerializedData
} from '../eosjs-jssig';
import { SignatureProviderArgs } from '../eosjs-api-interfaces';

describe('JsSignatureProvider', () => {
const privateKeys = [
Expand Down Expand Up @@ -40,9 +44,10 @@ describe('JsSignatureProvider', () => {
const serializedTransaction = new Uint8Array([
0, 16, 32, 128, 255,
]);
const abis: any[] = [];

const signOutput = await provider.sign({ chainId, requiredKeys, serializedTransaction, abis });
const signOutput = await provider.sign(
{ chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
);

expect(signOutput).toEqual({
signatures,
Expand All @@ -58,12 +63,13 @@ describe('JsSignatureProvider', () => {
const serializedTransaction = new Uint8Array([
0, 16, 32, 128, 255,
]);
const abis: any[] = [];

const signOutput = await provider.sign({ chainId, requiredKeys, serializedTransaction, abis });
const signOutput = await provider.sign(
{ chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
);

const sig = Signature.fromString(signOutput.signatures[0]);
const ellipticSig = sig.toElliptic();
const sig: Signature = Signature.fromString(signOutput.signatures[0]);
const ellipticSig: ec.Signature = sig.toElliptic();
const eosSig = Signature.fromElliptic(ellipticSig);
expect(sig).toEqual(eosSig);
});
Expand All @@ -75,9 +81,10 @@ describe('JsSignatureProvider', () => {
const serializedTransaction = new Uint8Array([
0, 16, 32, 128, 255,
]);
const abis: any[] = [];

const signOutput = await provider.sign({ chainId, requiredKeys, serializedTransaction, abis });
const signOutput = await provider.sign(
{ chainId, requiredKeys, serializedTransaction } as SignatureProviderArgs
);

const EC = new ec('secp256k1');
const ellipticSig = Signature.fromString(signOutput.signatures[0]).toElliptic();
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
},
"include": [
"src/**/*.ts",
"src/**/*.js",
"src/**/*.js"
]
}

0 comments on commit 2b0ca58

Please sign in to comment.