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

[BAC-1383] WIP: Support c++ implementations of crypto operations #55

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ module.exports = {
'newline-per-chained-call': 'off',
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': 'error',
'import/named': 'off', // Not working for `export * as x from '...';`
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,30 @@
*/

import BN from 'bn.js';
import elliptic from 'elliptic';
import expect from 'expect';

import {
pedersen,
sign,
verify,
} from '../../src/lib/starkex-resources';
import {
setGlobalStarkHashImplementation,
setGlobalStarkSigningImplementation,
setGlobalStarkVerificationImplementation,
} from '../../src/signable/crypto';
import { SignatureStruct } from '../../src/types';
} from '../../../src/lib/crypto/proxies';
import {
cryptoJs,
} from '../../../src/lib/crypto';
import { PublicKeyStruct, SignatureStruct } from '../../../src/types';

describe('Cryptographic function wrappers for STARK signable objects', () => {

it('allows setting the hash function implementation', async () => {
await setGlobalStarkHashImplementation(pedersen);
await setGlobalStarkHashImplementation(cryptoJs.pedersen);
});

it('allows setting the signing function implementation', async () => {
await setGlobalStarkSigningImplementation(sign);
await setGlobalStarkSigningImplementation(cryptoJs.sign);
});

it('allows setting the verification function implementation', async () => {
await setGlobalStarkVerificationImplementation(verify);
await setGlobalStarkVerificationImplementation(cryptoJs.verify);
});

it('throws if invalid hash function provided', async () => {
Expand All @@ -43,26 +40,26 @@ describe('Cryptographic function wrappers for STARK signable objects', () => {
it('throws if invalid signing function provided', async () => {
await expect(
setGlobalStarkSigningImplementation(
(_key: elliptic.ec.KeyPair, _message: BN) => ({
r: new BN(1),
s: new BN(2),
}) as elliptic.ec.Signature,
(_key: string, _message: BN) => ({
r: '0x1',
s: '0x2',
}),
),
).rejects.toThrow('Sanity check failed');
});

it('throws if invalid verification function provided (returning false)', async () => {
await expect(
setGlobalStarkVerificationImplementation(
(_key: elliptic.ec.KeyPair, _message: BN, _signature: SignatureStruct) => false,
(_key: string | PublicKeyStruct, _message: BN, _signature: SignatureStruct) => false,
),
).rejects.toThrow('Sanity check failed');
});

it('throws if invalid verification function provided (returning true)', async () => {
await expect(
setGlobalStarkVerificationImplementation(
(_key: elliptic.ec.KeyPair, _message: BN, _signature: SignatureStruct) => true,
(_key: string | PublicKeyStruct, _message: BN, _signature: SignatureStruct) => true,
),
).rejects.toThrow('Sanity check failed');
});
Expand Down
18 changes: 10 additions & 8 deletions __tests__/signable/hashes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import expect from 'expect';
import proxyquire from 'proxyquire';
import sinon from 'sinon';

import { pedersen } from '../../src/lib/starkex-resources';
import * as cryptoModule from '../../src/lib/crypto';
import { cryptoJs } from '../../src/lib/starkware';
import {
SignableConditionalTransfer as SignableConditionalTransferOrig,
} from '../../src/signable/conditional-transfer';
import * as cryptoModule from '../../src/signable/crypto';
import * as hashesModule from '../../src/signable/hashes';
import {
SignableOrder as SignableOrderOrig,
Expand Down Expand Up @@ -75,17 +75,19 @@ describe('Pedersen hashes', () => {

beforeEach(() => {
// Reload the hashes module fresh each time, resetting the cache.
mockPedersen = sinon.spy(pedersen);
proxyquiredCrypto = proxyquire('../../src/signable/crypto', {
'../lib/starkex-resources': {
pedersen: mockPedersen,
mockPedersen = sinon.spy(cryptoJs.pedersen);
proxyquiredCrypto = proxyquire('../../src/lib/crypto/proxies', {
'./crypto-js-wrappers': {
cryptoJs: {
pedersen: mockPedersen,
},
},
});
proxyquiredHashes = proxyquire('../../src/signable/hashes', {
'./crypto': proxyquiredCrypto,
'../lib/crypto': proxyquiredCrypto,
});
mocks = {
'./crypto': proxyquiredCrypto,
'../lib/crypto': proxyquiredCrypto,
'./hashes': proxyquiredHashes,
};
});
Expand Down
116 changes: 113 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,16 @@
"@types/big.js": "6.0.0",
"@types/elliptic": "^6.4.12",
"big.js": "6.0.3",
"bigint-buffer": "^1.1.5",
"bip39": "^3.0.3",
"bn.js": "5.1.3",
"ethereum-cryptography": "^0.1.3",
"ffi-napi": "^4.0.1",
"hash.js": "^1.1.7"
},
"devDependencies": {
"@dydxprotocol/node-service-base-dev": "0.0.11",
"@types/ffi-napi": "^2.4.3",
"@types/proxyquire": "^1.3.28",
"@types/sinon": "^9.0.10",
"expect": "^26.6.2",
Expand Down
20 changes: 17 additions & 3 deletions src/helpers/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import elliptic from 'elliptic';

import { starkEc } from '../lib/starkex-resources';
import { starkEc } from '../lib/starkware';
import {
bnToHex32,
normalizeHex32,
Expand Down Expand Up @@ -69,7 +69,7 @@ export function asEcKeyPairPublic(
/**
* Converts an `elliptic` KeyPair object to a simple object with publicKey & privateKey hex strings.
*
* Returns hex strings without 0x prefix.
* Returns keys as 32-byte hex strings without 0x prefix.
*/
export function asSimpleKeyPair(
ecKeyPair: elliptic.ec.KeyPair,
Expand All @@ -86,10 +86,24 @@ export function asSimpleKeyPair(
};
}

/**
* Converts an `elliptic` Signature object to a simple object with r & s hex strings.
*
* Returns r and s as 32-byte hex strings without 0x prefix.
*/
export function asSimpleSignature(
ecSignature: elliptic.ec.Signature,
): SignatureStruct {
return {
r: bnToHex32(ecSignature.r),
s: bnToHex32(ecSignature.s),
};
}

/**
* Converts an `elliptic` BasePoint object to a compressed representation: the x-coordinate as hex.
*
* Returns a hex string without 0x prefix.
* Returns a 32-byte hex string without 0x prefix.
*/
export function asSimplePublicKey(
ecPublicKey: elliptic.curve.base.BasePoint,
Expand Down
18 changes: 17 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
export * from './constants';
export * from './helpers';
export * from './keys';
export * from './lib';
export {
cryptoCpp,
cryptoJs,
setGlobalStarkHashImplementationNoSanityCheck,
setGlobalStarkSigningImplementationNoSanityCheck,
setGlobalStarkVerificationImplementationNoSanityCheck,
setGlobalStarkHashImplementation,
setGlobalStarkSigningImplementation,
setGlobalStarkVerificationImplementation,
} from './lib/crypto';
export {
starkEc,
} from './lib/starkware';
export {
factToCondition,
normalizeHex32,
} from './lib/util';
export * from './signable';
export * from './types';
Loading