Skip to content

Commit

Permalink
fix: p-460 bitcore message signature issue (#2553)
Browse files Browse the repository at this point in the history
* debug:check idGraph with aliceBitcoinIdentity

* fmt

* fix bitcore signmessage issue

* remove log && uncomment

* modify bitcore sign message logic

* switch to bitcoinjs lib

* del unused deps

* try 2000 tests

* fmt

* complete tests

* fmt one more

* pnpm-lock file

* pass ci

* Uncomment karat_dao test

* rollback handleVcEvents

* uncomment one more

* fix comments
  • Loading branch information
0xverin committed Mar 8, 2024
1 parent 61efd7b commit 744bc85
Show file tree
Hide file tree
Showing 14 changed files with 319 additions and 54 deletions.
7 changes: 3 additions & 4 deletions tee-worker/ts-tests/integration-tests/common/common-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { Metadata, TypeRegistry } from '@polkadot/types';
import { Wallet } from 'ethers';
import type { KeyringPair } from '@polkadot/keyring/types';
import type { HexString } from '@polkadot/util/types';
import bitcore from 'bitcore-lib';

import { ECPairInterface } from 'ecpair';
// If there are types already defined in the client-api, please avoid redefining these types.
// Instead, make every effort to use the types that have been generated within the client-api.
interface EthersWalletItem {
Expand All @@ -16,7 +15,7 @@ interface SubstrateWalletItem {
[key: string]: KeyringPair;
}
interface BitcoinWalletItem {
[key: string]: bitcore.PrivateKey;
[key: string]: ECPairInterface;
}
export type IntegrationTestContext = {
tee: WebSocketAsPromised;
Expand All @@ -35,7 +34,7 @@ export type IntegrationTestContext = {
export type Web3Wallets = {
substrateWallet: KeyringPair;
evmWallet: Wallet;
bitcoinWallet: bitcore.PrivateKey;
bitcoinWallet: ECPairInterface;
};

export type JsonRpcRequest = {
Expand Down
2 changes: 2 additions & 0 deletions tee-worker/ts-tests/integration-tests/common/di-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export const createSignedTrustedGetter = async (
let signature;
if (signer.type() === 'bitcoin') {
const payloadStr = u8aToHex(payload).substring(2);

signature = parachainApi.createType('LitentryMultiSignature', {
[signer.type()]: u8aToHex(await signer.sign(payloadStr)),
});
Expand All @@ -130,6 +131,7 @@ export const createSignedTrustedGetter = async (
[signer.type()]: u8aToHex(await signer.sign(payload)),
});
}

return parachainApi.createType('TrustedGetterSigned', {
getter: getter,
signature: signature,
Expand Down
9 changes: 8 additions & 1 deletion tee-worker/ts-tests/integration-tests/common/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import type { HexString } from '@polkadot/util/types';
import './config';
import { IntegrationTestContext, JsonRpcRequest } from './common-types';
import { randomBytes } from 'crypto';

import { ECPairFactory, ECPairInterface } from 'ecpair';
import * as ecc from 'tiny-secp256k1';
// format and setup
const keyring = new Keyring({ type: 'sr25519' });
export function getSubstrateSigner(): {
Expand Down Expand Up @@ -77,3 +78,9 @@ export function randomSubstrateWallet(): KeyringPair {
const keyring = new Keyring({ type: 'sr25519' });
return keyring.addFromSeed(randomBytes(32));
}

export function randomBitcoinWallet(): ECPairInterface {
const ecPair = ECPairFactory(ecc);
const keyPair = ecPair.makeRandom();
return keyPair;
}
9 changes: 4 additions & 5 deletions tee-worker/ts-tests/integration-tests/common/utils/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import type { IntegrationTestContext, Web3Wallets } from '../common-types';
import { identity, vc, trusted_operations, sidechain } from 'parachain-api';
import crypto from 'crypto';
import type { HexString } from '@polkadot/util/types';
import bitcore from 'bitcore-lib';

import { randomBitcoinWallet } from '../helpers';
// maximum block number that we wait in listening events before we timeout
export const defaultListenTimeoutInBlockNumber = 15;

Expand Down Expand Up @@ -49,8 +48,8 @@ export async function initIntegrationTestContext(
const substrateWallet = getSubstrateSigner();

const bitcoinWallet = {
alice: new bitcore.PrivateKey(),
bob: new bitcore.PrivateKey(),
alice: randomBitcoinWallet(),
bob: randomBitcoinWallet(),
};

const types = { ...identity.types, ...vc.types, ...trusted_operations.types, ...sidechain.types };
Expand Down Expand Up @@ -118,7 +117,7 @@ export async function generateWeb3Wallets(count: number): Promise<Web3Wallets[]>
for (let i = 0; i < count; i++) {
const substratePair = keyring.addFromUri(`${seed}//${i}`);
const evmWallet = ethers.Wallet.createRandom();
const bitcoinPair = new bitcore.PrivateKey();
const bitcoinPair = randomBitcoinWallet();
addresses.push({
substrateWallet: substratePair,
evmWallet: evmWallet,
Expand Down
15 changes: 8 additions & 7 deletions tee-worker/ts-tests/integration-tests/common/utils/crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import crypto from 'crypto';
import { KeyringPair } from '@polkadot/keyring/types';
import { ethers } from 'ethers';
import { blake2AsU8a } from '@polkadot/util-crypto';
import bitcore from 'bitcore-lib';
import { IntegrationTestContext } from './../common-types';
import { buildIdentityHelper } from './identity-helper';

import { ECPairInterface } from 'ecpair';
import * as bitcoinMessage from 'bitcoinjs-message';
export type KeypairType = 'ed25519' | 'sr25519' | 'ecdsa' | 'ethereum' | 'bitcoin';

export function encryptWithTeeShieldingKey(teeShieldingKey: KeyObject, plaintext: Uint8Array): Buffer {
Expand Down Expand Up @@ -131,21 +131,22 @@ export class EthersSigner implements Signer {
}

export class BitcoinSigner implements Signer {
keypair: bitcore.PrivateKey;
keypair: ECPairInterface;

constructor(keypair: bitcore.PrivateKey) {
constructor(keypair: ECPairInterface) {
this.keypair = keypair;
}

getAddressRaw(): Uint8Array {
return bufferToU8a(this.keypair.toPublicKey().toBuffer());
return bufferToU8a(this.keypair.publicKey);
}

sign(message: HexString | string | Uint8Array): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
if (isString(message)) {
const sig = new bitcore.Message(message).sign(this.keypair);
resolve(bufferToU8a(Buffer.from(sig, 'base64')));
// produce deterministic signatures
const sig = bitcoinMessage.sign(message, this.keypair.privateKey!, this.keypair.compressed);
resolve(sig);
} else {
reject('wrong message type');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import type { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from
import type { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types';
import type { KeyringPair } from '@polkadot/keyring/types';
import type { HexString } from '@polkadot/util/types';
import { bufferToU8a } from '@polkadot/util';
import bitcore from 'bitcore-lib';
import { ECPairInterface } from 'ecpair';
import * as bitcoinMessage from 'bitcoinjs-message';

// blake2_256(<sidechain nonce> + <primary AccountId> + <identity-to-be-linked>)
export function generateVerificationMessage(
Expand Down Expand Up @@ -151,11 +151,11 @@ export async function buildValidations(
network: 'ethereum' | 'substrate' | 'twitter' | 'bitcoin' | 'bitcoinPrettified',
substrateSigners?: KeyringPair[] | KeyringPair,
evmSigners?: ethers.Wallet[],
bitcoinSigners?: bitcore.PrivateKey[] | bitcore.PrivateKey
bitcoinSigners?: ECPairInterface[] | ECPairInterface
): Promise<LitentryValidationData[]> {
let evmSignature: HexString;
let substrateSignature: Uint8Array;
let bitcoinSignature: Uint8Array;
let bitcoinSignature: Buffer;
const validations: LitentryValidationData[] = [];

for (let index = 0; index < identities.length; index++) {
Expand Down Expand Up @@ -221,11 +221,14 @@ export async function buildValidations(
bitcoinValidationData.Web3Validation.Bitcoin.message = msg;
const bitcoinSigner = Array.isArray(bitcoinSigners!) ? bitcoinSigners![index] : bitcoinSigners!;
// we need to sign the hex string without `0x` prefix, the signature is base64-encoded string
const sig = new bitcore.Message(msg.substring(2)).sign(bitcoinSigner);
bitcoinSignature = bufferToU8a(Buffer.from(sig, 'base64'));
bitcoinSignature = bitcoinMessage.sign(
msg.substring(2),
bitcoinSigner.privateKey!,
bitcoinSigner.compressed
);
bitcoinValidationData!.Web3Validation.Bitcoin.signature.Bitcoin = u8aToHex(bitcoinSignature);
console.log('bitcoin pubkey: ', u8aToHex(bufferToU8a(bitcoinSigner.toPublicKey().toBuffer())));
console.log('bitcoin sig (base64): ', sig);
console.log('bitcoin pubkey: ', `0x${bitcoinSigner.publicKey.toString('hex')}`);
console.log('bitcoin sig (base64): ', bitcoinSignature.toString('base64'));
console.log('bitcoin sig (hex): ', u8aToHex(bitcoinSignature));
const encodedVerifyIdentityValidation: LitentryValidationData = context.api.createType(
'LitentryValidationData',
Expand All @@ -246,11 +249,16 @@ export async function buildValidations(
console.log('post verification msg to bitcoin: ', msg);
bitcoinValidationData.Web3Validation.Bitcoin.message = msg;
const bitcoinSigner = Array.isArray(bitcoinSigners!) ? bitcoinSigners![index] : bitcoinSigners!;
const sig = new bitcore.Message('Litentry authorization token: ' + msg).sign(bitcoinSigner);
bitcoinSignature = bufferToU8a(Buffer.from(sig, 'base64'));
bitcoinSignature = bitcoinMessage.sign(
'Litentry authorization token: ' + msg,
bitcoinSigner.privateKey!,
bitcoinSigner.compressed
);

bitcoinValidationData!.Web3Validation.Bitcoin.signature.BitcoinPrettified = u8aToHex(bitcoinSignature);
console.log('bitcoin pubkey: ', u8aToHex(bufferToU8a(bitcoinSigner.toPublicKey().toBuffer())));
console.log('bitcoin sig (base64): ', sig);
console.log('bitcoin pubkey: ', `0x${bitcoinSigner.publicKey.toString('hex')}`);

console.log('bitcoin sig (base64): ', bitcoinSignature.toString('base64'));
console.log('bitcoin sig (hex): ', u8aToHex(bitcoinSignature));
const encodedVerifyIdentityValidation: LitentryValidationData = context.api.createType(
'LitentryValidationData',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export const mockAssertions = [
EVMAmountHolding: 'Ton',
},
},
//karat_dao

{
description: 'You are a user of a certain platform',
assertion: {
Expand Down
3 changes: 2 additions & 1 deletion tee-worker/ts-tests/integration-tests/data-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import {
createSignedTrustedCallRequestVc,
} from './common/di-utils'; // @fixme move to a better place
import type { IntegrationTestContext } from './common/common-types';
import { CorePrimitivesIdentity, RequestVCResult } from 'parachain-api';
import { CorePrimitivesIdentity } from 'parachain-api';
import { aesKey } from './common/call';
import { $ as zx } from 'zx';
import { subscribeToEventsWithExtHash } from './common/transactions';
import { KeyringPair } from '@polkadot/keyring/types';
import { u8aToHex } from '@polkadot/util';
import { CredentialDefinition, credentialsJson } from './common/credential-json';

describe('Test Vc (direct invocation)', function () {
let context: IntegrationTestContext = undefined as any;
let teeShieldingKey: KeyObject = undefined as any;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { randomBytes, KeyObject } from 'crypto';
import { step } from 'mocha-steps';
import { assert } from 'chai';
import { u8aToHex, bufferToU8a } from '@polkadot/util';
import {
buildIdentityFromKeypair,
buildIdentityHelper,
Expand Down Expand Up @@ -29,7 +28,7 @@ import { aesKey } from './common/call';
import { LitentryValidationData, Web3Network, CorePrimitivesIdentity } from 'parachain-api';
import { Bytes, Vec } from '@polkadot/types';
import { subscribeToEventsWithExtHash } from './common/transactions';

import { u8aToHex } from '@polkadot/util';
describe('Test Identity (bitcoin direct invocation)', function () {
let context: IntegrationTestContext = undefined as any;
let teeShieldingKey: KeyObject = undefined as any;
Expand Down Expand Up @@ -66,13 +65,13 @@ describe('Test Identity (bitcoin direct invocation)', function () {
);
teeShieldingKey = await getTeeShieldingKey(context);
aliceBitcoinIdentity = await buildIdentityHelper(
u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())),
u8aToHex(context.bitcoinWallet.alice.publicKey),
'Bitcoin',
context
);
aliceEvmIdentity = await buildIdentityFromKeypair(new EthersSigner(context.ethersWallet.alice), context);
bobBitcoinIdentity = await buildIdentityHelper(
u8aToHex(bufferToU8a(context.bitcoinWallet.bob.toPublicKey().toBuffer())),
u8aToHex(context.bitcoinWallet.bob.publicKey),
'Bitcoin',
context
);
Expand Down Expand Up @@ -158,6 +157,7 @@ describe('Test Identity (bitcoin direct invocation)', function () {
);

const res = await sendRequestFromTrustedCall(context, teeShieldingKey, linkIdentityCall);

idGraphHashResults.push(
await assertIdGraphMutationResult(
context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ describe('Test Identity (direct invocation)', function () {

const bitcoinNonce = getNextNonce();
const bitcoinIdentity = await buildIdentityHelper(
u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())),
u8aToHex(context.bitcoinWallet.alice.publicKey),
'Bitcoin',
context
);
Expand Down Expand Up @@ -466,7 +466,7 @@ describe('Test Identity (direct invocation)', function () {

const bitcoinNonce = getNextNonce();
const bitcoinIdentity = await buildIdentityHelper(
u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())),
u8aToHex(context.bitcoinWallet.alice.publicKey),
'Bitcoin',
context
);
Expand Down Expand Up @@ -595,7 +595,7 @@ describe('Test Identity (direct invocation)', function () {

const bitcoinNonce = getNextNonce();
const bitcoinIdentity = await buildIdentityHelper(
u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())),
u8aToHex(context.bitcoinWallet.alice.publicKey),
'Bitcoin',
context
);
Expand Down
4 changes: 2 additions & 2 deletions tee-worker/ts-tests/integration-tests/di_vc.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { randomBytes, KeyObject } from 'crypto';
import { step } from 'mocha-steps';
import { assert } from 'chai';
import { u8aToHex, bufferToU8a } from '@polkadot/util';
import { buildIdentityFromKeypair, initIntegrationTestContext, PolkadotSigner } from './common/utils';
import { assertIsInSidechainBlock, assertVc } from './common/utils/assertion';
import {
Expand All @@ -19,6 +18,7 @@ import { subscribeToEventsWithExtHash } from './common/transactions';
import { mockAssertions } from './common/utils/vc-helper';
import { LitentryValidationData, Web3Network } from 'parachain-api';
import { Vec, Bytes } from '@polkadot/types';
import { u8aToHex } from '@polkadot/util';

describe('Test Vc (direct invocation)', function () {
let context: IntegrationTestContext = undefined as any;
Expand Down Expand Up @@ -93,7 +93,7 @@ describe('Test Vc (direct invocation)', function () {

const bitcoinNonce = getNextNonce();
const bitcoinIdentity = await buildIdentityHelper(
u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())),
u8aToHex(context.bitcoinWallet.alice.publicKey),
'Bitcoin',
context
);
Expand Down
4 changes: 2 additions & 2 deletions tee-worker/ts-tests/integration-tests/dr_vc.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { randomBytes, KeyObject } from 'crypto';
import { step } from 'mocha-steps';
import { assert } from 'chai';
import { u8aToHex, bufferToU8a } from '@polkadot/util';
import { buildIdentityFromKeypair, initIntegrationTestContext, PolkadotSigner } from './common/utils';
import { assertIsInSidechainBlock, assertVc } from './common/utils/assertion';
import {
Expand All @@ -19,6 +18,7 @@ import { subscribeToEventsWithExtHash } from './common/transactions';
import { mockAssertions } from './common/utils/vc-helper';
import { LitentryValidationData, Web3Network } from 'parachain-api';
import { Vec, Bytes } from '@polkadot/types';
import { u8aToHex } from '@polkadot/util';

describe('Test Vc (direct request)', function () {
let context: IntegrationTestContext = undefined as any;
Expand Down Expand Up @@ -93,7 +93,7 @@ describe('Test Vc (direct request)', function () {

const bitcoinNonce = getNextNonce();
const bitcoinIdentity = await buildIdentityHelper(
u8aToHex(bufferToU8a(context.bitcoinWallet.alice.toPublicKey().toBuffer())),
u8aToHex(context.bitcoinWallet.alice.publicKey),
'Bitcoin',
context
);
Expand Down
6 changes: 4 additions & 2 deletions tee-worker/ts-tests/integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,25 @@
"@polkadot/util": "^12.5.1",
"@polkadot/util-crypto": "^12.5.1",
"add": "^2.0.6",
"bitcore-lib": "^10.0.21",
"bitcoinjs-lib": "^6.1.5",
"bitcoinjs-message": "^2.2.0",
"chai": "^4.3.6",
"colors": "^1.4.0",
"ecpair": "^2.1.0",
"js-base64": "^3.7.5",
"micro-base58": "^0.5.1",
"mocha": "^10.1.0",
"mocha-steps": "^1.3.0",
"parachain-api": "file:../../client-api/parachain-api",
"scale-ts": "^0.2.11",
"sidechain-api": "file:../../client-api/sidechain-api",
"tiny-secp256k1": "^2.2.3",
"websocket-as-promised": "^2.0.1",
"ws": "^8.8.1",
"zx": "^7.2.3"
},
"devDependencies": {
"@ethersproject/providers": "^5.7.2",
"@types/bitcore-lib": "^0.15.1",
"@types/chai": "^4.3.3",
"@types/mocha": "^10.0.0",
"@types/node": "^20.4.4",
Expand Down

0 comments on commit 744bc85

Please sign in to comment.