Skip to content

Commit

Permalink
adding serializePathBip44 to keep backward compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
chcmedeiros committed Jan 21, 2023
1 parent e72517b commit ac681ad
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 30 deletions.
42 changes: 22 additions & 20 deletions src/helperV1.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { CLA, errorCodeToString, INS, PAYLOAD_TYPE, processErrorResponse } from
export function serializePathv1(path) {
// length 3: ADR 8 derivation path
// length 5: Legacy derivation path
if (!path || (path.length !== 3 && path.length !== 5)) {
if (!(path instanceof Array)) {
throw new Error("Path must be array of numbers");
}

if (path.length !== 3 && path.length !== 5) {
throw new Error("Invalid path.");
}

Expand All @@ -28,28 +32,26 @@ export async function signSendChunkv1(app, chunkIdx, chunkNum, chunk, ins) {
if (chunkIdx === chunkNum) {
payloadType = PAYLOAD_TYPE.LAST;
}
return app.transport
.send(CLA, ins, payloadType, 0, chunk, [0x9000, 0x6984, 0x6a80])
.then((response) => {
const errorCodeData = response.slice(-2);
const returnCode = errorCodeData[0] * 256 + errorCodeData[1];
let errorMessage = errorCodeToString(returnCode);
return app.transport.send(CLA, ins, payloadType, 0, chunk, [0x9000, 0x6984, 0x6a80]).then((response) => {
const errorCodeData = response.slice(-2);
const returnCode = errorCodeData[0] * 256 + errorCodeData[1];
let errorMessage = errorCodeToString(returnCode);

if (returnCode === 0x6a80 || returnCode === 0x6984) {
errorMessage = `${errorMessage} : ${response.slice(0, response.length - 2).toString("ascii")}`;
}
if (returnCode === 0x6a80 || returnCode === 0x6984) {
errorMessage = `${errorMessage} : ${response.slice(0, response.length - 2).toString("ascii")}`;
}

let signature = null;
if (response.length > 2) {
signature = response.slice(0, response.length - 2);
}
let signature = null;
if (response.length > 2) {
signature = response.slice(0, response.length - 2);
}

return {
signature,
return_code: returnCode,
error_message: errorMessage,
};
}, processErrorResponse);
return {
signature,
return_code: returnCode,
error_message: errorMessage,
};
}, processErrorResponse);
}

/** @param {import('./types').App} app */
Expand Down
45 changes: 37 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
P1_VALUES,
} from "./common";

const HARDENED = 0x80000000;

function processGetAddrEd25519Response(response) {
const errorCodeData = response.slice(-2);
const returnCode = errorCodeData[0] * 256 + errorCodeData[1];
Expand Down Expand Up @@ -111,6 +113,29 @@ export default class OasisApp {
}
}

/** @param {import('./types').DerivationPath} path */
async serializePathBip44(path) {
if (!(path instanceof Array)) {
throw new Error("Path must be array of numbers");
}

if (path.length !== 5) {
throw new Error("Invalid path.");
}

/* eslint no-bitwise: "off", no-plusplus: "off" */
const buf = Buffer.alloc(path.length * 4);
for (let i = 0; i < path.length; i++) {
if (path[i] >= HARDENED) {
throw new Error("Incorrect child value (bigger or equal to 0x80000000)");
}
const value = i < 3 ? (HARDENED | path[i]) >>> 0 : path[i];
buf.writeUInt32LE(value, i * 4);
}

return buf;
}

static prepareChunks(serializedPathBuffer, context, message) {
/** @type {Buffer[]} */
const chunks = [];
Expand Down Expand Up @@ -173,7 +198,11 @@ export default class OasisApp {

/** @param {import('./types').DerivationPath} path */
async signGetChunks(path, context, message, ins) {
const serializedPath = await this.serializePath(path);
let serializedPath = await this.serializePath(path);

if (ins === INS.SIGN_PT_SECP256K1) {
serializedPath = await this.serializePathBip44(path);
}
// NOTE: serializePath can return an error (not throw, but return an error!)
// so handle that.
if ("return_code" in serializedPath && serializedPath.return_code !== 0x9000) {
Expand All @@ -182,7 +211,7 @@ export default class OasisApp {
if (ins === INS.SIGN_ED25519) {
return OasisApp.prepareChunks(serializedPath, context, message);
}

return OasisApp.prepareMetaChunks(serializedPath, context, message);
}

Expand Down Expand Up @@ -318,9 +347,9 @@ export default class OasisApp {
.then(processGetAddrEd25519Response, processErrorResponse);
}

/** @param {import('./types').DerivationPath} path */
/** @param {import('./types').DerivationPath} path */
async getAddressAndPubKey_secp256k1(path) {
const data = await this.serializePath(path);
const data = await this.serializePathBip44(path);
// NOTE: serializePath can return an error (not throw, but return an error!)
// so handle that.
if ("return_code" in data && data.return_code !== 0x9000) {
Expand All @@ -344,9 +373,9 @@ export default class OasisApp {
.then(processGetAddrEd25519Response, processErrorResponse);
}

/** @param {import('./types').DerivationPath} path */
/** @param {import('./types').DerivationPath} path */
async showAddressAndPubKey_secp256k1(path) {
const data = await this.serializePath(path);
const data = await this.serializePathBip44(path);
// NOTE: serializePath can return an error (not throw, but return an error!)
// so handle that.
if ("return_code" in data && data.return_code !== 0x9000) {
Expand Down Expand Up @@ -412,7 +441,7 @@ export default class OasisApp {
}, processErrorResponse);
}

/**
/**
* @param {import('./types').DerivationPath} path
* @returns {import('./types').AsyncResponse<{signature: null | Buffer}>}
*/
Expand Down Expand Up @@ -452,7 +481,7 @@ export default class OasisApp {
}, processErrorResponse);
}

/**
/**
* @param {import('./types').DerivationPath} path
* @returns {import('./types').AsyncResponse<{signature: null | Buffer}>}
*/
Expand Down
48 changes: 46 additions & 2 deletions tests/basic.ispec.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe("Integration", function () {
const app = new OasisApp(transport);

// Derivation path. First 3 items are automatically hardened!
const path = [44, 60, 0];
const path = [44, 60, 0, 0, 0];
const resp = await app.getAddressAndPubKey_secp256k1(path);

console.log(resp);
Expand All @@ -109,7 +109,7 @@ describe("Integration", function () {
const app = new OasisApp(transport);

// Derivation path. First 3 items are automatically hardened!
const path = [44, 60, 0];
const path = [44, 60, 0, 0, 0];
const resp = await app.showAddressAndPubKey_secp256k1(path);

console.log(resp);
Expand All @@ -127,6 +127,50 @@ describe("Integration", function () {
expect(resp.pk.length).toEqual(33);
});

test("getAddressAndPubKey_Secp256k1_second_address", async () => {
const app = new OasisApp(transport);

// Derivation path. First 3 items are automatically hardened!
const path = [44, 60, 0, 0, 1];
const resp = await app.getAddressAndPubKey_secp256k1(path);

console.log(resp);

expect(resp.return_code).toEqual(0x9000);
expect(resp.error_message).toEqual("No errors");

expect(resp).toHaveProperty("hex_address");
expect(resp).toHaveProperty("pk");

expect(resp.hex_address).toEqual("a4d577fc4c4a3073553bd25a4e9cb3f1cdace549");
expect(resp.pk.toString("hex")).toEqual(
"022374f2dacd71042b5a888e3839e4ba54752ad6a51d35b54f6abb899c4329d4bf",
);
expect(resp.pk.length).toEqual(33);
});

test("showAddressAndPubKey_Secp256k1_second_address", async () => {
const app = new OasisApp(transport);

// Derivation path. First 3 items are automatically hardened!
const path = [44, 60, 0, 0, 1];
const resp = await app.showAddressAndPubKey_secp256k1(path);

console.log(resp);

expect(resp.return_code).toEqual(0x9000);
expect(resp.error_message).toEqual("No errors");

expect(resp).toHaveProperty("hex_address");
expect(resp).toHaveProperty("pk");

expect(resp.hex_address).toEqual("a4d577fc4c4a3073553bd25a4e9cb3f1cdace549");
expect(resp.pk.toString("hex")).toEqual(
"022374f2dacd71042b5a888e3839e4ba54752ad6a51d35b54f6abb899c4329d4bf",
);
expect(resp.pk.length).toEqual(33);
});

test("appInfo", async () => {
const app = new OasisApp(transport);

Expand Down

0 comments on commit ac681ad

Please sign in to comment.