Files
simplexmq/src/Simplex/Messaging/Crypto/SNTRUP761.hs
T
Evgeny @ SimpleX Chat 326d6cc559 code comments
2026-03-11 12:17:46 +00:00

40 lines
1.6 KiB
Haskell

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
-- spec: spec/modules/Simplex/Messaging/Crypto/SNTRUP761.md
module Simplex.Messaging.Crypto.SNTRUP761
( KEMHybridSecret (..),
kcbDecrypt,
kcbEncrypt,
kemHybridSecret,
) where
import Crypto.Hash (Digest, SHA3_256, hash)
import Data.ByteArray (ScrubbedBytes)
import qualified Data.ByteArray as BA
import Data.ByteString (ByteString)
import Simplex.Messaging.Crypto
import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Crypto.SNTRUP761.Bindings
-- Hybrid shared secret for crypto_box is defined as SHA256(DHSecret || KEMSharedKey),
-- similar to https://datatracker.ietf.org/doc/draft-josefsson-ntruprime-hybrid/
newtype KEMHybridSecret = KEMHybridSecret ScrubbedBytes
-- spec: spec/modules/Simplex/Messaging/Crypto/SNTRUP761.md#kcbencrypt--kcbdecrypt
-- | NaCl @crypto_box@ decrypt with a shared hybrid DH + KEM secret and 192-bit nonce.
kcbDecrypt :: KEMHybridSecret -> CbNonce -> ByteString -> Either CryptoError ByteString
kcbDecrypt (KEMHybridSecret k) = sbDecrypt_ k
-- | NaCl @crypto_box@ encrypt with a shared hybrid DH + KEM secret and 192-bit nonce.
kcbEncrypt :: KEMHybridSecret -> CbNonce -> ByteString -> Int -> Either CryptoError ByteString
kcbEncrypt (KEMHybridSecret k) = sbEncrypt_ k
-- spec: spec/modules/Simplex/Messaging/Crypto/SNTRUP761.md#kemhybridsecret
kemHybridSecret :: PublicKeyX25519 -> PrivateKeyX25519 -> KEMSharedKey -> KEMHybridSecret
kemHybridSecret k pk (KEMSharedKey kem) =
let DhSecretX25519 dh = C.dh' k pk
in KEMHybridSecret $ BA.convert (hash $ BA.convert dh <> kem :: Digest SHA3_256)