BOLT8.hs (25366B)
1 {-# OPTIONS_HADDOCK prune #-} 2 {-# LANGUAGE BangPatterns #-} 3 {-# LANGUAGE DeriveGeneric #-} 4 {-# LANGUAGE OverloadedStrings #-} 5 6 -- | 7 -- Module: Lightning.Protocol.BOLT8 8 -- Copyright: (c) 2025 Jared Tobin 9 -- License: MIT 10 -- Maintainer: Jared Tobin <jared@ppad.tech> 11 -- 12 -- Encrypted and authenticated transport for the Lightning Network, per 13 -- [BOLT #8](https://github.com/lightning/bolts/blob/master/08-transport.md): 14 -- the @Noise_XK_secp256k1_ChaChaPoly_SHA256@ handshake, followed by 15 -- length-prefixed, authenticated encryption of messages. 16 -- 17 -- The library is pure; reading from and writing to the network is up 18 -- to the caller. 19 -- 20 -- = Handshake 21 -- 22 -- The /initiator/ knows the responder's static public key in advance. 23 -- It sends act one ('act1'), receives act two, and replies with act 24 -- three ('act3'). The /responder/ receives act one, replies with act two 25 -- ('act2'), and receives act three ('finalize'), which authenticates 26 -- the initiator's static key. Both sides end up with a t'Handshake'. 27 -- 28 -- >>> :set -XOverloadedStrings 29 -- >>> import qualified Data.ByteString as BS 30 -- >>> let Just i = keypair (BS.replicate 32 0x11) 31 -- >>> let Just r = keypair (BS.replicate 32 0x21) 32 -- >>> -- initiator, knowing r's public key; entropy must be random! 33 -- >>> let Right (msg1, i_hs) = act1 i (keypair_pub r) (BS.replicate 32 0x12) 34 -- >>> -- responder 35 -- >>> let Right (msg2, r_hs) = act2 r (BS.replicate 32 0x22) msg1 36 -- >>> -- initiator 37 -- >>> let Right (msg3, i_res) = act3 i_hs msg2 38 -- >>> -- responder 39 -- >>> let Right r_res = finalize r_hs msg3 40 -- >>> handshake_remote_static r_res == keypair_pub i 41 -- True 42 -- 43 -- = Transport 44 -- 45 -- A t'Handshake' carries a t'Sender' for outgoing messages and a 46 -- t'Receiver' for incoming ones. They are independent, so a writer 47 -- thread can own the t'Sender' and a reader thread the t'Receiver'. 48 -- 49 -- >>> let Right (ct, i_snd) = encrypt (handshake_sender i_res) "hello" 50 -- >>> fmap fst (decrypt (handshake_receiver r_res) ct) 51 -- Right "hello" 52 -- 53 -- On a byte stream, read exactly 18 bytes and pass them to 54 -- 'decrypt_header', which returns the number of bytes to read next; 55 -- then read exactly that many bytes and pass them to 'decrypt_body'. 56 -- 'decrypt' does both for a buffer holding exactly one frame. 57 -- 58 -- Keys rotate every 1000 nonces, i.e. every 500 messages in each 59 -- direction; this is handled internally. Messages are at most 65535 60 -- bytes. 61 -- 62 -- = Security 63 -- 64 -- * __Use each state exactly once.__ Every function that takes an 65 -- t'Initiator', t'Responder', t'Sender', t'Receiver' or t'Pending' 66 -- returns the next state, and the caller must continue with that. 67 -- States are ordinary immutable values, so nothing stops an old one 68 -- from being used again, and doing so is catastrophic: encrypting 69 -- twice with the same t'Sender' reuses a nonce, which reveals the XOR 70 -- of the two plaintexts and allows forgeries, and decrypting with an 71 -- old t'Receiver' accepts replayed frames. 72 -- 73 -- * __Ephemeral entropy must be fresh.__ The 32 bytes passed to 'act1' 74 -- and 'act2' are used directly as the ephemeral secret key. They 75 -- must come from a cryptographically secure random source, be 76 -- uniformly random, and never be reused. 77 -- 78 -- * __Any error is fatal.__ BOLT #8 requires terminating the 79 -- connection on any handshake or transport failure. Don't retry with 80 -- the previous state. The one exception is 'encrypt' rejecting an 81 -- oversized message, which advances nothing. 82 83 module Lightning.Protocol.BOLT8 ( 84 -- * Keys 85 Keypair 86 , keypair 87 , keypair_pub 88 , Pub 89 , parse_pub 90 , serialize_pub 91 92 -- * Handshake 93 , Handshake 94 , handshake_sender 95 , handshake_receiver 96 , handshake_remote_static 97 98 -- ** Initiator 99 , Initiator 100 , act1 101 , act3 102 103 -- ** Responder 104 , Responder 105 , act2 106 , finalize 107 108 -- * Transport 109 , Sender 110 , encrypt 111 , Receiver 112 , decrypt 113 , Pending 114 , decrypt_header 115 , decrypt_body 116 117 -- * Errors 118 , Error(..) 119 ) where 120 121 import Control.DeepSeq (NFData(..)) 122 import Control.Monad (guard, unless) 123 import qualified Crypto.AEAD.ChaCha20Poly1305 as AEAD 124 import qualified Crypto.Curve.Secp256k1 as Secp256k1 125 import qualified Crypto.Hash.SHA256 as SHA256 126 import qualified Crypto.KDF.HMAC as HKDF 127 import Data.Bits (unsafeShiftR, (.&.)) 128 import qualified Data.ByteString as BS 129 import qualified Data.ByteString.Unsafe as BU 130 import Data.Word (Word8, Word16, Word64) 131 import GHC.Generics (Generic) 132 133 -- keys ----------------------------------------------------------------------- 134 135 -- A secret key: 32 bytes encoding a valid secp256k1 scalar. 136 newtype Sec = Sec BS.ByteString 137 138 -- | A secp256k1 public key. 139 -- 140 -- 'Show' renders the 33-byte compressed encoding in hex. 141 newtype Pub = Pub Secp256k1.Projective 142 143 instance Eq Pub where 144 Pub a == Pub b = 145 Secp256k1.serialize_point a == Secp256k1.serialize_point b 146 147 instance Show Pub where 148 showsPrec d p = showParen (d > 10) $ 149 showString "Pub " . shows (hex (serialize_pub p)) 150 151 instance NFData Pub where 152 rnf (Pub p) = p `seq` () 153 154 -- | A secp256k1 keypair: a secret key and its public key. 155 -- 156 -- Has no 'Show' or 'Eq' instance, as it contains secret material. 157 data Keypair = Keypair !Sec !Pub 158 159 instance NFData Keypair where 160 rnf (Keypair (Sec s) p) = s `seq` rnf p 161 162 -- | Construct a keypair from a 32-byte secret key. 163 -- 164 -- The bytes are used directly as the secret key, so they must be 165 -- uniformly random and kept secret. Returns 'Nothing' if the input 166 -- is not 32 bytes, or is not a valid secp256k1 secret key (zero, or 167 -- not less than the curve order). 168 -- 169 -- >>> import Data.Maybe (isJust) 170 -- >>> isJust (keypair (BS.replicate 32 0x11)) 171 -- True 172 -- >>> isJust (keypair (BS.replicate 32 0x00)) 173 -- False 174 keypair :: BS.ByteString -> Maybe Keypair 175 keypair sec = do 176 guard (BS.length sec == 32) 177 k <- Secp256k1.parse_int256 sec 178 p <- Secp256k1.derive_pub k 179 pure $! Keypair (Sec sec) (Pub p) 180 181 -- | The public key of a keypair. 182 -- 183 -- >>> let Just r = keypair (BS.replicate 32 0x21) 184 -- >>> keypair_pub r 185 -- Pub "028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7" 186 keypair_pub :: Keypair -> Pub 187 keypair_pub (Keypair _ p) = p 188 189 -- | Parse a 33-byte compressed public key. 190 -- 191 -- >>> let Just r = keypair (BS.replicate 32 0x21) 192 -- >>> parse_pub (serialize_pub (keypair_pub r)) == Just (keypair_pub r) 193 -- True 194 -- >>> parse_pub (BS.replicate 33 0x04) 195 -- Nothing 196 parse_pub :: BS.ByteString -> Maybe Pub 197 parse_pub bs = do 198 guard (BS.length bs == 33) 199 p <- Secp256k1.parse_point bs 200 pure (Pub p) 201 202 -- | Serialize a public key in 33-byte compressed form. 203 -- 204 -- >>> let Just r = keypair (BS.replicate 32 0x21) 205 -- >>> BS.length (serialize_pub (keypair_pub r)) 206 -- 33 207 serialize_pub :: Pub -> BS.ByteString 208 serialize_pub (Pub p) = Secp256k1.serialize_point p 209 210 -- handshake state ------------------------------------------------------------ 211 212 -- | The initiator's handshake state between acts one and three. 213 -- 214 -- Produced by 'act1' and consumed by 'act3'. Contains secret 215 -- material; use it once. 216 data Initiator = Initiator 217 {-# UNPACK #-} !BS.ByteString -- handshake hash 218 {-# UNPACK #-} !BS.ByteString -- chaining key 219 !Sec -- ephemeral secret 220 !Keypair -- local static keypair 221 !Pub -- remote static public key 222 223 instance NFData Initiator where 224 rnf (Initiator h ck (Sec e) s rs) = 225 h `seq` ck `seq` e `seq` rnf s `seq` rnf rs 226 227 -- | The responder's handshake state between acts two and three. 228 -- 229 -- Produced by 'act2' and consumed by 'finalize'. Contains secret 230 -- material; use it once. 231 data Responder = Responder 232 {-# UNPACK #-} !BS.ByteString -- handshake hash 233 {-# UNPACK #-} !BS.ByteString -- chaining key 234 {-# UNPACK #-} !BS.ByteString -- temp_k2 235 !Sec -- ephemeral secret 236 237 instance NFData Responder where 238 rnf (Responder h ck k (Sec e)) = h `seq` ck `seq` k `seq` e `seq` () 239 240 -- | The result of a successful handshake: the initial transport 241 -- states and the remote party's authenticated static public key. 242 -- 243 -- Take the t'Sender' and t'Receiver' out once, right after the 244 -- handshake, and don't keep the t'Handshake' around: it always yields 245 -- the /initial/ states, and encrypting with the initial t'Sender' 246 -- a second time reuses a nonce. 247 data Handshake = Handshake !Sender !Receiver !Pub 248 249 instance NFData Handshake where 250 rnf (Handshake s r p) = rnf s `seq` rnf r `seq` rnf p 251 252 -- | The initial t'Sender', for encrypting outgoing messages. 253 -- 254 -- Call this once per handshake. Every call returns the same initial 255 -- state, so encrypting with the result of a second call reuses a 256 -- nonce. 257 handshake_sender :: Handshake -> Sender 258 handshake_sender (Handshake s _ _) = s 259 260 -- | The initial t'Receiver', for decrypting incoming messages. 261 -- 262 -- Call this once per handshake. Every call returns the same initial 263 -- state, so decrypting with the result of a second call accepts 264 -- replayed frames. 265 handshake_receiver :: Handshake -> Receiver 266 handshake_receiver (Handshake _ r _) = r 267 268 -- | The remote party's static public key, authenticated by the 269 -- handshake. For the initiator, this is the key passed to 'act1'. 270 handshake_remote_static :: Handshake -> Pub 271 handshake_remote_static (Handshake _ _ p) = p 272 273 -- transport state ------------------------------------------------------------ 274 275 -- One direction's cipher state. 276 data Cipher = Cipher 277 {-# UNPACK #-} !BS.ByteString -- key 278 {-# UNPACK #-} !Word64 -- nonce, always < 1000 279 {-# UNPACK #-} !BS.ByteString -- chaining key 280 281 instance NFData Cipher where 282 rnf (Cipher k n ck) = k `seq` n `seq` ck `seq` () 283 284 -- | State for encrypting outgoing messages. 285 -- 286 -- Each 'encrypt' returns the next t'Sender'. Never use a t'Sender' 287 -- twice: doing so reuses a nonce. 288 newtype Sender = Sender Cipher 289 290 instance NFData Sender where 291 rnf (Sender c) = rnf c 292 293 -- | State for decrypting incoming messages. 294 -- 295 -- Each 'decrypt' or 'decrypt_header' consumes the t'Receiver'. 296 -- Never use a t'Receiver' twice: doing so accepts replayed frames. 297 newtype Receiver = Receiver Cipher 298 299 instance NFData Receiver where 300 rnf (Receiver c) = rnf c 301 302 -- | A t'Receiver' that has decrypted a frame header and awaits the 303 -- frame body. 304 -- 305 -- Produced by 'decrypt_header' and consumed by 'decrypt_body'. Use 306 -- it once. 307 data Pending = Pending {-# UNPACK #-} !Int !Cipher 308 309 instance NFData Pending where 310 rnf (Pending n c) = n `seq` rnf c 311 312 -- errors --------------------------------------------------------------------- 313 314 -- | Handshake and transport errors. 315 -- 316 -- Any error is fatal for the connection. 317 data Error = 318 InvalidEntropy 319 -- ^ ephemeral entropy is not a valid secret key 320 | InvalidLength 321 -- ^ input of the wrong length, or a payload over 65535 bytes 322 | InvalidVersion 323 -- ^ unknown handshake version 324 | InvalidPub 325 -- ^ invalid public key in a handshake message 326 | InvalidMAC 327 -- ^ authentication failed 328 deriving (Eq, Show, Generic) 329 330 instance NFData Error 331 332 -- protocol constants --------------------------------------------------------- 333 334 _PROTOCOL_NAME :: BS.ByteString 335 _PROTOCOL_NAME = "Noise_XK_secp256k1_ChaChaPoly_SHA256" 336 337 _PROLOGUE :: BS.ByteString 338 _PROLOGUE = "lightning" 339 340 -- cryptographic primitives --------------------------------------------------- 341 342 -- ECDH as specified by BOLT #8: SHA256 of the compressed shared point. 343 -- 344 -- 'Nothing' is unreachable for a valid secret key and a parsed point. 345 ecdh :: Sec -> Pub -> Maybe BS.ByteString 346 ecdh (Sec sec) (Pub pub) = do 347 k <- Secp256k1.parse_int256 sec 348 pt <- Secp256k1.mul pub k 349 pure (SHA256.hash (Secp256k1.serialize_point pt)) 350 351 -- h' = SHA256(h || dat) 352 mix_hash :: BS.ByteString -> BS.ByteString -> BS.ByteString 353 mix_hash h dat = SHA256.hash (h <> dat) 354 355 -- (ck', k) = HKDF(ck, ikm), with ck as salt and empty info. 356 -- 357 -- HKDF limits output to 255 * hashlen bytes (8160 for SHA256), so 358 -- 'Nothing' is impossible for the 64 bytes requested here. 359 mix_key 360 :: BS.ByteString 361 -> BS.ByteString 362 -> (BS.ByteString, BS.ByteString) 363 mix_key ck ikm = 364 case HKDF.derive hmac ck mempty 64 ikm of 365 Nothing -> 366 error "ppad-bolt8: internal error, please report a bug!" 367 Just output -> BS.splitAt 32 output 368 where 369 hmac k b = case SHA256.hmac k b of 370 SHA256.MAC mac -> mac 371 372 -- ChaCha20-Poly1305 encryption, returning ciphertext || MAC. 373 -- 374 -- Keys are always 32 bytes (halves of HKDF output), nonces always 12 375 -- bytes, and plaintexts at most 65535 bytes (far below the ChaCha20 376 -- counter limit), so encryption cannot fail. 377 encrypt_with_ad 378 :: BS.ByteString -- ^ key (32 bytes) 379 -> Word64 -- ^ nonce 380 -> BS.ByteString -- ^ associated data 381 -> BS.ByteString -- ^ plaintext 382 -> BS.ByteString 383 encrypt_with_ad key n ad pt = 384 case AEAD.encrypt ad key (encode_nonce n) pt of 385 Left _ -> 386 error "ppad-bolt8: internal error, please report a bug!" 387 Right (ct, mac) -> ct <> mac 388 389 -- ChaCha20-Poly1305 decryption of ciphertext || MAC. 390 decrypt_with_ad 391 :: BS.ByteString -- ^ key (32 bytes) 392 -> Word64 -- ^ nonce 393 -> BS.ByteString -- ^ associated data 394 -> BS.ByteString -- ^ ciphertext || mac 395 -> Maybe BS.ByteString -- ^ plaintext 396 decrypt_with_ad key n ad ctmac 397 | BS.length ctmac < 16 = Nothing 398 | otherwise = 399 let (ct, mac) = BS.splitAt (BS.length ctmac - 16) ctmac 400 in case AEAD.decrypt ad key (encode_nonce n) (ct, mac) of 401 Left _ -> Nothing 402 Right pt -> Just pt 403 404 -- 96-bit nonce: 4 zero bytes followed by the 64-bit nonce, little-endian 405 encode_nonce :: Word64 -> BS.ByteString 406 encode_nonce n = BS.replicate 4 0x00 <> BS.pack [ 407 fi n 408 , fi (unsafeShiftR n 8) 409 , fi (unsafeShiftR n 16) 410 , fi (unsafeShiftR n 24) 411 , fi (unsafeShiftR n 32) 412 , fi (unsafeShiftR n 40) 413 , fi (unsafeShiftR n 48) 414 , fi (unsafeShiftR n 56) 415 ] 416 417 -- big-endian 16-bit encoding 418 encode_be16 :: Word16 -> BS.ByteString 419 encode_be16 n = BS.pack [fi (unsafeShiftR n 8), fi n] 420 421 -- big-endian 16-bit decoding of exactly two bytes 422 decode_be16 :: BS.ByteString -> Maybe Word16 423 decode_be16 bs 424 | BS.length bs /= 2 = Nothing 425 | otherwise = 426 let !b0 = BU.unsafeIndex bs 0 427 !b1 = BU.unsafeIndex bs 1 428 in Just (fi b0 * 0x100 + fi b1) 429 430 -- handshake ------------------------------------------------------------------ 431 432 -- Initial (h, ck), given the responder's static public key: 433 -- 434 -- h = SHA256(protocol_name); ck = h 435 -- h = SHA256(h || prologue) 436 -- h = SHA256(h || rs.pub) 437 initial_state :: Pub -> (BS.ByteString, BS.ByteString) 438 initial_state rs = 439 let !h0 = SHA256.hash _PROTOCOL_NAME 440 !h1 = mix_hash h0 _PROLOGUE 441 !h2 = mix_hash h1 (serialize_pub rs) 442 in (h2, h0) 443 444 -- Split a 50-byte act one or act two message into its ephemeral public 445 -- key and MAC, checking length and version. 446 parse_act :: BS.ByteString -> Either Error (BS.ByteString, BS.ByteString) 447 parse_act msg = do 448 require (BS.length msg == 50) InvalidLength 449 require (BU.unsafeHead msg == 0x00) InvalidVersion 450 let !(e, c) = BS.splitAt 33 (BU.unsafeTail msg) 451 pure (e, c) 452 453 -- | Initiator: produce act one (50 bytes). 454 -- 455 -- Takes the local static keypair, the responder's static public key, 456 -- and 32 bytes of entropy for the ephemeral key. Returns act one and 457 -- the state for 'act3'. 458 -- 459 -- The entropy is used directly as the ephemeral secret key. It must 460 -- be fresh, uniformly random output of a cryptographically secure 461 -- random source, and must never be reused. Fails with 462 -- 'InvalidEntropy' if it is not a valid secret key. 463 -- 464 -- >>> let Just i = keypair (BS.replicate 32 0x11) 465 -- >>> let Just r = keypair (BS.replicate 32 0x21) 466 -- >>> let ent = BS.replicate 32 0x12 -- use random bytes in practice 467 -- >>> fmap (BS.length . fst) (act1 i (keypair_pub r) ent) 468 -- Right 50 469 act1 470 :: Keypair -- ^ local static keypair 471 -> Pub -- ^ responder's static public key 472 -> BS.ByteString -- ^ 32 bytes of fresh entropy 473 -> Either Error (BS.ByteString, Initiator) 474 act1 s rs ent = do 475 Keypair e_sec e_pub <- note InvalidEntropy (keypair ent) 476 let !(h0, ck0) = initial_state rs 477 !e_bytes = serialize_pub e_pub 478 !h1 = mix_hash h0 e_bytes 479 es <- note InvalidPub (ecdh e_sec rs) 480 let !(ck1, temp_k1) = mix_key ck0 es 481 !c = encrypt_with_ad temp_k1 0 h1 BS.empty 482 !h2 = mix_hash h1 c 483 !msg = BS.cons 0x00 (e_bytes <> c) 484 pure (msg, Initiator h2 ck1 e_sec s rs) 485 486 -- | Responder: process act one and produce act two (50 bytes). 487 -- 488 -- Takes the local static keypair, 32 bytes of entropy for the 489 -- ephemeral key, and act one. Returns act two and the state for 490 -- 'finalize'. 491 -- 492 -- The entropy is used directly as the ephemeral secret key. It must 493 -- be fresh, uniformly random output of a cryptographically secure 494 -- random source, and must never be reused. Fails with 495 -- 'InvalidEntropy' if it is not a valid secret key. 496 -- 497 -- Any error means the connection must be terminated. 498 -- 499 -- >>> let Just i = keypair (BS.replicate 32 0x11) 500 -- >>> let Just r = keypair (BS.replicate 32 0x21) 501 -- >>> let Right (msg1, _) = act1 i (keypair_pub r) (BS.replicate 32 0x12) 502 -- >>> fmap (BS.length . fst) (act2 r (BS.replicate 32 0x22) msg1) 503 -- Right 50 504 -- >>> fmap fst (act2 r (BS.replicate 32 0x22) (BS.take 49 msg1)) 505 -- Left InvalidLength 506 act2 507 :: Keypair -- ^ local static keypair 508 -> BS.ByteString -- ^ 32 bytes of fresh entropy 509 -> BS.ByteString -- ^ act one 510 -> Either Error (BS.ByteString, Responder) 511 act2 (Keypair s_sec s_pub) ent msg1 = do 512 (re_bytes, c) <- parse_act msg1 513 re <- note InvalidPub (parse_pub re_bytes) 514 Keypair e_sec e_pub <- note InvalidEntropy (keypair ent) 515 let !(h0, ck0) = initial_state s_pub 516 !h1 = mix_hash h0 re_bytes 517 es <- note InvalidPub (ecdh s_sec re) 518 let !(ck1, temp_k1) = mix_key ck0 es 519 _ <- note InvalidMAC (decrypt_with_ad temp_k1 0 h1 c) 520 let !h2 = mix_hash h1 c 521 !e_bytes = serialize_pub e_pub 522 !h3 = mix_hash h2 e_bytes 523 ee <- note InvalidPub (ecdh e_sec re) 524 let !(ck2, temp_k2) = mix_key ck1 ee 525 !c2 = encrypt_with_ad temp_k2 0 h3 BS.empty 526 !h4 = mix_hash h3 c2 527 !msg = BS.cons 0x00 (e_bytes <> c2) 528 pure (msg, Responder h4 ck2 temp_k2 e_sec) 529 530 -- | Initiator: process act two and produce act three (66 bytes), 531 -- completing the handshake. 532 -- 533 -- Any error means the connection must be terminated. 534 -- 535 -- Continuing the module-level example: 536 -- 537 -- >>> fmap (BS.length . fst) (act3 i_hs msg2) 538 -- Right 66 539 act3 540 :: Initiator -- ^ state from 'act1' 541 -> BS.ByteString -- ^ act two 542 -> Either Error (BS.ByteString, Handshake) 543 act3 (Initiator h ck e_sec (Keypair s_sec s_pub) rs) msg2 = do 544 (re_bytes, c) <- parse_act msg2 545 re <- note InvalidPub (parse_pub re_bytes) 546 let !h1 = mix_hash h re_bytes 547 ee <- note InvalidPub (ecdh e_sec re) 548 let !(ck1, temp_k2) = mix_key ck ee 549 _ <- note InvalidMAC (decrypt_with_ad temp_k2 0 h1 c) 550 let !h2 = mix_hash h1 c 551 !c3 = encrypt_with_ad temp_k2 1 h2 (serialize_pub s_pub) 552 !h3 = mix_hash h2 c3 553 se <- note InvalidPub (ecdh s_sec re) 554 let !(ck2, temp_k3) = mix_key ck1 se 555 !t = encrypt_with_ad temp_k3 0 h3 BS.empty 556 !(sk, rk) = mix_key ck2 BS.empty 557 !msg = BS.cons 0x00 (c3 <> t) 558 !hs = Handshake (Sender (Cipher sk 0 ck2)) 559 (Receiver (Cipher rk 0 ck2)) rs 560 pure (msg, hs) 561 562 -- | Responder: process act three, completing the handshake and 563 -- authenticating the initiator's static public key. 564 -- 565 -- Any error means the connection must be terminated. 566 -- 567 -- Continuing the module-level example: 568 -- 569 -- >>> let Right r_res' = finalize r_hs msg3 570 -- >>> handshake_remote_static r_res' == keypair_pub i 571 -- True 572 finalize 573 :: Responder -- ^ state from 'act2' 574 -> BS.ByteString -- ^ act three 575 -> Either Error Handshake 576 finalize (Responder h ck temp_k2 e_sec) msg3 = do 577 require (BS.length msg3 == 66) InvalidLength 578 require (BU.unsafeHead msg3 == 0x00) InvalidVersion 579 let !(c, t) = BS.splitAt 49 (BU.unsafeTail msg3) 580 rs_bytes <- note InvalidMAC (decrypt_with_ad temp_k2 1 h c) 581 rs <- note InvalidPub (parse_pub rs_bytes) 582 let !h1 = mix_hash h c 583 se <- note InvalidPub (ecdh e_sec rs) 584 let !(ck1, temp_k3) = mix_key ck se 585 _ <- note InvalidMAC (decrypt_with_ad temp_k3 0 h1 t) 586 let !(rk, sk) = mix_key ck1 BS.empty 587 pure (Handshake (Sender (Cipher sk 0 ck1)) (Receiver (Cipher rk 0 ck1)) rs) 588 589 -- transport ------------------------------------------------------------------ 590 591 -- Encrypt under the current key and nonce, then advance. 592 seal :: Cipher -> BS.ByteString -> (BS.ByteString, Cipher) 593 seal c@(Cipher k n _) pt = 594 let !ct = encrypt_with_ad k n BS.empty pt 595 in (ct, step c) 596 597 -- Decrypt under the current key and nonce, then advance. 598 open :: Cipher -> BS.ByteString -> Maybe (BS.ByteString, Cipher) 599 open c@(Cipher k n _) ct = do 600 pt <- decrypt_with_ad k n BS.empty ct 601 pure (pt, step c) 602 603 -- Increment the nonce, rotating the key once it reaches 1000: 604 -- 605 -- (ck', k') = HKDF(ck, k), n' = 0 606 step :: Cipher -> Cipher 607 step (Cipher k n ck) 608 | n' >= 1000 = 609 let !(ck', k') = mix_key ck k 610 in Cipher k' 0 ck' 611 | otherwise = Cipher k n' ck 612 where 613 !n' = n + 1 614 615 -- | Encrypt a message of at most 65535 bytes. 616 -- 617 -- Returns the frame to send (the message length plus 34 bytes) and 618 -- the next t'Sender', which must be used for the following message. 619 -- Encrypting with the same t'Sender' twice reuses a nonce and breaks 620 -- confidentiality and authenticity. 621 -- 622 -- Fails only with 'InvalidLength', for an oversized message. Nothing 623 -- is encrypted in that case, so the given t'Sender' remains the 624 -- current one and the connection can continue. 625 -- 626 -- Continuing the module-level example: 627 -- 628 -- >>> fmap (BS.length . fst) (encrypt i_snd "hello") 629 -- Right 39 630 -- >>> fmap fst (encrypt i_snd (BS.replicate 65536 0x00)) 631 -- Left InvalidLength 632 encrypt 633 :: Sender -- ^ current state 634 -> BS.ByteString -- ^ message 635 -> Either Error (BS.ByteString, Sender) 636 encrypt (Sender c0) m = do 637 let !len = BS.length m 638 require (len <= 65535) InvalidLength 639 let !(lc, c1) = seal c0 (encode_be16 (fi len)) 640 !(bc, c2) = seal c1 m 641 pure (lc <> bc, Sender c2) 642 643 -- | Decrypt a buffer holding exactly one frame. 644 -- 645 -- Returns the message and the next t'Receiver'. Fails with 646 -- 'InvalidLength' if the buffer is not exactly one frame, and with 647 -- 'InvalidMAC' if authentication fails. Any error means the 648 -- connection must be terminated. 649 -- 650 -- Continuing the module-level example: 651 -- 652 -- >>> fmap fst (decrypt (handshake_receiver r_res) ct) 653 -- Right "hello" 654 -- >>> fmap fst (decrypt (handshake_receiver r_res) (BS.take 38 ct)) 655 -- Left InvalidLength 656 decrypt 657 :: Receiver -- ^ current state 658 -> BS.ByteString -- ^ one frame 659 -> Either Error (BS.ByteString, Receiver) 660 decrypt r frame = do 661 let !(lc, c) = BS.splitAt 18 frame 662 (_, p) <- decrypt_header r lc 663 decrypt_body p c 664 665 -- | Decrypt the 18-byte header (encrypted length and its MAC) at the 666 -- start of a frame. 667 -- 668 -- Returns the number of bytes in the rest of the frame (the message 669 -- length plus a 16-byte MAC), which the caller should read exactly, 670 -- and the state for 'decrypt_body'. Fails with 'InvalidLength' if 671 -- the input is not 18 bytes, and with 'InvalidMAC' if 672 -- authentication fails. Any error means the connection must be 673 -- terminated. 674 -- 675 -- Continuing the module-level example: 676 -- 677 -- >>> fmap fst (decrypt_header (handshake_receiver r_res) (BS.take 18 ct)) 678 -- Right 21 679 decrypt_header 680 :: Receiver -- ^ current state 681 -> BS.ByteString -- ^ 18-byte header 682 -> Either Error (Int, Pending) 683 decrypt_header (Receiver c0) lc = do 684 require (BS.length lc == 18) InvalidLength 685 (l, c1) <- note InvalidMAC (open c0 lc) 686 len <- note InvalidLength (decode_be16 l) 687 let !body = fi len + 16 688 pure (body, Pending body c1) 689 690 -- | Decrypt the rest of a frame, following 'decrypt_header'. 691 -- 692 -- The input must be exactly as long as 'decrypt_header' reported. 693 -- Returns the message and the next t'Receiver'. Fails with 694 -- 'InvalidLength' on a length mismatch, and with 'InvalidMAC' if 695 -- authentication fails. Any error means the connection must be 696 -- terminated. 697 -- 698 -- Continuing the module-level example: 699 -- 700 -- >>> let (hdr, rest) = BS.splitAt 18 ct 701 -- >>> let Right (n, p) = decrypt_header (handshake_receiver r_res) hdr 702 -- >>> fmap fst (decrypt_body p (BS.take n rest)) 703 -- Right "hello" 704 decrypt_body 705 :: Pending -- ^ state from 'decrypt_header' 706 -> BS.ByteString -- ^ the rest of the frame 707 -> Either Error (BS.ByteString, Receiver) 708 decrypt_body (Pending body c1) c = do 709 require (BS.length c == body) InvalidLength 710 (m, c2) <- note InvalidMAC (open c1 c) 711 pure (m, Receiver c2) 712 713 -- utilities ------------------------------------------------------------------ 714 715 -- lowercase hex encoding 716 hex :: BS.ByteString -> String 717 hex = BS.foldr (\w acc -> nibble (unsafeShiftR w 4) : nibble (w .&. 15) : acc) 718 [] 719 where 720 nibble :: Word8 -> Char 721 nibble n 722 | n < 10 = toEnum (fi n + 0x30) 723 | otherwise = toEnum (fi n + 0x57) 724 725 note :: e -> Maybe a -> Either e a 726 note e = maybe (Left e) Right 727 {-# INLINE note #-} 728 729 require :: Bool -> e -> Either e () 730 require cond e = unless cond (Left e) 731 {-# INLINE require #-} 732 733 fi :: (Integral a, Num b) => a -> b 734 fi = fromIntegral 735 {-# INLINE fi #-}