in modules/serialize/src/deserialize_encrypted_data_keys.ts [18:103]
export function deserializeEncryptedDataKeysFactory(
toUtf8: (input: Uint8Array) => string
) {
return deserializeEncryptedDataKeys
/**
* Exported for testing. Used by deserializeMessageHeader to compose a complete solution.
* @param buffer Uint8Array
* @param startPos number
* @param deserializeOptions DeserializeOptions
*/
function deserializeEncryptedDataKeys(
buffer: Uint8Array,
startPos: number,
{ maxEncryptedDataKeys }: DeserializeOptions = {
maxEncryptedDataKeys: false,
}
):
| { encryptedDataKeys: ReadonlyArray<EncryptedDataKey>; readPos: number }
| false {
/* Precondition: startPos must be within the byte length of the buffer given. */
needs(
buffer.byteLength >= startPos && startPos >= 0,
'startPos out of bounds.'
)
/* Precondition: deserializeEncryptedDataKeys needs a valid maxEncryptedDataKeys. */
needs(
maxEncryptedDataKeys === false || maxEncryptedDataKeys >= 1,
'Invalid maxEncryptedDataKeys value.'
)
/* Check for early return (Postcondition): Need to have at least Uint16 (2) bytes of data. */
if (startPos + 2 > buffer.byteLength) return false
/* Uint8Array is a view on top of the underlying ArrayBuffer.
* This means that raw underlying memory stored in the ArrayBuffer
* may be larger than the Uint8Array. This is especially true of
* the Node.js Buffer object. The offset and length *must* be
* passed to the DataView otherwise I will get unexpected results.
*/
const dataView = new DataView(
buffer.buffer,
buffer.byteOffset,
buffer.byteLength
)
const encryptedDataKeysCount = dataView.getUint16(startPos, false) // big endian
/* Precondition: There must be at least 1 EncryptedDataKey element. */
needs(encryptedDataKeysCount, 'No EncryptedDataKey found.')
/* Precondition: encryptedDataKeysCount must not exceed maxEncryptedDataKeys. */
needs(
maxEncryptedDataKeys === false ||
encryptedDataKeysCount <= maxEncryptedDataKeys,
'maxEncryptedDataKeys exceeded.'
)
const elementInfo = readElements(
encryptedDataKeysCount,
3,
buffer,
startPos + 2
)
/* Check for early return (Postcondition): readElement will return false if there is not enough data.
* I can only continue if I have at least the entire EDK section.
*/
if (!elementInfo) return false
const { elements, readPos } = elementInfo
const encryptedDataKeys = elements.map(
([rawId, rawInfo, encryptedDataKey]) => {
const providerId = toUtf8(rawId)
const providerInfo = toUtf8(rawInfo)
return new EncryptedDataKey({
providerInfo,
providerId,
encryptedDataKey,
rawInfo,
})
}
)
Object.freeze(encryptedDataKeys)
return { encryptedDataKeys, readPos }
}
}