From 679e83103ef3e2e1be9d425e6db334abb99d3443 Mon Sep 17 00:00:00 2001 From: Stephen Diehl Date: Fri, 10 Mar 2017 11:06:08 +0000 Subject: [PATCH] stub out cryptography section --- resources/page.latex | 2 +- src/32-cryptography/AES.hs | 46 +++++++++++++++++++++ src/32-cryptography/ChaCha.hs | 1 + src/32-cryptography/Curve25519.hs | 68 +++++++++++++++++++++++++++++++ src/32-cryptography/DH.hs | 30 ++++++++++++++ src/32-cryptography/ECDH.hs | 1 + src/32-cryptography/ECDSA.hs | 1 + src/32-cryptography/Ed25519.hs | 1 + src/32-cryptography/HMAC.hs | 1 - src/32-cryptography/Poly1305.hs | 1 + 10 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 src/32-cryptography/AES.hs create mode 100644 src/32-cryptography/ChaCha.hs create mode 100644 src/32-cryptography/Curve25519.hs create mode 100644 src/32-cryptography/DH.hs create mode 100644 src/32-cryptography/ECDH.hs create mode 100644 src/32-cryptography/ECDSA.hs create mode 100644 src/32-cryptography/Ed25519.hs create mode 100644 src/32-cryptography/Poly1305.hs diff --git a/resources/page.latex b/resources/page.latex index 9d8f636..58a40ad 100644 --- a/resources/page.latex +++ b/resources/page.latex @@ -1,5 +1,5 @@ \documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$babel-lang$,$endif$$if(papersize)$$papersize$paper,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$} -\usepackage[top=1cm, bottom=1.25cm, left=1cm, right=1cm]{geometry} +\usepackage[top=1cm, bottom=1.5cm, left=1.5cm, right=1.5cm]{geometry} $if(fontfamily)$ \usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$} $else$ diff --git a/src/32-cryptography/AES.hs b/src/32-cryptography/AES.hs new file mode 100644 index 0000000..b8b31c4 --- /dev/null +++ b/src/32-cryptography/AES.hs @@ -0,0 +1,46 @@ +{-# LANGUAGE OverloadedStrings #-} + +import Data.ByteString (ByteString) +import Crypto.Cipher.AES (AES256) +import Crypto.Cipher.Types (BlockCipher(..),Cipher(..),nullIV) +import Crypto.Error (CryptoFailable(..)) + +-- https://github.com/Risto-Stevcev/haskell-crypto-simple/blob/master/src/Crypto/Simple/CBC.hs + +newtype Key a = Key ByteString + deriving (Show,Eq) + +secretKey :: ByteString +secretKey = "012-456-89A-CDE-012-456-89A-CDE-" + +encrypt :: ByteString -> ByteString -> ByteString +encrypt secret = ctrCombine ctx nullIV + where + ctx :: AES256 + ctx = cipherInitNoErr (cipherMakeKey (undefined :: AES256) secret) + + cipherInitNoErr :: BlockCipher c => Key c -> c + cipherInitNoErr (Key k) = case cipherInit k of + CryptoPassed a -> a + CryptoFailed e -> error (show e) + + cipherMakeKey :: Cipher cipher => cipher -> ByteString -> Key cipher + cipherMakeKey = const Key + + +decrypt :: ByteString -> ByteString -> ByteString +decrypt = encrypt + +foo :: ByteString +foo = encrypt secretKey "foo" + +bar :: ByteString +bar = decrypt secretKey foo + +main :: IO () +main = do + let msg = "The quick brown fox jumped over the lazy dog" + let res = encrypt secretKey msg + let dec = decrypt secretKey res + print res + print dec diff --git a/src/32-cryptography/ChaCha.hs b/src/32-cryptography/ChaCha.hs new file mode 100644 index 0000000..c773d27 --- /dev/null +++ b/src/32-cryptography/ChaCha.hs @@ -0,0 +1 @@ +module ChaCha where diff --git a/src/32-cryptography/Curve25519.hs b/src/32-cryptography/Curve25519.hs new file mode 100644 index 0000000..4ab6bc9 --- /dev/null +++ b/src/32-cryptography/Curve25519.hs @@ -0,0 +1,68 @@ +{-# LANGUAGE OverloadedStrings #-} + +import Data.Word +import Data.ByteString as S +import Data.ByteArray as B +import Data.Serialize + +import Crypto.Error +import Crypto.Random +import Crypto.Random.Entropy (getEntropy) + +import Crypto.PubKey.DH +import qualified Crypto.PubKey.Curve25519 as Curve25519 + +-- https://github.com/haskell-crypto/cryptonite/tree/3c087f0f4462df606524083699119445bb81dfa6/tests +-- https://github.com/centromere/cacophony/blob/80adb3c69dd850794b038a95364693d9503a24ce/src/Crypto/Noise/DH/Curve25519.hs +-- https://github.com/glguy/ssh-hans/blob/f49ef74a8a37ddff1f4748f46be949704d41557c/src/Network/SSH/Keys.hs + +alicePrivate = throwCryptoError $ Curve25519.secretKey ("\x77\x07\x6d\x0a\x73\x18\xa5\x7d\x3c\x16\xc1\x72\x51\xb2\x66\x45\xdf\x4c\x2f\x87\xeb\xc0\x99\x2a\xb1\x77\xfb\xa5\x1d\xb9\x2c\x2a" :: ByteString) +alicePublic = throwCryptoError $ Curve25519.publicKey ("\x85\x20\xf0\x09\x89\x30\xa7\x54\x74\x8b\x7d\xdc\xb4\x3e\xf7\x5a\x0d\xbf\x3a\x0d\x26\x38\x1a\xf4\xeb\xa4\xa9\x8e\xaa\x9b\x4e\x6a" :: ByteString) +bobPrivate = throwCryptoError $ Curve25519.secretKey ("\x5d\xab\x08\x7e\x62\x4a\x8a\x4b\x79\xe1\x7f\x8b\x83\x80\x0e\xe6\x6f\x3b\xb1\x29\x26\x18\xb6\xfd\x1c\x2f\x8b\x27\xff\x88\xe0\xeb" :: ByteString) +bobPublic = throwCryptoError $ Curve25519.publicKey ("\xde\x9e\xdb\x7d\x7b\x7d\xc1\xb4\xd3\x5b\x61\xc2\xec\xe4\x35\x37\x3f\x83\x43\xc8\x5b\x78\x67\x4d\xad\xfc\x7e\x14\x6f\x88\x2b\x4f" :: ByteString) + +genKey :: IO (Curve25519.SecretKey, Curve25519.PublicKey) +genKey = do + r <- getEntropy 32 :: IO ScrubbedBytes + let sk = throwCryptoError . Curve25519.secretKey $ r + pk = Curve25519.toPublic sk + return (sk, pk) + +dh :: Curve25519.SecretKey -> Curve25519.PublicKey -> ScrubbedBytes +dh sk pk = convert $ Curve25519.dh pk sk + +main :: IO () +main = do + (sk, pk) <- genKey + let res = B.convert (dh sk pk) :: ByteString + print res + + (a, fn) <- runCurve25519dh + print a + let sharedKey = fn (B.convert pk) + print sharedKey + +-- | Implements key exchange as defined by +-- curve25519-sha256@libssh.org.txt +runCurve25519dh :: + IO (S.ByteString, S.ByteString -> Maybe S.ByteString) + {- ^ local public, remote public -> shared key -} +runCurve25519dh = + + -- fails if key isn't 32 bytes long + do CryptoPassed priv <- + fmap Curve25519.secretKey (getRandomBytes 32 :: IO S.ByteString) + + -- Section 2: Transmit public key as "string" + let raw_pub_s = convert $ Curve25519.toPublic priv + + computeSecret raw_pub_c + -- fails if key isn't 32 bytes long + | CryptoPassed pub_c <- Curve25519.publicKey raw_pub_c + + -- Section 4.3: Treat shared key bytes as "integer" + = Just $ B.convert $ Curve25519.dh pub_c priv + + | otherwise = Nothing + + return (raw_pub_s, computeSecret) diff --git a/src/32-cryptography/DH.hs b/src/32-cryptography/DH.hs new file mode 100644 index 0000000..ed11f24 --- /dev/null +++ b/src/32-cryptography/DH.hs @@ -0,0 +1,30 @@ +{-# LANGUAGE BinaryLiterals #-} +{-# LANGUAGE OverloadedStrings #-} + +import Crypto.Random +import Crypto.PubKey.DH as DH + +-- https://github.com/vincenthz/hs-tls/blob/1415d7330d90049fc5f813afb7fcc116a31b6f7d/core/Network/TLS/Crypto/DH.hs + +type DHPublic = DH.PublicNumber +type DHPrivate = DH.PrivateNumber +type DHParams = DH.Params +type DHKey = DH.SharedKey + +-- | The second Oakley group from RFC 2409, which provides ~1024 bits of +-- security. +oakley2 :: DH.Params +oakley2 = Params { + params_p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF + , params_g = 2 + , params_bits = 1024 + } + +dhGenerateKeyPair :: MonadRandom r => DHParams -> r (DHPrivate, DHPublic) +dhGenerateKeyPair params = do + priv <- DH.generatePrivate params + let pub = DH.generatePublic params priv + return (priv, pub) + +test :: IO (DHPrivate, DHPublic) +test = dhGenerateKeyPair oakley2 diff --git a/src/32-cryptography/ECDH.hs b/src/32-cryptography/ECDH.hs new file mode 100644 index 0000000..a011054 --- /dev/null +++ b/src/32-cryptography/ECDH.hs @@ -0,0 +1 @@ +module ECDH where diff --git a/src/32-cryptography/ECDSA.hs b/src/32-cryptography/ECDSA.hs new file mode 100644 index 0000000..b81aa04 --- /dev/null +++ b/src/32-cryptography/ECDSA.hs @@ -0,0 +1 @@ +module ECDSA where diff --git a/src/32-cryptography/Ed25519.hs b/src/32-cryptography/Ed25519.hs new file mode 100644 index 0000000..8a4fe04 --- /dev/null +++ b/src/32-cryptography/Ed25519.hs @@ -0,0 +1 @@ +module Ed25519 where diff --git a/src/32-cryptography/HMAC.hs b/src/32-cryptography/HMAC.hs index 5800518..2c720d7 100644 --- a/src/32-cryptography/HMAC.hs +++ b/src/32-cryptography/HMAC.hs @@ -1,6 +1,5 @@ {-# LANGUAGE OverloadedStrings #-} - import Crypto.Hash (SHA256, Digest, hash) import Crypto.MAC.HMAC (HMAC(..), hmac) import Data.ByteArray (convert) diff --git a/src/32-cryptography/Poly1305.hs b/src/32-cryptography/Poly1305.hs new file mode 100644 index 0000000..02257eb --- /dev/null +++ b/src/32-cryptography/Poly1305.hs @@ -0,0 +1 @@ +module Poly1305 where