refactor: turn hkdf functions to async and remove extra deps (#1272)

* refactor: remove futoin-hkdf dependency and update hkdf implementation

* refactor: use crypto subtle and update functions to async

---------

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
This commit is contained in:
João Lucas de Oliveira Lopes
2025-03-01 13:31:48 -03:00
committed by GitHub
parent e6f98c3902
commit 8083754621
11 changed files with 78 additions and 48 deletions

View File

@@ -55,7 +55,7 @@ export const hkdfInfoKey = (type: MediaType) => {
}
/** generates all the keys required to encrypt/decrypt & sign a media message */
export function getMediaKeys(buffer: Uint8Array | string | null | undefined, mediaType: MediaType): MediaDecryptionKeyInfo {
export async function getMediaKeys(buffer: Uint8Array | string | null | undefined, mediaType: MediaType): Promise<MediaDecryptionKeyInfo> {
if(!buffer) {
throw new Boom('Cannot derive from empty media key')
}
@@ -65,7 +65,7 @@ export function getMediaKeys(buffer: Uint8Array | string | null | undefined, med
}
// expand using HKDF to 112 bytes, also pass in the relevant app info
const expandedMediaKey = hkdf(buffer, 112, { info: hkdfInfoKey(mediaType) })
const expandedMediaKey = await hkdf(buffer, 112, { info: hkdfInfoKey(mediaType) })
return {
iv: expandedMediaKey.slice(0, 16),
cipherKey: expandedMediaKey.slice(16, 48),
@@ -344,7 +344,7 @@ export const encryptedStream = async(
logger?.debug('fetched media stream')
const mediaKey = Crypto.randomBytes(32)
const { cipherKey, iv, macKey } = getMediaKeys(mediaKey, mediaType)
const { cipherKey, iv, macKey } = await getMediaKeys(mediaKey, mediaType)
const encWriteStream = new Readable({ read: () => {} })
let bodyPath: string | undefined
@@ -458,13 +458,13 @@ export type MediaDownloadOptions = {
export const getUrlFromDirectPath = (directPath: string) => `https://${DEF_HOST}${directPath}`
export const downloadContentFromMessage = (
export const downloadContentFromMessage = async(
{ mediaKey, directPath, url }: DownloadableMessage,
type: MediaType,
opts: MediaDownloadOptions = { }
) => {
const downloadUrl = url || getUrlFromDirectPath(directPath!)
const keys = getMediaKeys(mediaKey, type)
const keys = await getMediaKeys(mediaKey, type)
return downloadEncryptedContent(downloadUrl, keys, opts)
}
@@ -673,7 +673,7 @@ const getMediaRetryKey = (mediaKey: Buffer | Uint8Array) => {
/**
* Generate a binary node that will request the phone to re-upload the media & return the newly uploaded URL
*/
export const encryptMediaRetryRequest = (
export const encryptMediaRetryRequest = async(
key: proto.IMessageKey,
mediaKey: Buffer | Uint8Array,
meId: string
@@ -682,7 +682,7 @@ export const encryptMediaRetryRequest = (
const recpBuffer = proto.ServerErrorReceipt.encode(recp).finish()
const iv = Crypto.randomBytes(12)
const retryKey = getMediaRetryKey(mediaKey)
const retryKey = await getMediaRetryKey(mediaKey)
const ciphertext = aesEncryptGCM(recpBuffer, retryKey, iv, Buffer.from(key.id!))
const req: BinaryNode = {
@@ -752,12 +752,12 @@ export const decodeMediaRetryNode = (node: BinaryNode) => {
return event
}
export const decryptMediaRetryData = (
export const decryptMediaRetryData = async(
{ ciphertext, iv }: { ciphertext: Uint8Array, iv: Uint8Array },
mediaKey: Uint8Array,
msgId: string
) => {
const retryKey = getMediaRetryKey(mediaKey)
const retryKey = await getMediaRetryKey(mediaKey)
const plaintext = aesDecryptGCM(ciphertext, retryKey, iv, Buffer.from(msgId))
return proto.MediaRetryNotification.decode(plaintext)
}