diff --git a/.gitignore b/.gitignore index 518767e2..0dec6a16 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,5 @@ tests_tools/target fuzz-*.log /scan-build + +tests_zemu/bun.lockb diff --git a/tests_zemu/package.json b/tests_zemu/package.json index 873e82ac..e48084ad 100644 --- a/tests_zemu/package.json +++ b/tests_zemu/package.json @@ -1,47 +1,53 @@ { "name": "integration-tests", - "author": "Zondax AG", - "license": "Apache-2.0", "version": "1.0.0", "description": "", - "types": "./dist/index.d.ts", - "repository": { - "type": "git", - "url": "git+https://github.com/Zondax/ledger-cosmos" - }, "keywords": [ "Zondax", "Ledger" ], + "repository": { + "type": "git", + "url": "git+https://github.com/Zondax/ledger-cosmos" + }, + "license": "Apache-2.0", + "author": "Zondax AG", + "types": "./dist/index.d.ts", "scripts": { "clean": "ts-node tests/pullImageKillOld.ts", - "test": "yarn clean && jest --maxConcurrency 2" + "format": "FORCE_COLOR=1 prettier --write . && sort-package-json", + "format:check": "FORCE_COLOR=1 prettier --check .", + "lint": "eslint .", + "lint:fix": "eslint --fix .", + "test": "yarn clean && jest --maxConcurrency 3", + "try": "node try.mjs", + "upgrade": "bunx npm-check-updates -i" }, "dependencies": { - "@zondax/ledger-cosmos-js": "^3.0.3", + "@zondax/ledger-cosmos-js": "^3", "@zondax/zemu": "^0.50.2" }, "devDependencies": { + "@ledgerhq/hw-transport-node-hid": "^6.29.3", + "@ledgerhq/logs": "^6.12.0", + "@noble/curves": "^1.5.0", + "@scure/base": "^1.1.7", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/jest": "^29.5.12", "@types/ledgerhq__hw-transport": "^4.21.8", - "@typescript-eslint/eslint-plugin": "^7.17.0", - "@typescript-eslint/parser": "^7.17.0", - "bech32": "^2.0.0", - "blakejs": "^1.1.1", - "crypto-js": "4.2.0", - "eslint": "^9.7.0", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^28.6.0", + "eslint-plugin-jest": "^28.8.2", "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-promise": "^7.1.0", + "eslint-plugin-tsdoc": "^0.3.0", + "eslint-plugin-unused-imports": "^4.1.3", "jest": "29.7.0", - "jest-serial-runner": "^1.1.0", - "js-sha3": "0.9.3", - "jssha": "^3.2.0", - "keccak256": "^1.0.6", "prettier": "^3.3.3", - "secp256k1": "^5.0.0", - "ts-jest": "^29.2.3", + "ts-jest": "^29.2.5", "ts-node": "^10.9.2", "typescript": "^5.5.4" } diff --git a/tests_zemu/tests/amino.test.ts b/tests_zemu/tests/amino.test.ts index 7dc50337..e9a0d040 100644 --- a/tests_zemu/tests/amino.test.ts +++ b/tests_zemu/tests/amino.test.ts @@ -15,7 +15,6 @@ ******************************************************************************* */ import Zemu, { ClickNavigation, TouchNavigation, isTouchDevice } from '@zondax/zemu' -// @ts-ignore import { CosmosApp } from '@zondax/ledger-cosmos-js' import { defaultOptions, @@ -29,11 +28,10 @@ import { example_tx_str_msgMultiSend, } from './common' -// @ts-ignore -import secp256k1 from 'secp256k1/elliptic' -// @ts-ignore -import crypto from 'crypto' import { ButtonKind, IButton, SwipeDirection } from '@zondax/zemu/dist/types' +import { secp256k1 } from '@noble/curves/secp256k1' +import { sha256 } from '@noble/hashes/sha256' +import { keccak_256 } from '@noble/hashes/sha3' jest.setTimeout(120000) @@ -55,7 +53,7 @@ describe('Amino', function () { const app = new CosmosApp(sim.getTransport()) const path = [44, 118, 0, 0, 0] - const tx = Buffer.from(JSON.stringify(example_tx_str_basic), "utf-8") + const tx = Buffer.from(JSON.stringify(example_tx_str_basic), 'utf-8') const hrp = 'cosmos' // get address / publickey @@ -79,15 +77,13 @@ describe('Amino', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) + const msgHash = sha256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -124,15 +120,13 @@ describe('Amino', function () { expect(resp.error_message).toEqual('No errors') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) + const msgHash = sha256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -170,15 +164,13 @@ describe('Amino', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) + const msgHash = sha256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -216,15 +208,13 @@ describe('Amino', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) + const msgHash = sha256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -262,15 +252,13 @@ describe('Amino', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) + const msgHash = sha256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -308,15 +296,13 @@ describe('Amino', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) + const msgHash = sha256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -330,7 +316,7 @@ describe('Amino', function () { const app = new CosmosApp(sim.getTransport()) // Activate expert mode - await sim.toggleExpertMode(); + await sim.toggleExpertMode() const path = [44, 118, 0, 0, 0] const tx = Buffer.from(JSON.stringify(example_tx_str_msgMultiSend)) @@ -357,15 +343,13 @@ describe('Amino', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) + const msgHash = sha256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -379,7 +363,7 @@ describe('Amino', function () { const app = new CosmosApp(sim.getTransport()) // Change to expert mode so we can skip fields - await sim.toggleExpertMode(); + await sim.toggleExpertMode() const path = [44, 60, 0, 0, 0] const tx = Buffer.from(JSON.stringify(setWithdrawAddress)) @@ -406,15 +390,13 @@ describe('Amino', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const sha3 = require('js-sha3') - const msgHash = Buffer.from(sha3.keccak256(tx), 'hex') + const msgHash = keccak_256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -428,10 +410,10 @@ describe('Amino', function () { const app = new CosmosApp(sim.getTransport()) // Enable expert to allow sign with eth path - await sim.toggleExpertMode(); + await sim.toggleExpertMode() const path = [44, 60, 0, 0, 0] - const tx = Buffer.from(JSON.stringify(example_tx_str_basic), "utf-8") + const tx = Buffer.from(JSON.stringify(example_tx_str_basic), 'utf-8') const hrp = 'inj' // check with invalid HRP @@ -460,15 +442,13 @@ describe('Amino', function () { console.log(respPk) // Now verify the signature - const sha3 = require('js-sha3') - const msgHash = Buffer.from(sha3.keccak256(tx), 'hex') + const msgHash = keccak_256(tx) - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) + const signature = secp256k1.Signature.fromDER(resp.signature) const pk = Uint8Array.from(respPk.compressed_pk) - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -482,7 +462,7 @@ describe('Amino', function () { const app = new CosmosApp(sim.getTransport()) const path = [44, 60, 0, 0, 0] - const tx = Buffer.from(JSON.stringify(example_tx_str_basic), "utf-8") + const tx = Buffer.from(JSON.stringify(example_tx_str_basic), 'utf-8') // get address / publickey const respPk = await app.getAddressAndPubKey(path, 'inj') @@ -495,22 +475,20 @@ describe('Amino', function () { // Wait until we are not in the main menu await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) - let nav = undefined; + let nav = undefined if (isTouchDevice(m.name)) { const okButton: IButton = { x: 200, y: 540, delay: 0.25, direction: SwipeDirection.NoSwipe, - }; - nav = new TouchNavigation(m.name, [ - ButtonKind.ConfirmYesButton, - ]); - nav.schedule[0].button = okButton; + } + nav = new TouchNavigation(m.name, [ButtonKind.ConfirmYesButton]) + nav.schedule[0].button = okButton } else { - nav = new ClickNavigation([1, 0]); + nav = new ClickNavigation([1, 0]) } - await sim.navigate('.', `${m.prefix.toLowerCase()}-sign_basic_eth_warning`, nav.schedule); + await sim.navigate('.', `${m.prefix.toLowerCase()}-sign_basic_eth_warning`, nav.schedule) const resp = await signatureRequest console.log(resp) diff --git a/tests_zemu/tests/common.ts b/tests_zemu/tests/common.ts index ec158cae..c3a3a50b 100644 --- a/tests_zemu/tests/common.ts +++ b/tests_zemu/tests/common.ts @@ -42,64 +42,65 @@ export const DEVICE_MODELS: IDeviceModel[] = [ { name: 'flex', prefix: 'FL', path: APP_PATH_FL }, ] -export const tx_sign_textual = 'a10192a20168436861696e20696402686d792d636861696ea2016e4163636f756e74206e756d626572026131a2016853657175656e6365026132a301674164647265737302782d636f736d6f7331756c6176336873656e7570737771666b77327933737570356b677471776e767161386579687304f5a3016a5075626c6963206b657902781f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657904f5a3026d5075624b6579206f626a656374030104f5a401634b657902785230324542204444374620453446442045423736204443384120323035452046363544203739304320443330452038413337203541354320323532382045423341203932334120463146422034443739203444030204f5a102781e54686973207472616e73616374696f6e206861732031204d657373616765a3016d4d6573736167652028312f312902781c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e640301a2026e4d736753656e64206f626a6563740302a3016c46726f6d206164647265737302782d636f736d6f7331756c6176336873656e7570737771666b77327933737570356b677471776e76716138657968730303a3016a546f206164647265737302782d636f736d6f7331656a726634637572327779366b667572673966326a707070326833616665356836706b6835740303a30166416d6f756e74026731302041544f4d0303a1026e456e64206f66204d657373616765a201644d656d6f0278193e20e29a9befb88f5c7532363942e29a9befb88f2020202020a2016446656573026a302e3030322041544f4da30169476173206c696d697402673130302730303004f5a3017148617368206f66207261772062797465730278403963303433323930313039633237306232666661396633633066613535613039306330313235656265663838316637646135333937386462663933663733383504f5' +export const tx_sign_textual = + 'a10192a20168436861696e20696402686d792d636861696ea2016e4163636f756e74206e756d626572026131a2016853657175656e6365026132a301674164647265737302782d636f736d6f7331756c6176336873656e7570737771666b77327933737570356b677471776e767161386579687304f5a3016a5075626c6963206b657902781f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657904f5a3026d5075624b6579206f626a656374030104f5a401634b657902785230324542204444374620453446442045423736204443384120323035452046363544203739304320443330452038413337203541354320323532382045423341203932334120463146422034443739203444030204f5a102781e54686973207472616e73616374696f6e206861732031204d657373616765a3016d4d6573736167652028312f312902781c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e640301a2026e4d736753656e64206f626a6563740302a3016c46726f6d206164647265737302782d636f736d6f7331756c6176336873656e7570737771666b77327933737570356b677471776e76716138657968730303a3016a546f206164647265737302782d636f736d6f7331656a726634637572327779366b667572673966326a707070326833616665356836706b6835740303a30166416d6f756e74026731302041544f4d0303a1026e456e64206f66204d657373616765a201644d656d6f0278193e20e29a9befb88f5c7532363942e29a9befb88f2020202020a2016446656573026a302e3030322041544f4da30169476173206c696d697402673130302730303004f5a3017148617368206f66207261772062797465730278403963303433323930313039633237306232666661396633633066613535613039306330313235656265663838316637646135333937386462663933663733383504f5' export const example_tx_str_msgMultiSend = { - "account_number": "10", - "chain_id": "chain-WiONzW", - "fee": { - "amount": [], - "gas": "200000" + account_number: '10', + chain_id: 'chain-WiONzW', + fee: { + amount: [], + gas: '200000', }, - "memo": "", - "msgs": [ + memo: '', + msgs: [ { - "type": "cosmos-sdk/MsgMultiSend", - "value": { - "inputs": [ + type: 'cosmos-sdk/MsgMultiSend', + value: { + inputs: [ { - "address": "cosmos1w4efqfklkezgyt6lncjdwxncrzyzpr2efzcqal", - "coins": [ + address: 'cosmos1w4efqfklkezgyt6lncjdwxncrzyzpr2efzcqal', + coins: [ { - "amount": "30", - "denom": "stake" - } - ] - } + amount: '30', + denom: 'stake', + }, + ], + }, ], - "outputs": [ + outputs: [ { - "address": "cosmos184hgxlzat3qhm7p28563w4jyw4aa3wcgnj6gtv", - "coins": [ + address: 'cosmos184hgxlzat3qhm7p28563w4jyw4aa3wcgnj6gtv', + coins: [ { - "amount": "10", - "denom": "stake" - } - ] + amount: '10', + denom: 'stake', + }, + ], }, { - "address": "cosmos1pfyz36qx8z8dm8ktd75mwx5j5vsmkzfn7wrgp9", - "coins": [ + address: 'cosmos1pfyz36qx8z8dm8ktd75mwx5j5vsmkzfn7wrgp9', + coins: [ { - "amount": "10", - "denom": "stake" - } - ] + amount: '10', + denom: 'stake', + }, + ], }, { - "address": "cosmos1xu388ml6krya3ysmlrup2ylxjtzhl4hlaem3ng", - "coins": [ + address: 'cosmos1xu388ml6krya3ysmlrup2ylxjtzhl4hlaem3ng', + coins: [ { - "amount": "10", - "denom": "stake" - } - ] - } - ] - } - } + amount: '10', + denom: 'stake', + }, + ], + }, + ], + }, + }, ], - "sequence": "16", + sequence: '16', } export const example_tx_str_basic = { @@ -260,34 +261,34 @@ export const example_tx_str_basic_extra_fields = { }, ], sequence: '106', - unknown_field: 123456 + unknown_field: 123456, } export const ibc_denoms = { - account_number: "0", - chain_id: "cosmoshub-4", + account_number: '0', + chain_id: 'cosmoshub-4', fee: { amount: [ { - "amount": '5', - "denom": 'uatom', - } + amount: '5', + denom: 'uatom', + }, ], gas: '10000', }, - memo: "testmemo", + memo: 'testmemo', msgs: [ { inputs: [ { - address: "cosmosaccaddr1d9h8qat5e4ehc5", + address: 'cosmosaccaddr1d9h8qat5e4ehc5', coins: [ { amount: '10', - denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2' - } - ] - } + denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2', + }, + ], + }, ], outputs: [ { @@ -295,14 +296,14 @@ export const ibc_denoms = { coins: [ { amount: '10', - denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2' - } - ] - } - ] - } + denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2', + }, + ], + }, + ], + }, ], - sequence: '1' + sequence: '1', } export const setWithdrawAddress = { @@ -312,10 +313,10 @@ export const setWithdrawAddress = { amount: [ { amount: '5000', - denom: 'uatom' - } + denom: 'uatom', + }, ], - gas: '200000' + gas: '200000', }, memo: '', msgs: [ @@ -323,18 +324,18 @@ export const setWithdrawAddress = { type: 'cosmos-sdk/MsgSetWithdrawAddress', value: { delegator_address: 'cosmos1hr9x0sjvel6z3vt9qny8sdd5gnnlgk0p69d6cv', - withdraw_address: 'cosmos12d64j98tjjpqkx70r08aspc4nvntqp2w6wr2de' - } + withdraw_address: 'cosmos12d64j98tjjpqkx70r08aspc4nvntqp2w6wr2de', + }, }, { type: 'cosmos-sdk/MsgWithdrawDelegationReward', value: { delegator_address: 'cosmos1hr9x0sjvel6z3vt9qny8sdd5gnnlgk0p69d6cv', - validator_address: 'cosmosvaloper13dr26wdygna3s8fdl5tlc45m2le2ydyddxzj49' - } - } + validator_address: 'cosmosvaloper13dr26wdygna3s8fdl5tlc45m2le2ydyddxzj49', + }, + }, ], - sequence: '7' + sequence: '7', } export const cliGovDeposit = { @@ -342,21 +343,23 @@ export const cliGovDeposit = { chain_id: 'my-chain', fee: { amount: [], - gas: '200000' + gas: '200000', }, memo: 'A B C', msgs: [ { type: 'cosmos-sdk/MsgDeposit', value: { - amount: [{ - amount: '10', - denom: 'stake', - }], + amount: [ + { + amount: '10', + denom: 'stake', + }, + ], depositor: 'cosmos1xl2256vdh0j68khz9wq88hnyqcq0f5f4za2480', - proposal_id: '1' - } + proposal_id: '1', + }, }, ], - sequence: '2' + sequence: '2', } diff --git a/tests_zemu/tests/standard.test.ts b/tests_zemu/tests/standard.test.ts index 2983ddef..d68a1338 100644 --- a/tests_zemu/tests/standard.test.ts +++ b/tests_zemu/tests/standard.test.ts @@ -17,9 +17,9 @@ import Zemu, { zondaxMainmenuNavigation, ButtonKind, isTouchDevice } from '@zondax/zemu' import { CosmosApp } from '@zondax/ledger-cosmos-js' import { defaultOptions, DEVICE_MODELS } from './common' - -// @ts-ignore -// import secp256k1 from 'secp256k1/elliptic' +import { secp256k1 } from '@noble/curves/secp256k1' +import { keccak_256 } from '@noble/hashes/sha3' +import { bech32 } from '@scure/base' jest.setTimeout(90000) @@ -53,8 +53,6 @@ describe('Standard', function () { console.log(resp) - expect(resp.return_code).toEqual(0x9000) - expect(resp.error_message).toEqual('No errors') expect(resp).toHaveProperty('test_mode') expect(resp).toHaveProperty('major') expect(resp).toHaveProperty('minor') @@ -84,7 +82,7 @@ describe('Standard', function () { expect(resp.bech32_address).toEqual('cosmos1wkd9tfm5pqvhhaxq77wv9tvjcsazuaykwsld65') expect(resp.compressed_pk.length).toEqual(33) - expect(resp.compressed_pk.toString("hex")).toEqual('035c986b9ae5fbfb8e1e9c12c817f5ef8fdb821cdecaa407f1420ec4f8f1d766bf') + expect(resp.compressed_pk.toString('hex')).toEqual('035c986b9ae5fbfb8e1e9c12c817f5ef8fdb821cdecaa407f1420ec4f8f1d766bf') } finally { await sim.close() } @@ -119,7 +117,7 @@ describe('Standard', function () { expect(resp.bech32_address).toEqual('cosmos1wkd9tfm5pqvhhaxq77wv9tvjcsazuaykwsld65') expect(resp.compressed_pk.length).toEqual(33) - expect(resp.compressed_pk.toString("hex")).toEqual('035c986b9ae5fbfb8e1e9c12c817f5ef8fdb821cdecaa407f1420ec4f8f1d766bf') + expect(resp.compressed_pk.toString('hex')).toEqual('035c986b9ae5fbfb8e1e9c12c817f5ef8fdb821cdecaa407f1420ec4f8f1d766bf') } finally { await sim.close() } @@ -162,14 +160,9 @@ describe('Standard', function () { expect(resp.compressed_pk.length).toEqual(33) // Verify address - const secp256k1 = require("secp256k1"); - const keccak = require("keccak256"); - const { bech32 } = require("bech32"); - - // Take the compressed pubkey and verify that the expected address can be computed - const uncompressPubKeyUint8Array = secp256k1.publicKeyConvert(resp.compressed_pk, false).subarray(1); - const ethereumAddressBuffer = Buffer.from(keccak(Buffer.from(uncompressPubKeyUint8Array))).subarray(-20); - const eth_address = bech32.encode(hrp, bech32.toWords(ethereumAddressBuffer)); // "cosmos15n2h0lzvfgc8x4fm6fdya89n78x6ee2fm7fxr3" + const uncompressPubKeyUint8Array = secp256k1.ProjectivePoint.fromHex(resp.compressed_pk).toRawBytes(false).subarray(1) + const ethereumAddressBuffer = Buffer.from(keccak_256(uncompressPubKeyUint8Array)).subarray(-20) + const eth_address = bech32.encode(hrp, bech32.toWords(ethereumAddressBuffer)) // "cosmos15n2h0lzvfgc8x4fm6fdya89n78x6ee2fm7fxr3" expect(resp.bech32_address).toEqual(eth_address) expect(resp.bech32_address).toEqual('inj15n2h0lzvfgc8x4fm6fdya89n78x6ee2f3h7z3f') @@ -213,7 +206,7 @@ describe('Standard', function () { const app = new CosmosApp(sim.getTransport()) // Activate expert mode - await sim.toggleExpertMode(); + await sim.toggleExpertMode() // Derivation path. First 3 items are automatically hardened! const path = [44, 118, 2147483647, 0, 4294967295] diff --git a/tests_zemu/tests/textual.test.ts b/tests_zemu/tests/textual.test.ts index 06a26816..84964b73 100644 --- a/tests_zemu/tests/textual.test.ts +++ b/tests_zemu/tests/textual.test.ts @@ -15,13 +15,11 @@ ******************************************************************************* */ import Zemu, { ClickNavigation, TouchNavigation, isTouchDevice } from '@zondax/zemu' -// @ts-ignore import { CosmosApp } from '@zondax/ledger-cosmos-js' import { defaultOptions, DEVICE_MODELS, tx_sign_textual, TEXTUAL_TX } from './common' -// @ts-ignore -import secp256k1 from 'secp256k1/elliptic' -// @ts-ignore -import crypto from 'crypto' +import { secp256k1 } from '@noble/curves/secp256k1' +import { sha256 } from '@noble/hashes/sha256' +import { keccak_256 } from '@noble/hashes/sha3' import { ButtonKind, IButton, SwipeDirection } from '@zondax/zemu/dist/types' jest.setTimeout(90000) @@ -71,15 +69,10 @@ describe('Textual', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) - - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) - - const pk = Uint8Array.from(respPk.compressed_pk) - - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const hash = sha256(tx) + const signature = secp256k1.Signature.fromDER(resp.signature) + const pk = secp256k1.ProjectivePoint.fromHex(respPk.compressed_pk) + const signatureOk = secp256k1.verify(signature, hash, pk.toRawBytes()) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -120,29 +113,24 @@ describe('Textual', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const hash = crypto.createHash('sha256') - const msgHash = Uint8Array.from(hash.update(tx).digest()) - - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) - - const pk = Uint8Array.from(respPk.compressed_pk) - - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const hash = sha256(tx) + const signature = secp256k1.Signature.fromDER(resp.signature) + const pk = secp256k1.ProjectivePoint.fromHex(respPk.compressed_pk) + const signatureOk = secp256k1.verify(signature, hash, pk.toRawBytes()) expect(signatureOk).toEqual(true) } finally { await sim.close() } }) - test.concurrent.each(TEXTUAL_MODELS)('sign basic textual eth ', async function (m) { + test.concurrent.each(TEXTUAL_MODELS)('sign basic textual eth', async function (m) { const sim = new Zemu(m.path) try { await sim.start({ ...defaultOptions, model: m.name }) const app = new CosmosApp(sim.getTransport()) // Enable expert to allow sign with eth path - await sim.toggleExpertMode(); + await sim.toggleExpertMode() const path = [44, 60, 0, 0, 0] const tx = Buffer.from(tx_sign_textual, 'hex') @@ -169,15 +157,10 @@ describe('Textual', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const sha3 = require('js-sha3') - const msgHash = Buffer.from(sha3.keccak256(tx), 'hex') - - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) - - const pk = Uint8Array.from(respPk.compressed_pk) - - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const msgHash = keccak_256(tx) + const signature = secp256k1.Signature.fromDER(resp.signature) + const pk = secp256k1.ProjectivePoint.fromHex(respPk.compressed_pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk.toRawBytes()) expect(signatureOk).toEqual(true) } finally { await sim.close() @@ -205,22 +188,20 @@ describe('Textual', function () { // Wait until we are not in the main menu await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) - let nav = undefined; + let nav = undefined if (isTouchDevice(m.name)) { const okButton: IButton = { x: 200, y: 540, delay: 0.25, direction: SwipeDirection.NoSwipe, - }; - nav = new TouchNavigation(m.name, [ - ButtonKind.ConfirmYesButton, - ]); - nav.schedule[0].button = okButton; + } + nav = new TouchNavigation(m.name, [ButtonKind.ConfirmYesButton]) + nav.schedule[0].button = okButton } else { - nav = new ClickNavigation([1, 0]); + nav = new ClickNavigation([1, 0]) } - await sim.navigate('.', `${m.prefix.toLowerCase()}-textual-sign_basic_eth_warning`, nav.schedule); + await sim.navigate('.', `${m.prefix.toLowerCase()}-textual-sign_basic_eth_warning`, nav.schedule) const resp = await signatureRequest console.log(resp) @@ -271,15 +252,10 @@ describe('Textual', function () { expect(resp).toHaveProperty('signature') // Now verify the signature - const sha3 = require('js-sha3') - const msgHash = Buffer.from(sha3.keccak256(tx), 'hex') - - const signatureDER = resp.signature - const signature = secp256k1.signatureImport(Uint8Array.from(signatureDER)) - - const pk = Uint8Array.from(respPk.compressed_pk) - - const signatureOk = secp256k1.ecdsaVerify(signature, msgHash, pk) + const msgHash = keccak_256(tx) + const signature = secp256k1.Signature.fromDER(resp.signature) + const pk = secp256k1.ProjectivePoint.fromHex(respPk.compressed_pk) + const signatureOk = secp256k1.verify(signature, msgHash, pk.toRawBytes()) expect(signatureOk).toEqual(true) } finally { await sim.close()