mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
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:
committed by
GitHub
parent
e6f98c3902
commit
8083754621
@@ -49,7 +49,6 @@
|
|||||||
"audio-decode": "^2.1.3",
|
"audio-decode": "^2.1.3",
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.0",
|
||||||
"cache-manager": "^5.7.6",
|
"cache-manager": "^5.7.6",
|
||||||
"futoin-hkdf": "^1.5.1",
|
|
||||||
"libphonenumber-js": "^1.10.20",
|
"libphonenumber-js": "^1.10.20",
|
||||||
"libsignal": "github:WhiskeySockets/libsignal-node",
|
"libsignal": "github:WhiskeySockets/libsignal-node",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
const companionSharedKey = Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey)
|
const companionSharedKey = Curve.sharedKey(authState.creds.pairingEphemeralKeyPair.private, codePairingPublicKey)
|
||||||
const random = randomBytes(32)
|
const random = randomBytes(32)
|
||||||
const linkCodeSalt = randomBytes(32)
|
const linkCodeSalt = randomBytes(32)
|
||||||
const linkCodePairingExpanded = hkdf(companionSharedKey, 32, {
|
const linkCodePairingExpanded = await hkdf(companionSharedKey, 32, {
|
||||||
salt: linkCodeSalt,
|
salt: linkCodeSalt,
|
||||||
info: 'link_code_pairing_key_bundle_encryption_key'
|
info: 'link_code_pairing_key_bundle_encryption_key'
|
||||||
})
|
})
|
||||||
@@ -486,7 +486,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
|
|||||||
const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted])
|
const encryptedPayload = Buffer.concat([linkCodeSalt, encryptIv, encrypted])
|
||||||
const identitySharedKey = Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey)
|
const identitySharedKey = Curve.sharedKey(authState.creds.signedIdentityKey.private, primaryIdentityPublicKey)
|
||||||
const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random])
|
const identityPayload = Buffer.concat([companionSharedKey, identitySharedKey, random])
|
||||||
authState.creds.advSecretKey = hkdf(identityPayload, 32, { info: 'adv_secret' }).toString('base64')
|
authState.creds.advSecretKey = (await hkdf(identityPayload, 32, { info: 'adv_secret' })).toString('base64')
|
||||||
await query({
|
await query({
|
||||||
tag: 'iq',
|
tag: 'iq',
|
||||||
attrs: {
|
attrs: {
|
||||||
|
|||||||
@@ -654,20 +654,20 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
const content = assertMediaContent(message.message)
|
const content = assertMediaContent(message.message)
|
||||||
const mediaKey = content.mediaKey!
|
const mediaKey = content.mediaKey!
|
||||||
const meId = authState.creds.me!.id
|
const meId = authState.creds.me!.id
|
||||||
const node = encryptMediaRetryRequest(message.key, mediaKey, meId)
|
const node = await encryptMediaRetryRequest(message.key, mediaKey, meId)
|
||||||
|
|
||||||
let error: Error | undefined = undefined
|
let error: Error | undefined = undefined
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
[
|
[
|
||||||
sendNode(node),
|
sendNode(node),
|
||||||
waitForMsgMediaUpdate(update => {
|
waitForMsgMediaUpdate(async(update) => {
|
||||||
const result = update.find(c => c.key.id === message.key.id)
|
const result = update.find(c => c.key.id === message.key.id)
|
||||||
if(result) {
|
if(result) {
|
||||||
if(result.error) {
|
if(result.error) {
|
||||||
error = result.error
|
error = result.error
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const media = decryptMediaRetryData(result.media!, mediaKey, result.key.id!)
|
const media = await decryptMediaRetryData(result.media!, mediaKey, result.key.id!)
|
||||||
if(media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
|
if(media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
|
||||||
const resultStr = proto.MediaRetryNotification.ResultType[media.result]
|
const resultStr = proto.MediaRetryNotification.ResultType[media.result]
|
||||||
throw new Boom(
|
throw new Boom(
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ export const makeSocket = (config: SocketConfig) => {
|
|||||||
|
|
||||||
logger.trace({ handshake }, 'handshake recv from WA')
|
logger.trace({ handshake }, 'handshake recv from WA')
|
||||||
|
|
||||||
const keyEnc = noise.processHandshake(handshake, creds.noiseKey)
|
const keyEnc = await noise.processHandshake(handshake, creds.noiseKey)
|
||||||
|
|
||||||
let node: proto.IClientPayload
|
let node: proto.IClientPayload
|
||||||
if(!creds.me) {
|
if(!creds.me) {
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ type FetchAppStateSyncKey = (keyId: string) => Promise<proto.Message.IAppStateSy
|
|||||||
|
|
||||||
export type ChatMutationMap = { [index: string]: ChatMutation }
|
export type ChatMutationMap = { [index: string]: ChatMutation }
|
||||||
|
|
||||||
const mutationKeys = (keydata: Uint8Array) => {
|
const mutationKeys = async(keydata: Uint8Array) => {
|
||||||
const expanded = hkdf(keydata, 160, { info: 'WhatsApp Mutation Keys' })
|
const expanded = await hkdf(keydata, 160, { info: 'WhatsApp Mutation Keys' })
|
||||||
return {
|
return {
|
||||||
indexKey: expanded.slice(0, 32),
|
indexKey: expanded.slice(0, 32),
|
||||||
valueEncryptionKey: expanded.slice(32, 64),
|
valueEncryptionKey: expanded.slice(32, 64),
|
||||||
@@ -144,7 +144,7 @@ export const encodeSyncdPatch = async(
|
|||||||
})
|
})
|
||||||
const encoded = proto.SyncActionData.encode(dataProto).finish()
|
const encoded = proto.SyncActionData.encode(dataProto).finish()
|
||||||
|
|
||||||
const keyValue = mutationKeys(key.keyData!)
|
const keyValue = await mutationKeys(key.keyData!)
|
||||||
|
|
||||||
const encValue = aesEncrypt(encoded, keyValue.valueEncryptionKey)
|
const encValue = aesEncrypt(encoded, keyValue.valueEncryptionKey)
|
||||||
const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey)
|
const valueMac = generateMac(operation, encValue, encKeyId, keyValue.valueMacKey)
|
||||||
@@ -261,7 +261,7 @@ export const decodeSyncdPatch = async(
|
|||||||
throw new Boom(`failed to find key "${base64Key}" to decode patch`, { statusCode: 404, data: { msg } })
|
throw new Boom(`failed to find key "${base64Key}" to decode patch`, { statusCode: 404, data: { msg } })
|
||||||
}
|
}
|
||||||
|
|
||||||
const mainKey = mutationKeys(mainKeyObj.keyData!)
|
const mainKey = await mutationKeys(mainKeyObj.keyData!)
|
||||||
const mutationmacs = msg.mutations!.map(mutation => mutation.record!.value!.blob!.slice(-32))
|
const mutationmacs = msg.mutations!.map(mutation => mutation.record!.value!.blob!.slice(-32))
|
||||||
|
|
||||||
const patchMac = generatePatchMac(msg.snapshotMac!, mutationmacs, toNumber(msg.version!.version), name, mainKey.patchMacKey)
|
const patchMac = generatePatchMac(msg.snapshotMac!, mutationmacs, toNumber(msg.version!.version), name, mainKey.patchMacKey)
|
||||||
@@ -390,7 +390,7 @@ export const decodeSyncdSnapshot = async(
|
|||||||
throw new Boom(`failed to find key "${base64Key}" to decode mutation`)
|
throw new Boom(`failed to find key "${base64Key}" to decode mutation`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = mutationKeys(keyEnc.keyData!)
|
const result = await mutationKeys(keyEnc.keyData!)
|
||||||
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
||||||
if(Buffer.compare(snapshot.mac!, computedSnapshotMac) !== 0) {
|
if(Buffer.compare(snapshot.mac!, computedSnapshotMac) !== 0) {
|
||||||
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name} from snapshot`)
|
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name} from snapshot`)
|
||||||
@@ -458,7 +458,7 @@ export const decodePatches = async(
|
|||||||
throw new Boom(`failed to find key "${base64Key}" to decode mutation`)
|
throw new Boom(`failed to find key "${base64Key}" to decode mutation`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = mutationKeys(keyEnc.keyData!)
|
const result = await mutationKeys(keyEnc.keyData!)
|
||||||
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
||||||
if(Buffer.compare(snapshotMac!, computedSnapshotMac) !== 0) {
|
if(Buffer.compare(snapshotMac!, computedSnapshotMac) !== 0) {
|
||||||
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name}`)
|
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name}`)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes } from 'crypto'
|
import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes } from 'crypto'
|
||||||
import HKDF from 'futoin-hkdf'
|
|
||||||
import * as libsignal from 'libsignal'
|
import * as libsignal from 'libsignal'
|
||||||
import { KEY_BUNDLE_TYPE } from '../Defaults'
|
import { KEY_BUNDLE_TYPE } from '../Defaults'
|
||||||
import { KeyPair } from '../Types'
|
import { KeyPair } from '../Types'
|
||||||
@@ -122,10 +121,47 @@ export function md5(buffer: Buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HKDF key expansion
|
// HKDF key expansion
|
||||||
export function hkdf(buffer: Uint8Array | Buffer, expandedLength: number, info: { salt?: Buffer, info?: string }) {
|
export async function hkdf(
|
||||||
return HKDF(!Buffer.isBuffer(buffer) ? Buffer.from(buffer) : buffer, expandedLength, info)
|
buffer: Uint8Array | Buffer,
|
||||||
|
expandedLength: number,
|
||||||
|
info: { salt?: Buffer, info?: string }
|
||||||
|
): Promise<Buffer> {
|
||||||
|
// Ensure we have a Uint8Array for the key material
|
||||||
|
const inputKeyMaterial = buffer instanceof Uint8Array
|
||||||
|
? buffer
|
||||||
|
: new Uint8Array(buffer)
|
||||||
|
|
||||||
|
// Set default values if not provided
|
||||||
|
const salt = info.salt ? new Uint8Array(info.salt) : new Uint8Array(0)
|
||||||
|
const infoBytes = info.info
|
||||||
|
? new TextEncoder().encode(info.info)
|
||||||
|
: new Uint8Array(0)
|
||||||
|
|
||||||
|
// Import the input key material
|
||||||
|
const importedKey = await crypto.subtle.importKey(
|
||||||
|
'raw',
|
||||||
|
inputKeyMaterial,
|
||||||
|
{ name: 'HKDF' },
|
||||||
|
false,
|
||||||
|
['deriveBits']
|
||||||
|
)
|
||||||
|
|
||||||
|
// Derive bits using HKDF
|
||||||
|
const derivedBits = await crypto.subtle.deriveBits(
|
||||||
|
{
|
||||||
|
name: 'HKDF',
|
||||||
|
hash: 'SHA-256',
|
||||||
|
salt: salt,
|
||||||
|
info: infoBytes
|
||||||
|
},
|
||||||
|
importedKey,
|
||||||
|
expandedLength * 8 // Convert bytes to bits
|
||||||
|
)
|
||||||
|
|
||||||
|
return Buffer.from(derivedBits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function derivePairingCodeKey(pairingCode: string, salt: Buffer): Promise<Buffer> {
|
export async function derivePairingCodeKey(pairingCode: string, salt: Buffer): Promise<Buffer> {
|
||||||
// Convert inputs to formats Web Crypto API can work with
|
// Convert inputs to formats Web Crypto API can work with
|
||||||
const encoder = new TextEncoder()
|
const encoder = new TextEncoder()
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ export const generateMessageIDV2 = (userId?: string): string => {
|
|||||||
export const generateMessageID = () => '3EB0' + randomBytes(18).toString('hex').toUpperCase()
|
export const generateMessageID = () => '3EB0' + randomBytes(18).toString('hex').toUpperCase()
|
||||||
|
|
||||||
export function bindWaitForEvent<T extends keyof BaileysEventMap>(ev: BaileysEventEmitter, event: T) {
|
export function bindWaitForEvent<T extends keyof BaileysEventMap>(ev: BaileysEventEmitter, event: T) {
|
||||||
return async(check: (u: BaileysEventMap[T]) => boolean | undefined, timeoutMs?: number) => {
|
return async(check: (u: BaileysEventMap[T]) => Promise<boolean | undefined>, timeoutMs?: number) => {
|
||||||
let listener: (item: BaileysEventMap[T]) => void
|
let listener: (item: BaileysEventMap[T]) => void
|
||||||
let closeListener: (state: Partial<ConnectionState>) => void
|
let closeListener: (state: Partial<ConnectionState>) => void
|
||||||
await (
|
await (
|
||||||
@@ -223,8 +223,8 @@ export function bindWaitForEvent<T extends keyof BaileysEventMap>(ev: BaileysEve
|
|||||||
}
|
}
|
||||||
|
|
||||||
ev.on('connection.update', closeListener)
|
ev.on('connection.update', closeListener)
|
||||||
listener = (update) => {
|
listener = async(update) => {
|
||||||
if(check(update)) {
|
if(await check(update)) {
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,15 +35,15 @@ class d {
|
|||||||
var n = this
|
var n = this
|
||||||
return n.add(n.subtract(e, r), t)
|
return n.add(n.subtract(e, r), t)
|
||||||
}
|
}
|
||||||
_addSingle(e, t) {
|
async _addSingle(e, t) {
|
||||||
var r = this
|
var r = this
|
||||||
const n = new Uint8Array(hkdf(Buffer.from(t), o, { info: r.salt })).buffer
|
const n = new Uint8Array(await hkdf(Buffer.from(t), o, { info: r.salt })).buffer
|
||||||
return r.performPointwiseWithOverflow(e, n, ((e, t) => e + t))
|
return r.performPointwiseWithOverflow(e, n, ((e, t) => e + t))
|
||||||
}
|
}
|
||||||
_subtractSingle(e, t) {
|
async _subtractSingle(e, t) {
|
||||||
var r = this
|
var r = this
|
||||||
|
|
||||||
const n = new Uint8Array(hkdf(Buffer.from(t), o, { info: r.salt })).buffer
|
const n = new Uint8Array(await hkdf(Buffer.from(t), o, { info: r.salt })).buffer
|
||||||
return r.performPointwiseWithOverflow(e, n, ((e, t) => e - t))
|
return r.performPointwiseWithOverflow(e, n, ((e, t) => e - t))
|
||||||
}
|
}
|
||||||
performPointwiseWithOverflow(e, t, r) {
|
performPointwiseWithOverflow(e, t, r) {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const hkdfInfoKey = (type: MediaType) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** generates all the keys required to encrypt/decrypt & sign a media message */
|
/** 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) {
|
if(!buffer) {
|
||||||
throw new Boom('Cannot derive from empty media key')
|
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
|
// 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 {
|
return {
|
||||||
iv: expandedMediaKey.slice(0, 16),
|
iv: expandedMediaKey.slice(0, 16),
|
||||||
cipherKey: expandedMediaKey.slice(16, 48),
|
cipherKey: expandedMediaKey.slice(16, 48),
|
||||||
@@ -344,7 +344,7 @@ export const encryptedStream = async(
|
|||||||
logger?.debug('fetched media stream')
|
logger?.debug('fetched media stream')
|
||||||
|
|
||||||
const mediaKey = Crypto.randomBytes(32)
|
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: () => {} })
|
const encWriteStream = new Readable({ read: () => {} })
|
||||||
|
|
||||||
let bodyPath: string | undefined
|
let bodyPath: string | undefined
|
||||||
@@ -458,13 +458,13 @@ export type MediaDownloadOptions = {
|
|||||||
|
|
||||||
export const getUrlFromDirectPath = (directPath: string) => `https://${DEF_HOST}${directPath}`
|
export const getUrlFromDirectPath = (directPath: string) => `https://${DEF_HOST}${directPath}`
|
||||||
|
|
||||||
export const downloadContentFromMessage = (
|
export const downloadContentFromMessage = async(
|
||||||
{ mediaKey, directPath, url }: DownloadableMessage,
|
{ mediaKey, directPath, url }: DownloadableMessage,
|
||||||
type: MediaType,
|
type: MediaType,
|
||||||
opts: MediaDownloadOptions = { }
|
opts: MediaDownloadOptions = { }
|
||||||
) => {
|
) => {
|
||||||
const downloadUrl = url || getUrlFromDirectPath(directPath!)
|
const downloadUrl = url || getUrlFromDirectPath(directPath!)
|
||||||
const keys = getMediaKeys(mediaKey, type)
|
const keys = await getMediaKeys(mediaKey, type)
|
||||||
|
|
||||||
return downloadEncryptedContent(downloadUrl, keys, opts)
|
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
|
* 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,
|
key: proto.IMessageKey,
|
||||||
mediaKey: Buffer | Uint8Array,
|
mediaKey: Buffer | Uint8Array,
|
||||||
meId: string
|
meId: string
|
||||||
@@ -682,7 +682,7 @@ export const encryptMediaRetryRequest = (
|
|||||||
const recpBuffer = proto.ServerErrorReceipt.encode(recp).finish()
|
const recpBuffer = proto.ServerErrorReceipt.encode(recp).finish()
|
||||||
|
|
||||||
const iv = Crypto.randomBytes(12)
|
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 ciphertext = aesEncryptGCM(recpBuffer, retryKey, iv, Buffer.from(key.id!))
|
||||||
|
|
||||||
const req: BinaryNode = {
|
const req: BinaryNode = {
|
||||||
@@ -752,12 +752,12 @@ export const decodeMediaRetryNode = (node: BinaryNode) => {
|
|||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
export const decryptMediaRetryData = (
|
export const decryptMediaRetryData = async(
|
||||||
{ ciphertext, iv }: { ciphertext: Uint8Array, iv: Uint8Array },
|
{ ciphertext, iv }: { ciphertext: Uint8Array, iv: Uint8Array },
|
||||||
mediaKey: Uint8Array,
|
mediaKey: Uint8Array,
|
||||||
msgId: string
|
msgId: string
|
||||||
) => {
|
) => {
|
||||||
const retryKey = getMediaRetryKey(mediaKey)
|
const retryKey = await getMediaRetryKey(mediaKey)
|
||||||
const plaintext = aesDecryptGCM(ciphertext, retryKey, iv, Buffer.from(msgId))
|
const plaintext = aesDecryptGCM(ciphertext, retryKey, iv, Buffer.from(msgId))
|
||||||
return proto.MediaRetryNotification.decode(plaintext)
|
return proto.MediaRetryNotification.decode(plaintext)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,13 +57,13 @@ export const makeNoiseHandler = ({
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
const localHKDF = (data: Uint8Array) => {
|
const localHKDF = async(data: Uint8Array) => {
|
||||||
const key = hkdf(Buffer.from(data), 64, { salt, info: '' })
|
const key = await hkdf(Buffer.from(data), 64, { salt, info: '' })
|
||||||
return [key.slice(0, 32), key.slice(32)]
|
return [key.slice(0, 32), key.slice(32)]
|
||||||
}
|
}
|
||||||
|
|
||||||
const mixIntoKey = (data: Uint8Array) => {
|
const mixIntoKey = async(data: Uint8Array) => {
|
||||||
const [write, read] = localHKDF(data)
|
const [write, read] = await localHKDF(data)
|
||||||
salt = write
|
salt = write
|
||||||
encKey = read
|
encKey = read
|
||||||
decKey = read
|
decKey = read
|
||||||
@@ -71,8 +71,8 @@ export const makeNoiseHandler = ({
|
|||||||
writeCounter = 0
|
writeCounter = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const finishInit = () => {
|
const finishInit = async() => {
|
||||||
const [write, read] = localHKDF(new Uint8Array(0))
|
const [write, read] = await localHKDF(new Uint8Array(0))
|
||||||
encKey = write
|
encKey = write
|
||||||
decKey = read
|
decKey = read
|
||||||
hash = Buffer.from([])
|
hash = Buffer.from([])
|
||||||
@@ -82,7 +82,7 @@ export const makeNoiseHandler = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = Buffer.from(NOISE_MODE)
|
const data = Buffer.from(NOISE_MODE)
|
||||||
let hash = Buffer.from(data.byteLength === 32 ? data : sha256(data))
|
let hash = data.byteLength === 32 ? data : sha256(data)
|
||||||
let salt = hash
|
let salt = hash
|
||||||
let encKey = hash
|
let encKey = hash
|
||||||
let decKey = hash
|
let decKey = hash
|
||||||
@@ -102,12 +102,12 @@ export const makeNoiseHandler = ({
|
|||||||
authenticate,
|
authenticate,
|
||||||
mixIntoKey,
|
mixIntoKey,
|
||||||
finishInit,
|
finishInit,
|
||||||
processHandshake: ({ serverHello }: proto.HandshakeMessage, noiseKey: KeyPair) => {
|
processHandshake: async({ serverHello }: proto.HandshakeMessage, noiseKey: KeyPair) => {
|
||||||
authenticate(serverHello!.ephemeral!)
|
authenticate(serverHello!.ephemeral!)
|
||||||
mixIntoKey(Curve.sharedKey(privateKey, serverHello!.ephemeral!))
|
await mixIntoKey(Curve.sharedKey(privateKey, serverHello!.ephemeral!))
|
||||||
|
|
||||||
const decStaticContent = decrypt(serverHello!.static!)
|
const decStaticContent = decrypt(serverHello!.static!)
|
||||||
mixIntoKey(Curve.sharedKey(privateKey, decStaticContent))
|
await mixIntoKey(Curve.sharedKey(privateKey, decStaticContent))
|
||||||
|
|
||||||
const certDecoded = decrypt(serverHello!.payload!)
|
const certDecoded = decrypt(serverHello!.payload!)
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ export const makeNoiseHandler = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const keyEnc = encrypt(noiseKey.public)
|
const keyEnc = encrypt(noiseKey.public)
|
||||||
mixIntoKey(Curve.sharedKey(noiseKey.private, serverHello!.ephemeral!))
|
await mixIntoKey(Curve.sharedKey(noiseKey.private, serverHello!.ephemeral!))
|
||||||
|
|
||||||
return keyEnc
|
return keyEnc
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3461,11 +3461,6 @@ functions-have-names@^1.2.3:
|
|||||||
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
|
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
|
||||||
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
||||||
|
|
||||||
futoin-hkdf@^1.5.1:
|
|
||||||
version "1.5.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/futoin-hkdf/-/futoin-hkdf-1.5.3.tgz#6c8024f2e1429da086d4e18289ef2239ad33ee35"
|
|
||||||
integrity sha512-SewY5KdMpaoCeh7jachEWFsh1nNlaDjNHZXWqL5IGwtpEYHTgkr2+AMCgNwKWkcc0wpSYrZfR7he4WdmHFtDxQ==
|
|
||||||
|
|
||||||
gensync@^1.0.0-beta.2:
|
gensync@^1.0.0-beta.2:
|
||||||
version "1.0.0-beta.2"
|
version "1.0.0-beta.2"
|
||||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||||
|
|||||||
Reference in New Issue
Block a user