UNPKG

@ideem/zsm-client-sdk

Version:

ZSM makes 2FA easy and invisible for everyone, all the time, using advanced cryptography like MPC to establish cryptographic proof of the origin of any transaction or login attempt, while eliminating opportunities for social engineering. ZSM has no relian

62 lines (51 loc) 6.74 kB
/** @name decodeAttestationObject @description Decodes a CBOR-encoded attestation object buffer into a JavaScript object (CBOR map of 3 entries (0xA3)) with properties 'fmt', 'attStmt', and 'authData'. @param {ArrayBuffer} buffer The CBOR-encoded attestation object. @returns {Object} The decoded attestation object with properties 'fmt', 'attStmt', and 'authData'. @throws {Error} If the first byte does not indicate a CBOR map of 3 entries. @throws {Error} If the major type of a value is unsupported. @throws {Error} If the input buffer is not a valid CBOR-encoded attestation object. */ function decodeAttestationObject(buffer) { try { if (!buffer) // IF the buffer argument is missing... throw new TypeError("Invalid input"); // ...throw an error if (buffer instanceof Uint8Array) // IF the buffer argument is a Uint8Array... buffer = buffer.buffer; // ...convert it to an ArrayBuffer if (!(buffer instanceof ArrayBuffer)) // IF the buffer argument is (STILL) not an ArrayBuffer... throw new TypeError("Invalid input"); // ...throw an error if (!buffer || !(buffer instanceof ArrayBuffer)) // IF the buffer argument is missing or not an ArrayBuffer... throw new TypeError("Invalid input"); // ...throw an error const view = new DataView(buffer); // Create a DataView to read the buffer argument (CBOR is a binary format) const attObj = {}; // Create an object to hold the decoded attestation object let offset = 0; // Create an offset counter to track our position in the buffer // Expect a CBOR map of 3 entries (0xA3) const type = view.getUint8(offset++); // Read the first byte to determine the major type if (type !== 0xA3) throw new Error("Unexpected format"); // Since we expect a map with 3 key-value pairs, throw an error if not found for (let i = 0; i < 3; i++) { // Iterate over the 3 key-value pairs... const keyLen = view.getUint8(offset++) - 0x60; // Read the length of the key (CBOR short string) const key = new TextDecoder() // Isolate out the key by initializing a TextDecoder... .decode(new Uint8Array(buffer, offset, keyLen)); // ...and decoding the buffered CBOR short string into it offset += keyLen; // Move offset past the key by the length of the key const majorType = view.getUint8(offset); // Read the major type of the value offset++; // Move past the major type byte if (majorType === 0x58) { // IF the major type's value is a byte string with length in next byte... const len = view.getUint8(offset++); // ...read the length of the byte string... attObj[key] = new Uint8Array(buffer, offset, len); // ...extract the byte string... offset += len; // ...and increment offset by length. } else if (majorType >= 0x60 && majorType < 0x78) { // OTHERWISE, if major type's value is a short string (for 'fmt') const len = majorType - 0x60; // ...determine length from major type... attObj[key] = new TextDecoder() // ...and initialize a TextDecoder... .decode(new Uint8Array(buffer, offset, len)); // ...decoding the buffered CBOR short string into it offset += len; // ...finally, increment offset by length } else if (majorType === 0xA0) { // OTHERWISE, if major type's value is an empty map attObj[key] = {}; // ...and assign an empty object } else throw new Error("Unsupported type"); // OTHERWISE, throw an error } return attObj; // return the decoded attestation object } catch (e) { throw new Error("[Utils] :: decodeAttestationObject :: Failed to decode attestation object: " + e.message); } } export { decodeAttestationObject };