summaryrefslogtreecommitdiffhomepage
path: root/Crypto.hs
blob: 8d4a3506e7a7b2a62be46b45f8643e6a738f4983 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
module Crypto where

import Val
import Hash
import Types

import qualified Crypto.PubKey.Ed25519 as Ed25519
import Crypto.Error
import Crypto.Random.Entropy
import Data.ByteArray (convert)
import Data.ByteString

dummySignature :: Signature
dummySignature = OtherSignature (Val undefined)

-- | Sign any Hashable value.
sign :: Hashable v => MySessionKey -> v -> Signature
sign (MySessionKey sk pk) v = Ed25519Signature $ Val $ convert $
	Ed25519.sign sk pk $ val $ hashValue $ hash v

-- | Verifiy a signature of any Hashable value.
--
-- To avoid overhead of converting the PublicKey to the Ed25519.PublicKey
-- each time, partially evaluate this function.
verify :: Hashable v => PublicKey -> v -> Signature -> Bool
verify (PublicKey (Val pk) _) v (Ed25519Signature (Val s)) = 
	case Ed25519.publicKey pk of
		CryptoPassed pk' -> case Ed25519.signature s of
			CryptoPassed sig -> 
				Ed25519.verify pk' (val $ hashValue $ hash v) sig
			CryptoFailed _ -> False
		CryptoFailed _ -> False
verify _ _ (OtherSignature _) = False

data MySessionKey = MySessionKey Ed25519.SecretKey Ed25519.PublicKey

genMySessionKey :: IO MySessionKey
genMySessionKey = do
	-- Crypto.Random.Entropy may use rdrand, or /dev/random.
	-- Even if you don't trust rdrand to be free of backdoors, 
	-- it seems safe enough to use it for a session key that
	-- is only used for signing, not encryption.
	rand32 <- getEntropy 32 :: IO ByteString
	sk <- throwCryptoErrorIO $ Ed25519.secretKey rand32
	return $ MySessionKey sk (Ed25519.toPublic sk)