hs-tls/Network/TLS/Crypto.hs
Vincent Hanquez a95dd8f45e Generalize key exchange and use in-house RSA.
Remove need for spoon, since RSA will fails gracefully.
Add support for full private key format for fast decryption.
Generalization of key exchange to add future support for DH, etc.
2010-11-04 19:10:00 +00:00

114 lines
2.6 KiB
Haskell

module Network.TLS.Crypto
( HashType(..)
, HashCtx
-- * incremental interface with algorithm type wrapping for genericity
, initHash
, updateHash
, finalizeHash
-- * single pass lazy bytestring interface for each algorithm
, hashMD5
, hashSHA1
-- * incremental interface for each algorithm
, initMD5
, updateMD5
, finalizeMD5
, initSHA1
, updateSHA1
, finalizeSHA1
-- * key exchange generic interface
, PublicKey(..)
, PrivateKey(..)
, kxEncrypt
, kxDecrypt
, KxError(..)
) where
import qualified Crypto.Hash.SHA1 as SHA1
import qualified Crypto.Hash.MD5 as MD5
import qualified Data.ByteString as B
import Data.ByteString (ByteString)
import qualified Crypto.Cipher.RSA as RSA
import Crypto.Random (CryptoRandomGen)
data PublicKey = PubRSA RSA.PublicKey
data PrivateKey = PrivRSA RSA.PrivateKey
instance Show PublicKey where
show (_) = "PublicKey(..)"
instance Show PrivateKey where
show (_) = "privateKey(..)"
data KxError = RSAError RSA.Error
deriving (Show)
data HashCtx =
SHA1 !SHA1.Ctx
| MD5 !MD5.Ctx
data KeyXchg =
KxRSA RSA.PublicKey RSA.PrivateKey
deriving (Show)
instance Show HashCtx where
show (SHA1 _) = "sha1"
show (MD5 _) = "md5"
data HashType = HashTypeSHA1 | HashTypeMD5
{- MD5 -}
initMD5 :: MD5.Ctx
initMD5 = MD5.init
updateMD5 :: MD5.Ctx -> ByteString -> MD5.Ctx
updateMD5 = MD5.update
finalizeMD5 :: MD5.Ctx -> ByteString
finalizeMD5 = MD5.finalize
hashMD5 :: ByteString -> ByteString
hashMD5 = MD5.hash
{- SHA1 -}
initSHA1 :: SHA1.Ctx
initSHA1 = SHA1.init
updateSHA1 :: SHA1.Ctx -> ByteString -> SHA1.Ctx
updateSHA1 = SHA1.update
finalizeSHA1 :: SHA1.Ctx -> ByteString
finalizeSHA1 = SHA1.finalize
hashSHA1 :: ByteString -> ByteString
hashSHA1 = SHA1.hash
{- generic Hashing -}
initHash :: HashType -> HashCtx
initHash HashTypeSHA1 = SHA1 (initSHA1)
initHash HashTypeMD5 = MD5 (initMD5)
updateHash :: HashCtx -> B.ByteString -> HashCtx
updateHash (SHA1 ctx) = SHA1 . updateSHA1 ctx
updateHash (MD5 ctx) = MD5 . updateMD5 ctx
finalizeHash :: HashCtx -> B.ByteString
finalizeHash (SHA1 ctx) = finalizeSHA1 ctx
finalizeHash (MD5 ctx) = finalizeMD5 ctx
{- key exchange methods encrypt and decrypt for each supported algorithm -}
generalizeRSAError :: Either RSA.Error a -> Either KxError a
generalizeRSAError (Left e) = Left (RSAError e)
generalizeRSAError (Right x) = Right x
kxEncrypt :: CryptoRandomGen g => g -> PublicKey -> ByteString -> Either KxError (ByteString, g)
kxEncrypt g (PubRSA pk) b = generalizeRSAError $ RSA.encrypt g pk b
kxDecrypt :: PrivateKey -> ByteString -> Either KxError ByteString
kxDecrypt (PrivRSA pk) b = generalizeRSAError $ RSA.decrypt pk b