import { from_hex } from 'libsodium-wrappers-sumo'; import { concatUInt8Array, LibSodiumWrappers } from '../crypto'; export function generateBlindingFactor(serverPk: string, sodium: LibSodiumWrappers) { const hexServerPk = from_hex(serverPk); const serverPkHash = sodium.crypto_generichash(64, hexServerPk); if (!serverPkHash.length) { throw new Error('generateBlindingFactor: crypto_generichash failed'); } // Reduce the server public key into an ed25519 scalar (`k`) const k = sodium.crypto_core_ed25519_scalar_reduce(serverPkHash); return k; } export function combineKeys( lhsKeyBytes: Uint8Array, rhsKeyBytes: Uint8Array, sodium: LibSodiumWrappers ) { return sodium.crypto_scalarmult_ed25519_noclamp(lhsKeyBytes, rhsKeyBytes); } // Calculate a shared secret for a message from A to B: // // BLAKE2b(a kB || kA || kB) // // The receiver can calculate the same value via: // // BLAKE2b(b kA || kA || kB) export function sharedBlindedEncryptionKey({ fromBlindedPublicKey, otherBlindedPublicKey, secretKey, sodium, toBlindedPublicKey, }: { secretKey: Uint8Array; otherBlindedPublicKey: Uint8Array; fromBlindedPublicKey: Uint8Array; toBlindedPublicKey: Uint8Array; sodium: LibSodiumWrappers; }) { const aBytes = generatePrivateKeyScalar(secretKey, sodium); const combinedKeyBytes = combineKeys(aBytes, otherBlindedPublicKey, sodium); return sodium.crypto_generichash( 32, concatUInt8Array(combinedKeyBytes, fromBlindedPublicKey, toBlindedPublicKey) ); } // Calculate k*a. To get 'a' (the Ed25519 private key scalar) we call the sodium function to // convert to an *x* secret key, which seems wrong--but isn't because converted keys use the // same secret scalar secret (and so this is just the most convenient way to get 'a' out of // a sodium Ed25519 secret key) export function generatePrivateKeyScalar(secretKey: Uint8Array, sodium: LibSodiumWrappers) { return sodium.crypto_sign_ed25519_sk_to_curve25519(secretKey); } export function toX25519(ed25519PublicKey: Uint8Array, sodium: LibSodiumWrappers) { return sodium.crypto_sign_ed25519_pk_to_curve25519(ed25519PublicKey); }