@ledgerhq/domain-service
Version:
Ledger service responsible for domain handling
56 lines • 2.77 kB
JavaScript
/* istanbul ignore file: this file can be ignored in tests as long as it's only for debugging purpose & not touching userland */
const TLVs = {
"01": { typeName: "STRUCTURE_TYPE", parser: input => parseInt(input, 16) },
"02": { typeName: "VERSION", parser: input => parseInt(input, 16) },
"12": { typeName: "CHALLENGE", parser: input => input },
"13": { typeName: "SIGNER_KEY_ID", parser: input => input },
"14": { typeName: "SIGNER_ALGO", parser: input => input },
"20": {
typeName: "TRUSTED_NAME",
parser: input => Buffer.from(input, "hex").toString(),
},
"21": { typeName: "COIN_TYPE", parser: input => parseInt(input, 16) },
"22": { typeName: "ADDRESS", parser: input => `0x${input}` },
"15": { typeName: "SIGNATURE", parser: input => input },
};
/**
* Parser logic
*/
export const tlvParser = (apdu) => {
const parsedApdu = [];
let apduLeft = apdu;
while (apduLeft.length > 0) {
const type = apduLeft.substring(0, 2);
const TLV = TLVs[type] || {};
const lengthByte = apduLeft.substring(2, 4);
// documentation to explain DER integer encoding
// @see https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-integer
const isLengthDEREncodedInt = !!(parseInt(lengthByte, 16) >> 7); // check if the high bit of the 7 bits number a 1 ?
if (isLengthDEREncodedInt) {
const lengthByteLast6Bits = parseInt(lengthByte, 16) & 0x3f; // 0x3F === "111111" so this will return the last 6 bits of the DER encoded integer
const lengthSizeInBytes = parseInt(lengthByteLast6Bits.toString(16), 10); // length size in bytes as decimal
const offset = 4 + lengthSizeInBytes * 2; // we'll have to take the number of bytes for the size into account to not consider it as part of the Value of th TLV
const length = parseInt(apduLeft.substring(4, offset), 16); // the actual length of the Value
const lengthInChars = length * 2;
const value = apduLeft.substring(offset, offset + lengthInChars);
parsedApdu.push({
T: TLV.typeName,
L: length.toString(16),
V: TLV.parser?.(value) || null,
});
apduLeft = apduLeft.substring(offset + lengthInChars);
}
else {
const lengthInChars = parseInt(lengthByte, 16) * 2;
const value = apduLeft.substring(4, 4 + lengthInChars);
parsedApdu.push({
T: TLV.typeName,
L: lengthByte,
V: TLV.parser?.(value) || null,
});
apduLeft = apduLeft.substring(4 + lengthInChars);
}
}
return parsedApdu;
};
//# sourceMappingURL=index.js.map