cryptocipher 0.4.0 → 0.5.0
raw patch · 15 files changed
+15/−1086 lines, 15 filesdep −crypto-pubkey-typesdep −taggedPVP ok
version bump matches the API change (PVP)
Dependencies removed: crypto-pubkey-types, tagged
API changes (from Hackage documentation)
- Crypto.Cipher.DH: data PrivateNumber :: *
- Crypto.Cipher.DH: data PublicNumber :: *
- Crypto.Cipher.DH: data SharedKey :: *
- Crypto.Cipher.DH: generateParams :: CryptoRandomGen g => g -> Int -> Integer -> Either GenError (Params, g)
- Crypto.Cipher.DH: generatePrivate :: CryptoRandomGen g => g -> Int -> Either GenError (PrivateNumber, g)
- Crypto.Cipher.DH: generatePublic :: Params -> PrivateNumber -> PublicNumber
- Crypto.Cipher.DH: getShared :: Params -> PrivateNumber -> PublicNumber -> SharedKey
- Crypto.Cipher.DH: type Params = (Integer, Integer)
- Crypto.Cipher.DSA: InvalidSignature :: Error
- Crypto.Cipher.DSA: PrivateKey :: Params -> Integer -> PrivateKey
- Crypto.Cipher.DSA: PublicKey :: Params -> Integer -> PublicKey
- Crypto.Cipher.DSA: RandomGenFailure :: GenError -> Error
- Crypto.Cipher.DSA: data Error
- Crypto.Cipher.DSA: data PrivateKey :: *
- Crypto.Cipher.DSA: data PublicKey :: *
- Crypto.Cipher.DSA: instance Eq Error
- Crypto.Cipher.DSA: instance Show Error
- Crypto.Cipher.DSA: private_params :: PrivateKey -> Params
- Crypto.Cipher.DSA: private_x :: PrivateKey -> Integer
- Crypto.Cipher.DSA: public_params :: PublicKey -> Params
- Crypto.Cipher.DSA: public_y :: PublicKey -> Integer
- Crypto.Cipher.DSA: sign :: CryptoRandomGen g => g -> (ByteString -> ByteString) -> PrivateKey -> ByteString -> Either GenError (Signature, g)
- Crypto.Cipher.DSA: type Params = (Integer, Integer, Integer)
- Crypto.Cipher.DSA: type Signature = (Integer, Integer)
- Crypto.Cipher.DSA: verify :: Signature -> (ByteString -> ByteString) -> PublicKey -> ByteString -> Either Error Bool
- Crypto.Cipher.RSA: KeyInternalError :: Error
- Crypto.Cipher.RSA: MessageNotRecognized :: Error
- Crypto.Cipher.RSA: MessageSizeIncorrect :: Error
- Crypto.Cipher.RSA: MessageTooLong :: Error
- Crypto.Cipher.RSA: PrivateKey :: PublicKey -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> PrivateKey
- Crypto.Cipher.RSA: PublicKey :: Int -> Integer -> Integer -> PublicKey
- Crypto.Cipher.RSA: RandomGenFailure :: GenError -> Error
- Crypto.Cipher.RSA: SignatureTooLong :: Error
- Crypto.Cipher.RSA: data Error
- Crypto.Cipher.RSA: data PrivateKey :: *
- Crypto.Cipher.RSA: data PublicKey :: *
- Crypto.Cipher.RSA: decrypt :: PrivateKey -> ByteString -> Either Error ByteString
- Crypto.Cipher.RSA: encrypt :: CryptoRandomGen g => g -> PublicKey -> ByteString -> Either Error (ByteString, g)
- Crypto.Cipher.RSA: generate :: CryptoRandomGen g => g -> Int -> Integer -> Either Error ((PublicKey, PrivateKey), g)
- Crypto.Cipher.RSA: instance Eq Error
- Crypto.Cipher.RSA: instance Show Error
- Crypto.Cipher.RSA: private_d :: PrivateKey -> Integer
- Crypto.Cipher.RSA: private_dP :: PrivateKey -> Integer
- Crypto.Cipher.RSA: private_dQ :: PrivateKey -> Integer
- Crypto.Cipher.RSA: private_p :: PrivateKey -> Integer
- Crypto.Cipher.RSA: private_pub :: PrivateKey -> PublicKey
- Crypto.Cipher.RSA: private_q :: PrivateKey -> Integer
- Crypto.Cipher.RSA: private_qinv :: PrivateKey -> Integer
- Crypto.Cipher.RSA: public_e :: PublicKey -> Integer
- Crypto.Cipher.RSA: public_n :: PublicKey -> Integer
- Crypto.Cipher.RSA: public_size :: PublicKey -> Int
- Crypto.Cipher.RSA: sign :: HashF -> HashASN1 -> PrivateKey -> ByteString -> Either Error ByteString
- Crypto.Cipher.RSA: type HashASN1 = ByteString
- Crypto.Cipher.RSA: type HashF = ByteString -> ByteString
- Crypto.Cipher.RSA: verify :: HashF -> HashASN1 -> PublicKey -> ByteString -> ByteString -> Either Error Bool
Files
- Crypto/Cipher/AES.hs +7/−0
- Crypto/Cipher/DH.hs +0/−46
- Crypto/Cipher/DSA.hs +0/−67
- Crypto/Cipher/ElGamal.hs +0/−73
- Crypto/Cipher/RC4.hs +6/−0
- Crypto/Cipher/RSA.hs +0/−180
- Number/Basic.hs +0/−88
- Number/Generate.hs +0/−38
- Number/ModArithmetic.hs +0/−45
- Number/Polynomial.hs +0/−133
- Number/Prime.hs +0/−180
- Number/Serialize.hs +0/−26
- Tests/KAT.hs +1/−1
- Tests/tests.hs +0/−196
- cryptocipher.cabal +1/−13
Crypto/Cipher/AES.hs view
@@ -5,6 +5,13 @@ -- Maintainer : Vincent Hanquez <vincent@snarc.org> -- Stability : experimental -- Portability : Good+--+-- This module just re-export Crypto.Cipher.AES from the+-- cipher-aes module.+--+-- Documentation can be found at+-- <http://hackage.haskell.org/package/cipher-aes>+-- module Crypto.Cipher.AES ( module Crypto.Cipher.AES
− Crypto/Cipher/DH.hs
@@ -1,46 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}---- |--- Module : Crypto.Cipher.DH--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good----module Crypto.Cipher.DH {-# DEPRECATED "Use crypto-pubkey Crypto.PubKey.DH" #-}- ( Params- , PublicNumber- , PrivateNumber- , SharedKey- , generateParams- , generatePrivate- , generatePublic- , getShared- ) where--import Number.ModArithmetic (exponantiation)-import Number.Prime (generateSafePrime)-import Number.Generate (generateOfSize)-import Crypto.Types.PubKey.DH-import Crypto.Random-import Control.Arrow (first)---- | generate params from a specific generator (2 or 5 are common values)--- we generate a safe prime (a prime number of the form 2p+1 where p is also prime)-generateParams :: CryptoRandomGen g => g -> Int -> Integer -> Either GenError (Params, g)-generateParams rng bits generator =- either Left (Right . first (\p -> (p, generator))) $ generateSafePrime rng bits---- | generate a private number with no specific property--- this number is usually called X in DH text.-generatePrivate :: CryptoRandomGen g => g -> Int -> Either GenError (PrivateNumber, g)-generatePrivate rng bits = either Left (Right . first PrivateNumber) $ generateOfSize rng bits---- | generate a public number that is for the other party benefits.--- this number is usually called Y in DH text.-generatePublic :: Params -> PrivateNumber -> PublicNumber-generatePublic (p,g) (PrivateNumber x) = PublicNumber $ exponantiation g x p---- | generate a shared key using our private number and the other party public number-getShared :: Params -> PrivateNumber -> PublicNumber -> SharedKey-getShared (p,_) (PrivateNumber x) (PublicNumber y) = SharedKey $ exponantiation y x p
− Crypto/Cipher/DSA.hs
@@ -1,67 +0,0 @@--- |--- Module : Crypto.Cipher.DSA--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good-----module Crypto.Cipher.DSA {-# DEPRECATED "Use crypto-pubkey Crypto.PubKey.DSA" #-}- ( Error(..)- , Params- , Signature- , PublicKey(..)- , PrivateKey(..)- , sign- , verify- ) where--import Crypto.Random-import Data.Maybe-import Data.ByteString (ByteString)-import Number.ModArithmetic (exponantiation, inverse)-import Number.Serialize-import Number.Generate-import Crypto.Types.PubKey.DSA--data Error = - InvalidSignature -- ^ signature is not valid r or s is not between the bound 0..q- | RandomGenFailure GenError -- ^ the random generator returns an error. give the opportunity to reseed for example.- deriving (Show,Eq)--{-| sign message using the private key. -}-sign :: CryptoRandomGen g => g -> (ByteString -> ByteString) -> PrivateKey -> ByteString -> Either GenError (Signature, g)-sign rng hash pk m =- -- Recalculate the signature in the unlikely case that r = 0 or s = 0- case generateMax rng q of- Left err -> Left err- Right (k, rng') ->- let kinv = fromJust $ inverse k q in- let r = expmod g k p `mod` q in- let s = (kinv * (hm + x * r)) `mod` q in- if r == 0 || s == 0- then sign rng' hash pk m- else Right ((r, s), rng')- where- (p,g,q) = private_params pk- x = private_x pk- hm = os2ip $ hash m--{- | verify a bytestring using the public key. -}-verify :: Signature -> (ByteString -> ByteString) -> PublicKey -> ByteString -> Either Error Bool-verify (r,s) hash pk m- -- Reject the signature if either 0 < r <q or 0 < s < q is not satisfied.- | r <= 0 || r >= q || s <= 0 || s >= q = Left InvalidSignature- | otherwise = Right $ v == r- where- (p,g,q) = public_params pk- y = public_y pk- hm = os2ip $ hash m-- w = fromJust $ inverse s q- u1 = (hm*w) `mod` q- u2 = (r*w) `mod` q- v = ((expmod g u1 p) * (expmod y u2 p)) `mod` p `mod` q--expmod :: Integer -> Integer -> Integer -> Integer-expmod = exponantiation
− Crypto/Cipher/ElGamal.hs
@@ -1,73 +0,0 @@--- |--- Module : Crypto.Cipher.ElGamal--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good------ This module is a work in progress. do not use:--- it might eat your dog, your data or even both.------ TODO: provide a mapping between integer and ciphertext--- generate numbers correctly----module Crypto.Cipher.ElGamal {-# DEPRECATED "Use crypto-pubkey Crypto.PubKey.ElGamal" #-}- ( Params- , PublicNumber- , PrivateNumber- , SharedKey- , generatePrivate- , generatePublic- , encryptWith- , encrypt- , decrypt-{-- , sign- , verify--}- ) where--import Number.ModArithmetic (exponantiation, inverse)-import Number.Generate (generateOfSize)-import Crypto.Types.PubKey.DH-import Crypto.Random-import Control.Arrow (first)-import Control.Applicative ((<$>))-import Data.Maybe (fromJust)---- | generate a private number with no specific property--- this number is usually called a.--- --- FIXME replace generateOfSize by generateBetween [0, q-1]-generatePrivate :: CryptoRandomGen g => g -> Int -> Either GenError (PrivateNumber, g)-generatePrivate rng bits = either Left (Right . first PrivateNumber) $ generateOfSize rng bits---- | generate a public number that is for the other party benefits.--- this number is usually called h=g^a-generatePublic :: Params -> PrivateNumber -> PublicNumber-generatePublic (p,g) (PrivateNumber a) = PublicNumber $ exponantiation g a p---- | encrypt with a specified ephemeral key--- do not reuse ephemeral key.-encryptWith :: PrivateNumber -> Params -> PublicNumber -> Integer -> (Integer,Integer)-encryptWith (PrivateNumber b) (p,g) (PublicNumber h) m = (c1,c2)- where s = exponantiation h b p- c1 = exponantiation g b p- c2 = (s * m) `mod` p---- | encrypt a message using params and public keys--- will generate b (called the ephemeral key)-encrypt :: CryptoRandomGen g => g -> Params -> PublicNumber -> Integer -> Either GenError ((Integer,Integer), g)-encrypt rng params public m = (\(b,rng') -> (encryptWith b params public m,rng')) <$> generatePrivate rng 1024---- | decrypt message-decrypt :: Params -> PrivateNumber -> (Integer, Integer) -> Integer-decrypt (p,_) (PrivateNumber a) (c1,c2) = (c2 * sm1) `mod` p- where s = exponantiation c1 a p- sm1 = fromJust $ inverse s p -- always inversible in Zp--{--sign = undefined--verify = undefined--}
Crypto/Cipher/RC4.hs view
@@ -5,6 +5,12 @@ -- Stability : experimental -- Portability : Good --+-- This module just re-export Crypto.Cipher.RC4 from the+-- cipher-rc4 module.+--+-- Documentation can be found at+-- <http://hackage.haskell.org/package/cipher-rc4>+-- {-# LANGUAGE PackageImports #-} module Crypto.Cipher.RC4 (module Crypto.Cipher.RC4) where
− Crypto/Cipher/RSA.hs
@@ -1,180 +0,0 @@-{-# LANGUAGE FlexibleInstances, CPP #-}---- |--- Module : Crypto.Cipher.RSA--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good----module Crypto.Cipher.RSA {-# DEPRECATED "Use crypto-pubkey Crypto.PubKey.RSA" #-}- ( Error(..)- , PublicKey(..)- , PrivateKey(..)- , HashF- , HashASN1- , generate- , decrypt- , encrypt- , sign- , verify- ) where--import Control.Arrow (first)-import Crypto.Random-import Crypto.Types.PubKey.RSA-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import Number.ModArithmetic (exponantiation, inverse)-import Number.Prime (generatePrime)-import Number.Serialize-import Data.Maybe (fromJust)--data Error =- MessageSizeIncorrect -- ^ the message to decrypt is not of the correct size (need to be == private_size)- | MessageTooLong -- ^ the message to encrypt is too long (>= private_size - 11)- | MessageNotRecognized -- ^ the message decrypted doesn't have a PKCS15 structure (0 2 .. 0 msg)- | SignatureTooLong -- ^ the signature generated through the hash is too long to process with this key- | RandomGenFailure GenError -- ^ the random generator returns an error. give the opportunity to reseed for example.- | KeyInternalError -- ^ the whole key is probably not valid, since the message is bigger than the key size- deriving (Show,Eq)--type HashF = ByteString -> ByteString-type HashASN1 = ByteString--#if ! (MIN_VERSION_base(4,3,0))-instance Monad (Either Error) where- return = Right- (Left x) >>= _ = Left x- (Right x) >>= f = f x-#endif--padPKCS1 :: CryptoRandomGen g => g -> Int -> ByteString -> Either Error (ByteString, g)-padPKCS1 rng len m = do- (padding, rng') <- getRandomBytes rng (len - B.length m - 3)- return (B.concat [ B.singleton 0, B.singleton 2, padding, B.singleton 0, m ], rng')--unpadPKCS1 :: ByteString -> Either Error ByteString-unpadPKCS1 packed- | signal_error = Left MessageNotRecognized- | otherwise = Right m- where- (zt, ps0m) = B.splitAt 2 packed- (ps, zm) = B.span (/= 0) ps0m- (z, m) = B.splitAt 1 zm- signal_error = (B.unpack zt /= [0, 2]) || (B.unpack z /= [0]) || (B.length ps < 8)--{- dpSlow computes the decrypted message not using any precomputed cache value.- only n and d need to valid. -}-dpSlow :: PrivateKey -> ByteString -> Either Error ByteString-dpSlow pk c = i2ospOf (private_size pk) $ expmod (os2ip c) (private_d pk) (private_n pk)--{- dpFast computes the decrypted message more efficiently if the- precomputed private values are available. mod p and mod q are faster- to compute than mod pq -}-dpFast :: PrivateKey -> ByteString -> Either Error ByteString-dpFast pk c = i2ospOf (private_size pk) (m2 + h * (private_q pk))- where- iC = os2ip c- m1 = expmod iC (private_dP pk) (private_p pk)- m2 = expmod iC (private_dQ pk) (private_q pk)- h = ((private_qinv pk) * (m1 - m2)) `mod` (private_p pk)--{-| decrypt message using the private key. -}-decrypt :: PrivateKey -> ByteString -> Either Error ByteString-decrypt pk c- | B.length c /= (private_size pk) = Left MessageSizeIncorrect- | otherwise = dp pk c >>= unpadPKCS1- where dp = if private_p pk /= 0 && private_q pk /= 0 then dpFast else dpSlow--{- | encrypt a bytestring using the public key and a CryptoRandomGen random generator.- - the message need to be smaller than the key size - 11- -}-encrypt :: CryptoRandomGen g => g -> PublicKey -> ByteString -> Either Error (ByteString, g)-encrypt rng pk m- | B.length m > public_size pk - 11 = Left MessageTooLong- | otherwise = do- (em, rng') <- padPKCS1 rng (public_size pk) m- c <- i2ospOf (public_size pk) $ expmod (os2ip em) (public_e pk) (public_n pk)- return (c, rng')--{-| sign message using private key, a hash and its ASN1 description -}-sign :: HashF -> HashASN1 -> PrivateKey -> ByteString -> Either Error ByteString-sign hash hashdesc pk m = makeSignature hash hashdesc (private_size pk) m >>= d pk- where d = if private_p pk /= 0 && private_q pk /= 0 then dpFast else dpSlow--{-| verify message with the signed message -}-verify :: HashF -> HashASN1 -> PublicKey -> ByteString -> ByteString -> Either Error Bool-verify hash hashdesc pk m sm = do- s <- makeSignature hash hashdesc (public_size pk) m- em <- i2ospOf (public_size pk) $ expmod (os2ip sm) (public_e pk) (public_n pk)- Right (s == em)---- | generate a pair of (private, public) key of size in bytes.-generate :: CryptoRandomGen g => g -> Int -> Integer -> Either Error ((PublicKey, PrivateKey), g)-generate rng size e = do- ((p,q), rng') <- generatePQ rng- let n = p * q- let phi = (p-1)*(q-1)- case inverse e phi of- Nothing -> generate rng' size e- Just d -> do- let pub = PublicKey- { public_size = size- , public_n = n- , public_e = e- }- let priv = PrivateKey- { private_pub = pub- , private_d = d- , private_p = p- , private_q = q- , private_dP = d `mod` (p-1)- , private_dQ = d `mod` (q-1)- , private_qinv = fromJust $ inverse q p -- q and p are coprime, so fromJust is safe.- }- Right ((pub, priv), rng')- where- generatePQ g = do- (p, g') <- genPrime g (8 * (size `div` 2))- (q, g'') <- generateQ p g'- return ((p,q), g'')- generateQ p h = do- (q, h') <- genPrime h (8 * (size - (size `div` 2)))- if p == q then generateQ p h' else return (q, h')- genPrime g sz = either (Left . RandomGenFailure) Right $ generatePrime g sz--{- makeSignature for sign and verify -}-makeSignature :: HashF -> HashASN1 -> Int -> ByteString -> Either Error ByteString-makeSignature hash descr klen m- | klen < siglen+1 = Left SignatureTooLong- | otherwise = Right $ B.concat [B.singleton 0,B.singleton 1,padding,B.singleton 0,signature]- where- signature = descr `B.append` hash m- siglen = B.length signature- padding = B.replicate (klen - siglen - 3) 0xff--{- get random non-null bytes for encryption padding. -}-getRandomBytes :: CryptoRandomGen g => g -> Int -> Either Error (ByteString, g)-getRandomBytes rng n = do- gend <- either (Left . RandomGenFailure) Right $ genBytes n rng- let (bytes, rng') = first (B.pack . filter (/= 0) . B.unpack) gend- let left = (n - B.length bytes)- if left == 0- then return (bytes, rng')- else getRandomBytes rng' left >>= return . first (B.append bytes)--{- convert a positive integer into a bytestring of specific size.- if the number is too big, this will returns an error, otherwise it will pad- the bytestring of 0 -}-i2ospOf :: Int -> Integer -> Either Error ByteString-i2ospOf len m - | lenbytes < len = Right $ B.replicate (len - lenbytes) 0 `B.append` bytes- | lenbytes == len = Right bytes- | otherwise = Left KeyInternalError- where- lenbytes = B.length bytes- bytes = i2osp m--expmod :: Integer -> Integer -> Integer -> Integer-expmod = exponantiation
− Number/Basic.hs
@@ -1,88 +0,0 @@-{-# LANGUAGE BangPatterns #-}--- |--- Module : Number.Basic--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good--module Number.Basic- ( sqrti- , gcde- , gcde_binary- , areEven- ) where--import Data.Bits---- | sqrti returns two integer (l,b) so that l <= sqrt i <= b--- the implementation is quite naive, use an approximation for the first number--- and use a dichotomy algorithm to compute the bound relatively efficiently.-sqrti :: Integer -> (Integer, Integer)-sqrti i- | i < 0 = error "cannot compute negative square root"- | i == 0 = (0,0)- | i == 1 = (1,1)- | i == 2 = (1,2)- | otherwise = loop x0- where- nbdigits = length $ show i- x0n = (if even nbdigits then nbdigits - 2 else nbdigits - 1) `div` 2- x0 = if even nbdigits then 2 * 10 ^ x0n else 6 * 10 ^ x0n- loop x = case compare (sq x) i of- LT -> iterUp x- EQ -> (x, x)- GT -> iterDown x- iterUp lb = if sq ub >= i then iter lb ub else iterUp ub- where ub = lb * 2- iterDown ub = if sq lb >= i then iterDown lb else iter lb ub- where lb = ub `div` 2- iter lb ub- | lb == ub = (lb, ub)- | lb+1 == ub = (lb, ub)- | otherwise =- let d = (ub - lb) `div` 2 in- if sq (lb + d) >= i- then iter lb (ub-d)- else iter (lb+d) ub- sq a = a * a---- | get the extended GCD of two integer using integer divMod-gcde :: Integer -> Integer -> (Integer, Integer, Integer)-gcde a b = if d < 0 then (-x,-y,-d) else (x,y,d) where- (d, x, y) = f (a,1,0) (b,0,1)- f t (0, _, _) = t- f (a', sa, ta) t@(b', sb, tb) =- let (q, r) = a' `divMod` b' in- f t (r, sa - (q * sb), ta - (q * tb))---- | get the extended GCD of two integer using the extended binary algorithm (HAC 14.61)--- get (x,y,d) where d = gcd(a,b) and x,y satisfying ax + by = d-gcde_binary :: Integer -> Integer -> (Integer, Integer, Integer)-gcde_binary a' b'- | b' == 0 = (1,0,a')- | a' >= b' = compute a' b'- | otherwise = (\(x,y,d) -> (y,x,d)) $ compute b' a'- where- getEvenMultiplier !g !x !y- | areEven [x,y] = getEvenMultiplier (g `shiftL` 1) (x `shiftR` 1) (y `shiftR` 1)- | otherwise = (x,y,g)- halfLoop !x !y !u !i !j- | areEven [u,i,j] = halfLoop x y (u `shiftR` 1) (i `shiftR` 1) (j `shiftR` 1)- | even u = halfLoop x y (u `shiftR` 1) ((i + y) `shiftR` 1) ((j - x) `shiftR` 1)- | otherwise = (u, i, j)- compute a b =- let (x,y,g) = getEvenMultiplier 1 a b in- loop g x y x y 1 0 0 1-- loop g _ _ 0 !v _ _ !c !d = (c, d, g * v)- loop g x y !u !v !a !b !c !d =- let (u2,a2,b2) = halfLoop x y u a b in- let (v2,c2,d2) = halfLoop x y v c d in- if u2 >= v2- then loop g x y (u2 - v2) v2 (a2 - c2) (b2 - d2) c2 d2- else loop g x y u2 (v2 - u2) a2 b2 (c2 - a2) (d2 - b2)---- | check if a list of integer are all even-areEven :: [Integer] -> Bool-areEven = and . map even
− Number/Generate.hs
@@ -1,38 +0,0 @@--- |--- Module : Number.Generate--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good--module Number.Generate- ( generateMax- , generateBetween- , generateOfSize- ) where--import Number.Serialize-import Crypto.Random-import qualified Data.ByteString as B-import Data.Bits ((.|.))---- | generate a positive integer between 0 and m.--- using as many bytes as necessary to the same size as m, that are converted to integer.-generateMax :: CryptoRandomGen g => g -> Integer -> Either GenError (Integer, g)-generateMax rng m = case genBytes (lengthBytes m) rng of- Left err -> Left err- Right (bs, rng') -> Right (os2ip bs `mod` m, rng')---- | generate a number between the inclusive bound [low,high].-generateBetween :: CryptoRandomGen g => g -> Integer -> Integer -> Either GenError (Integer, g)-generateBetween rng low high = case generateMax rng (high - low + 1) of- Left err -> Left err- Right (v, rng') -> Right (low + v, rng')---- | generate a positive integer of a specific size in bits.--- the number of bits need to be multiple of 8. It will always returns--- an integer that is close 2^(1+bits/8) by setting the 2 highest bits to 1.-generateOfSize :: CryptoRandomGen g => g -> Int -> Either GenError (Integer, g)-generateOfSize rng bits = case genBytes (bits `div` 8) rng of- Left err -> Left err- Right (bs, rng') -> Right (os2ip $ snd $ B.mapAccumL (\acc w -> (0, w .|. acc)) 0xc0 bs, rng')
− Number/ModArithmetic.hs
@@ -1,45 +0,0 @@-{-# LANGUAGE BangPatterns #-}--- |--- Module : Number.ModArithmetic--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good--module Number.ModArithmetic- ( exponantiation_rtl_binary- , exponantiation- , inverse- ) where--import Number.Basic (gcde_binary)-import Data.Bits---- note on exponantiation: 0^0 is treated as 1 for mimicking the standard library;--- the mathematic debate is still open on whether or not this is true, but pratically--- in computer science it shouldn't be useful for anything anyway.---- | exponantiation_rtl_binary computes modular exponantiation as b^e mod m--- using the right-to-left binary exponentiation algorithm (HAC 14.79)-exponantiation_rtl_binary :: Integer -> Integer -> Integer -> Integer-exponantiation_rtl_binary 0 0 m = 1 `mod` m-exponantiation_rtl_binary b e m = loop e b 1- where- sq x = (x * x) `mod` m- loop !0 _ !a = a `mod` m- loop !i !s !a = loop (i `shiftR` 1) (sq s) (if odd i then a * s else a)---- | exponantiation computes modular exponantiation as b^e mod m--- using repetitive squaring.-exponantiation :: Integer -> Integer -> Integer -> Integer-exponantiation b e m- | e == 0 = 1- | e == 1 = b `mod` m- | even e = let p = (exponantiation b (e `div` 2) m) `mod` m- in (p^(2::Integer)) `mod` m- | otherwise = (b * exponantiation b (e-1) m) `mod` m---- | inverse computes the modular inverse as in g^(-1) mod m-inverse :: Integer -> Integer -> Maybe Integer-inverse g m = if d > 1 then Nothing else Just (x `mod` m)- where (x,_,d) = gcde_binary g m
− Number/Polynomial.hs
@@ -1,133 +0,0 @@-{-# LANGUAGE BangPatterns #-}--- |--- Module : Number.Polynomial--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good--module Number.Polynomial- ( Monomial(..)- -- * polynomial operations- , Polynomial- , toList- , fromList- , addPoly- , subPoly- , mulPoly- , squarePoly- , expPoly- , divPoly- , negPoly- ) where--import Data.List (intercalate, sort)-import Data.Vector ((!), Vector)-import qualified Data.Vector as V-import Control.Arrow (first)--data Monomial = Monomial {-# UNPACK #-} !Int !Integer- deriving (Eq)--data Polynomial = Polynomial (Vector Monomial)- deriving (Eq)--instance Ord Monomial where- compare (Monomial w1 v1) (Monomial w2 v2) =- case compare w1 w2 of- EQ -> compare v1 v2- r -> r--instance Show Monomial where- show (Monomial w v) = show v ++ "x^" ++ show w--instance Show Polynomial where- show (Polynomial p) = intercalate "+" $ map show $ V.toList p--toList :: Polynomial -> [Monomial]-toList (Polynomial p) = V.toList p--fromList :: [Monomial] -> Polynomial-fromList = Polynomial . V.fromList . reverse . sort . filterZero- where- filterZero = filter (\(Monomial _ v) -> v /= 0)--getWeight :: Polynomial -> Int -> Maybe Integer-getWeight (Polynomial p) n = look 0- where- plen = V.length p- look !i- | i >= plen = Nothing- | otherwise =- let (Monomial w v) = p ! i in- case compare w n of- LT -> Nothing- EQ -> Just v- GT -> look (i+1)- --mergePoly :: (Integer -> Integer -> Integer) -> Polynomial -> Polynomial -> Polynomial-mergePoly f (Polynomial p1) (Polynomial p2) = fromList $ loop 0 0- where- l1 = V.length p1- l2 = V.length p2- loop !i1 !i2- | i1 == l1 && i2 == l2 = []- | i1 == l1 = (p2 ! i2) : loop i1 (i2+1)- | i2 == l2 = (p1 ! i1) : loop (i1+1) i2- | otherwise =- let (coef, i1inc, i2inc) = addCoef (p1 ! i1) (p2 ! i2) in- coef : loop (i1+i1inc) (i2+i2inc)- addCoef m1@(Monomial w1 v1) (Monomial w2 v2) =- case compare w1 w2 of- LT -> (Monomial w2 (f 0 v2), 0, 1)- EQ -> (Monomial w1 (f v1 v2), 1, 1)- GT -> (m1, 1, 0)--addPoly :: Polynomial -> Polynomial -> Polynomial-addPoly = mergePoly (+)--subPoly :: Polynomial -> Polynomial -> Polynomial-subPoly = mergePoly (-)--negPoly :: Polynomial -> Polynomial-negPoly (Polynomial p) = Polynomial $ V.map negateMonomial p- where negateMonomial (Monomial w v) = Monomial w (-v)--mulPoly :: Polynomial -> Polynomial -> Polynomial-mulPoly p1@(Polynomial v1) p2@(Polynomial v2) =- fromList $ filter (\(Monomial _ v) -> v /= 0) $ map (\i -> Monomial i (c i)) $ reverse [0..(m+n)]- where- (Monomial m _) = v1 ! 0- (Monomial n _) = v2 ! 0- c r = foldl (\acc i -> (b $ r-i) * (a $ i) + acc) 0 [0..r]- where- a = maybe 0 id . getWeight p1- b = maybe 0 id . getWeight p2--squarePoly :: Polynomial -> Polynomial-squarePoly p = p `mulPoly` p--expPoly :: Polynomial -> Integer -> Polynomial-expPoly p e = loop p e- where- loop t 0 = t- loop t n = loop (squarePoly t) (n-1)--divPoly :: Polynomial -> Polynomial -> (Polynomial, Polynomial)-divPoly p1 p2@(Polynomial pp2) = first fromList $ divLoop p1- where divLoop d1@(Polynomial pp1)- | V.null pp1 = ([], d1)- | otherwise =- let (Monomial w1 v1) = pp1 ! 0 in- let (Monomial w2 v2) = pp2 ! 0 in- let w = w1 - w2 in- let (v,r) = v1 `divMod` v2 in- if w >= 0 && r == 0- then- let mono = (Monomial w v) in- let remain = d1 `subPoly` (p2 `mulPoly` (fromList [mono])) in- let (l, finalRem) = divLoop remain in- (mono : l, finalRem)- else- ([], d1)
− Number/Prime.hs
@@ -1,180 +0,0 @@-{-# LANGUAGE BangPatterns #-}--- |--- Module : Number.Prime--- License : BSD-style--- Maintainer : Vincent Hanquez <vincent@snarc.org>--- Stability : experimental--- Portability : Good--module Number.Prime- ( generatePrime- , generateSafePrime- , isProbablyPrime- , findPrimeFrom- , findPrimeFromWith- , primalityTestNaive- , primalityTestMillerRabin- , primalityTestFermat- , isCoprime- ) where--import Crypto.Random-import Data.Bits-import Number.Generate-import Number.Basic (sqrti, gcde_binary)-import Number.ModArithmetic (exponantiation)---- | returns if the number is probably prime.--- first a list of small primes are implicitely tested for divisibility,--- then a fermat primality test is used with arbitrary numbers and--- then the Miller Rabin algorithm is used with an accuracy of 30 recursions-isProbablyPrime :: CryptoRandomGen g => g -> Integer -> Either GenError (Bool, g)-isProbablyPrime rng !n- | any (\p -> p `divides` n) (filter (< n) smallPrimes) = Right (False, rng)- | primalityTestFermat 50 (n`div`2) n = primalityTestMillerRabin rng 30 n- | otherwise = Right (False, rng)---- | generate a prime number of the required bitsize-generatePrime :: CryptoRandomGen g => g -> Int -> Either GenError (Integer, g)-generatePrime rng bits = case generateOfSize rng bits of- Left err -> Left err- Right (sp, rng') -> findPrimeFrom rng' sp---- | generate a prime number of the form 2p+1 where p is also prime.--- it is also knowed as a Sophie Germaine prime or safe prime.------ The number of safe prime is significantly smaller to the number of prime,--- as such it shouldn't be used if this number is supposed to be kept safe.-generateSafePrime :: CryptoRandomGen g => g -> Int -> Either GenError (Integer, g)-generateSafePrime rng bits = case generateOfSize rng bits of- Left err -> Left err- Right (sp, rng') -> case findPrimeFromWith rng' (\g i -> isProbablyPrime g (2*i+1)) (sp `div` 2) of- Left err -> Left err- Right (p, rng'') -> Right (2*p+1, rng'')---- | find a prime from a starting point where the property hold.-findPrimeFromWith :: CryptoRandomGen g => g -> (g -> Integer -> Either GenError (Bool,g)) -> Integer -> Either GenError (Integer, g)-findPrimeFromWith rng prop !n- | even n = findPrimeFromWith rng prop (n+1)- | otherwise = case isProbablyPrime rng n of- Left err -> Left err- Right (False, rng') -> findPrimeFromWith rng' prop (n+2)- Right (True, rng') ->- case prop rng' n of- Left err -> Left err- Right (False, rng'') -> findPrimeFromWith rng'' prop (n+2)- Right (True, rng'') -> Right (n, rng'')---- | find a prime from a starting point with no specific property.-findPrimeFrom :: CryptoRandomGen g => g -> Integer -> Either GenError (Integer, g)-findPrimeFrom rng n = findPrimeFromWith rng (\g _ -> Right (True, g)) n---- | Miller Rabin algorithm return if the number is probably prime or composite.--- the tries parameter is the number of recursion, that determines the accuracy of the test.-primalityTestMillerRabin :: CryptoRandomGen g => g -> Int -> Integer -> Either GenError (Bool, g)-primalityTestMillerRabin rng tries !n- | n <= 3 = error "Miller-Rabin requires tested value to be > 3"- | even n = Right (False, rng)- | tries <= 0 = error "Miller-Rabin tries need to be > 0"- | otherwise = loop rng (factorise 0 (n-1)) tries where- -- factorise n-1 into the form 2^s*d- factorise :: Integer -> Integer -> (Integer, Integer)- factorise !s !v- | v `testBit` 0 = (s, v)- | otherwise = factorise (s+1) (v `shiftR` 1)- expmod = exponantiation- -- when iteration reach zero, we have a probable prime- loop g _ 0 = Right (True, g)- loop g t@(_,d) k = case generateBetween g 2 (n-2) of- Left err -> Left err- Right (a, g') ->- let x = expmod a d n in- if x == (1 :: Integer) || x == (n-1)- then loop g' t (k-1)- else loop' g' t (k-1) ((x*x) `mod` n) 1- -- loop from 1 to s-1. if we reach the end then it's composite- loop' g t@(s,_) km1 !x2 !r- | r == s = Right (False, g)- | x2 == 1 = Right (False, g)- | x2 /= (n-1) = loop' g t km1 ((x2*x2) `mod` n) (r+1)- | otherwise = loop g t km1---- | Probabilitic Test using Fermat primility test.--- Beware of Carmichael numbers that are Fermat liars, i.e. this test--- is useless for them. always combines with some other test.-primalityTestFermat :: Int -- ^ number of iterations of the algorithm- -> Integer -- ^ starting a- -> Integer -- ^ number to test for primality- -> Bool-primalityTestFermat n a p = and $ map expTest [a..(a+fromIntegral n)]- where !pm1 = p-1- expTest i = exponantiation i pm1 p == 1---- | Test naively is integer is prime.--- while naive, we skip even number and stop iteration at i > sqrt(n)-primalityTestNaive :: Integer -> Bool-primalityTestNaive n- | n <= 1 = False- | n == 2 = True- | even n = False- | otherwise = loop 3 where- ubound = snd $ sqrti n- loop i- | i > ubound = True- | i `divides` n = False- | otherwise = loop (i+2)---- | Test is two integer are coprime to each other-isCoprime :: Integer -> Integer -> Bool-isCoprime m n = case gcde_binary m n of (_,_,d) -> d == 1---- | list of the first primes till 2903..-smallPrimes :: [Integer]-smallPrimes =- [ 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29- , 31 , 37 , 41 , 43 , 47 , 53 , 59 , 61 , 67 , 71- , 73 , 79 , 83 , 89 , 97 , 101 , 103 , 107 , 109 , 113- , 127 , 131 , 137 , 139 , 149 , 151 , 157 , 163 , 167 , 173- , 179 , 181 , 191 , 193 , 197 , 199 , 211 , 223 , 227 , 229- , 233 , 239 , 241 , 251 , 257 , 263 , 269 , 271 , 277 , 281- , 283 , 293 , 307 , 311 , 313 , 317 , 331 , 337 , 347 , 349- , 353 , 359 , 367 , 373 , 379 , 383 , 389 , 397 , 401 , 409- , 419 , 421 , 431 , 433 , 439 , 443 , 449 , 457 , 461 , 463- , 467 , 479 , 487 , 491 , 499 , 503 , 509 , 521 , 523 , 541- , 547 , 557 , 563 , 569 , 571 , 577 , 587 , 593 , 599 , 601- , 607 , 613 , 617 , 619 , 631 , 641 , 643 , 647 , 653 , 659- , 661 , 673 , 677 , 683 , 691 , 701 , 709 , 719 , 727 , 733- , 739 , 743 , 751 , 757 , 761 , 769 , 773 , 787 , 797 , 809- , 811 , 821 , 823 , 827 , 829 , 839 , 853 , 857 , 859 , 863- , 877 , 881 , 883 , 887 , 907 , 911 , 919 , 929 , 937 , 941- , 947 , 953 , 967 , 971 , 977 , 983 , 991 , 997 , 1009 , 1013- , 1019 , 1021 , 1031 , 1033 , 1039 , 1049 , 1051 , 1061 , 1063 , 1069- , 1087 , 1091 , 1093 , 1097 , 1103 , 1109 , 1117 , 1123 , 1129 , 1151- , 1153 , 1163 , 1171 , 1181 , 1187 , 1193 , 1201 , 1213 , 1217 , 1223- , 1229 , 1231 , 1237 , 1249 , 1259 , 1277 , 1279 , 1283 , 1289 , 1291- , 1297 , 1301 , 1303 , 1307 , 1319 , 1321 , 1327 , 1361 , 1367 , 1373- , 1381 , 1399 , 1409 , 1423 , 1427 , 1429 , 1433 , 1439 , 1447 , 1451- , 1453 , 1459 , 1471 , 1481 , 1483 , 1487 , 1489 , 1493 , 1499 , 1511- , 1523 , 1531 , 1543 , 1549 , 1553 , 1559 , 1567 , 1571 , 1579 , 1583- , 1597 , 1601 , 1607 , 1609 , 1613 , 1619 , 1621 , 1627 , 1637 , 1657- , 1663 , 1667 , 1669 , 1693 , 1697 , 1699 , 1709 , 1721 , 1723 , 1733- , 1741 , 1747 , 1753 , 1759 , 1777 , 1783 , 1787 , 1789 , 1801 , 1811- , 1823 , 1831 , 1847 , 1861 , 1867 , 1871 , 1873 , 1877 , 1879 , 1889- , 1901 , 1907 , 1913 , 1931 , 1933 , 1949 , 1951 , 1973 , 1979 , 1987- , 1993 , 1997 , 1999 , 2003 , 2011 , 2017 , 2027 , 2029 , 2039 , 2053- , 2063 , 2069 , 2081 , 2083 , 2087 , 2089 , 2099 , 2111 , 2113 , 2129- , 2131 , 2137 , 2141 , 2143 , 2153 , 2161 , 2179 , 2203 , 2207 , 2213- , 2221 , 2237 , 2239 , 2243 , 2251 , 2267 , 2269 , 2273 , 2281 , 2287- , 2293 , 2297 , 2309 , 2311 , 2333 , 2339 , 2341 , 2347 , 2351 , 2357- , 2371 , 2377 , 2381 , 2383 , 2389 , 2393 , 2399 , 2411 , 2417 , 2423- , 2437 , 2441 , 2447 , 2459 , 2467 , 2473 , 2477 , 2503 , 2521 , 2531- , 2539 , 2543 , 2549 , 2551 , 2557 , 2579 , 2591 , 2593 , 2609 , 2617- , 2621 , 2633 , 2647 , 2657 , 2659 , 2663 , 2671 , 2677 , 2683 , 2687- , 2689 , 2693 , 2699 , 2707 , 2711 , 2713 , 2719 , 2729 , 2731 , 2741- , 2749 , 2753 , 2767 , 2777 , 2789 , 2791 , 2797 , 2801 , 2803 , 2819- , 2833 , 2837 , 2843 , 2851 , 2857 , 2861 , 2879 , 2887 , 2897 , 2903- ]--{-# INLINE divides #-}-divides :: Integer -> Integer -> Bool-divides i n = n `mod` i == 0
− Number/Serialize.hs
@@ -1,26 +0,0 @@-module Number.Serialize- ( i2osp- , os2ip- , lengthBytes- ) where--import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import Data.Bits---- | os2ip converts a byte string into a positive integer-os2ip :: ByteString -> Integer-os2ip = B.foldl' (\a b -> (256 * a) .|. (fromIntegral b)) 0---- | i2osp converts a positive integer into a byte string-i2osp :: Integer -> ByteString-i2osp m = B.reverse $ B.unfoldr divMod256 m- where- divMod256 0 = Nothing- divMod256 n = Just (fromIntegral a,b) where (b,a) = n `divMod` 256---- | returns the number of bytes to store an integer with i2osp-lengthBytes :: Integer -> Int-lengthBytes n- | n < 256 = 1- | otherwise = 1 + lengthBytes (n `div` 256)
Tests/KAT.hs view
@@ -228,7 +228,7 @@ ] vectors =- [ ("RC4", vectors_rc4, encryptStream RC4.initCtx RC4.encrypt)+ [ ("RC4", vectors_rc4, encryptStream RC4.initCtx RC4.combine) -- AES haskell implementation , ("AES 128 Enc", vectors_aes128_enc, encryptBlock aes128InitKey AES.encryptECB) , ("AES 192 Enc", vectors_aes192_enc, encryptBlock aes192InitKey AES.encryptECB)
Tests/tests.hs view
@@ -21,185 +21,13 @@ -- for DSA import qualified Crypto.Hash.SHA1 as SHA1 --- numbers-{--import Number.ModArithmetic-import Number.Basic-import Number.Prime-import Number.Serialize--} -- ciphers/Kexch import AES (aesTests) import qualified Crypto.Cipher.AES as AES-import qualified Crypto.Cipher.RSA as RSA-import qualified Crypto.Cipher.DSA as DSA-import qualified Crypto.Cipher.DH as DH import Crypto.Random import KAT -{--prop_gcde_binary_valid (Positive a, Positive b) =- let (x,y,v) = gcde_binary a b in- let (x',y',v') = gcde a b in- and [v==v', a*x' + b*y' == v', a*x + b*y == v, gcd a b == v]--prop_modexp_rtl_valid (NonNegative a, NonNegative b, Positive m) =- exponantiation_rtl_binary a b m == ((a ^ b) `mod` m)--prop_modinv_valid (Positive a, Positive m)- | m > 1 =- case inverse a m of- Just ainv -> (ainv * a) `mod` m == 1- Nothing -> True- | otherwise = True--prop_sqrti_valid (Positive i) = l*l <= i && i <= u*u where (l, u) = sqrti i--prop_generate_prime_valid i =- -- becuase of the next naive test, we can't generate easily number above 32 bits- -- otherwise it slows down the tests to uselessness. when AKS or ECPP is implemented- -- we can revisit the number here- let p = withAleasInteger rng i (\g -> generatePrime g 32) in- -- FIXME test if p is around 32 bits- primalityTestNaive p--prop_miller_rabin_valid i- | i <= 3 = True- | otherwise =- -- miller rabin only returns with certitude that the integer is composite.- let b = withAleasInteger rng i (\g -> isProbablyPrime g i) in- (b == False && primalityTestNaive i == False) || b == True--withAleasInteger rng i f = case reseed (i2osp (if i < 0 then -i else i)) rng of- Left _ -> error "impossible"- Right rng' -> case f rng' of- Left _ -> error "impossible"- Right v -> fst v--}--newtype RSAMessage = RSAMessage B.ByteString deriving (Show, Eq)--instance Arbitrary RSAMessage where- arbitrary = do- sz <- choose (0, 128 - 11)- ws <- replicateM sz (choose (0,255) :: Gen Int)- return $ RSAMessage $ B.pack $ map fromIntegral ws--{- this is a just test rng. this is absolutely not a serious RNG. DO NOT use elsewhere -}-data Rng = Rng (Int, Int)--getByte :: Rng -> (Word8, Rng)-getByte (Rng (mz, mw)) =- let mz2 = 36969 * (mz `mod` 65536) in- let mw2 = 18070 * (mw `mod` 65536) in- (fromIntegral (mz2 + mw2), Rng (mz2, mw2))--getBytes 0 rng = ([], rng)-getBytes n rng =- let (b, rng') = getByte rng in- let (l, rng'') = getBytes (n-1) rng' in- (b:l, rng'')--instance CryptoRandomGen Rng where- newGen _ = Right (Rng (2,3))- genSeedLength = 0- genBytes len g = Right $ first B.pack $ getBytes len g- reseed bs (Rng (a,b)) = Right $ Rng (fromIntegral a', b) where- a' = ((fromIntegral a) + i * 36969) `mod` 65536- i = B.head bs--rng = Rng (1,2) - {-----------------------------------------------------------------------------------------------}-{- testing RSA -}-{-----------------------------------------------------------------------------------------------}--{--prop_rsa_generate_valid (Positive i, RSAMessage msgz) =- let keysz = 64 in- let (pub,priv) = withAleasInteger rng i (\g -> RSA.generate g keysz 65537) in- let msg = B.take (keysz - 11) msgz in- (RSA.private_p priv * RSA.private_q priv == RSA.private_n priv) &&- ((RSA.private_d priv * RSA.public_e pub) `mod` ((RSA.private_p priv - 1) * (RSA.private_q priv - 1)) == 1) &&- (either Left (RSA.decrypt priv . fst) $ RSA.encrypt rng pub msg) == Right msg--}--prop_rsa_valid fast (RSAMessage msg) =- (either Left (RSA.decrypt pk . fst) $ RSA.encrypt rng rsaPublickey msg) == Right msg- where pk = if fast then rsaPrivatekey else rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 }--prop_rsa_fast_valid = prop_rsa_valid True-prop_rsa_slow_valid = prop_rsa_valid False--prop_rsa_sign_valid fast (RSAMessage msg) = (either Left (\smsg -> verify msg smsg) $ sign msg) == Right True- where- verify = RSA.verify (SHA1.hash) sha1desc rsaPublickey- sign = RSA.sign (SHA1.hash) sha1desc pk- sha1desc = B.pack [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03, 0x02,0x1a,0x05,0x00,0x04,0x14]- pk = if fast then rsaPrivatekey else rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 }--prop_rsa_sign_fast_valid = prop_rsa_sign_valid True-prop_rsa_sign_slow_valid = prop_rsa_sign_valid False--rsaPrivatekey = RSA.PrivateKey- { RSA.private_pub = rsaPublickey- , RSA.private_d = 133764127300370985476360382258931504810339098611363623122953018301285450176037234703101635770582297431466449863745848961134143024057267778947569638425565153896020107107895924597628599677345887446144410702679470631826418774397895304952287674790343620803686034122942606764275835668353720152078674967983573326257- , RSA.private_p = 12909745499610419492560645699977670082358944785082915010582495768046269235061708286800087976003942261296869875915181420265794156699308840835123749375331319- , RSA.private_q = 10860278066550210927914375228722265675263011756304443428318337179619069537063135098400347475029673115805419186390580990519363257108008103841271008948795129- , RSA.private_dP = 5014229697614831746694710412330921341325464081424013940131184365711243776469716106024020620858146547161326009604054855316321928968077674343623831428796843- , RSA.private_dQ = 3095337504083058271243917403868092841421453478127022884745383831699720766632624326762288333095492075165622853999872779070009098364595318242383709601515849- , RSA.private_qinv = 11136639099661288633118187183300604127717437440459572124866697429021958115062007251843236337586667012492941414990095176435990146486852255802952814505784196- }--rsaPublickey = RSA.PublicKey- { RSA.public_size = 128- , RSA.public_n = 140203425894164333410594309212077886844966070748523642084363106504571537866632850620326769291612455847330220940078873180639537021888802572151020701352955762744921926221566899281852945861389488419179600933178716009889963150132778947506523961974222282461654256451508762805133855866018054403911588630700228345151- , RSA.public_e = 65537- }--{-----------------------------------------------------------------------------------------------}-{- testing DSA -}-{-----------------------------------------------------------------------------------------------}---dsaParams = (p,g,q)- where- p = 0x00a8c44d7d0bbce69a39008948604b9c7b11951993a5a1a1fa995968da8bb27ad9101c5184bcde7c14fb79f7562a45791c3d80396cefb328e3e291932a17e22edd- g = 0x0bf9fe6c75d2367b88912b2252d20fdcad06b3f3a234b92863a1e30a96a123afd8e8a4b1dd953e6f5583ef8e48fc7f47a6a1c8f24184c76dba577f0fec2fcd1c- q = 0x0096674b70ef58beaaab6743d6af16bb862d18d119--dsaPrivatekey = DSA.PrivateKey- { DSA.private_params = dsaParams- , DSA.private_x = 0x229bac7aa1c7db8121bfc050a3426eceae23fae8- }--dsaPublickey = DSA.PublicKey- { DSA.public_params = dsaParams- , DSA.public_y = 0x4fa505e86e32922f1fa1702a120abdba088bb4be801d4c44f7fc6b9094d85cd52c429cbc2b39514e30909b31e2e2e0752b0fc05c1a7d9c05c3e52e49e6edef4c- }--prop_dsa_valid (RSAMessage msg) =- case DSA.verify signature (SHA1.hash) dsaPublickey msg of- Left err -> False- Right b -> b- where- Right (signature, rng') = DSA.sign rng (SHA1.hash) dsaPrivatekey msg--{-----------------------------------------------------------------------------------------------}-{- testing DH -}-{-----------------------------------------------------------------------------------------------}-instance Arbitrary DH.PrivateNumber where- arbitrary = fromIntegral <$> (suchThat (arbitrary :: Gen Integer) (\x -> x >= 1))--prop_dh_valid (xa, xb) = sa == sb- where- sa = DH.getShared dhparams xa yb- sb = DH.getShared dhparams xb ya- yb = DH.generatePublic dhparams xb- ya = DH.generatePublic dhparams xa- dhparams = (11, 7)--{-----------------------------------------------------------------------------------------------} {- testing AES -} {-----------------------------------------------------------------------------------------------} data AES128Message = AES128Message B.ByteString B.ByteString B.ByteString deriving (Show, Eq)@@ -277,35 +105,11 @@ , testProperty "AES256 (CBC)" prop_aes256_cbc_valid ] -asymEncryptionTests = testGroup "assymmetric cipher encryption"- [ testProperty "RSA (slow)" prop_rsa_slow_valid- , testProperty "RSA (fast)" prop_rsa_fast_valid- ]--asymSignatureTests = testGroup "assymmetric cipher signature"- [ testProperty "RSA (slow)" prop_rsa_sign_slow_valid- , testProperty "RSA (fast)" prop_rsa_sign_fast_valid- , testProperty "DSA" prop_dsa_valid- ]--asymOtherTests = testGroup "assymetric other tests"- [ testProperty "DH valid" prop_dh_valid- ]--arithmeticTests = testGroup "arithmetic"- []--{- run_test "RSA generate" prop_rsa_generate_valid -}- tests :: [Test] tests = [ symCipherExpectedTests , symCipherMarshallTests , testGroup "AES" aesTests- , arithmeticTests- , asymEncryptionTests- , asymSignatureTests- , asymOtherTests ] main = defaultMain tests
cryptocipher.cabal view
@@ -1,5 +1,5 @@ Name: cryptocipher-Version: 0.4.0+Version: 0.5.0 Description: Symmetrical block and stream ciphers. License: BSD3 License-file: LICENSE@@ -28,23 +28,11 @@ , cipher-aes , cipher-rc4 , crypto-api >= 0.5- , crypto-pubkey-types >= 0.2 && < 0.3- , tagged , cereal Exposed-modules: Crypto.Cipher.RC4 Crypto.Cipher.AES Crypto.Cipher.Blowfish Crypto.Cipher.Camellia- Crypto.Cipher.RSA- Crypto.Cipher.DSA- Crypto.Cipher.DH- other-modules: Number.ModArithmetic- Number.Serialize- Number.Generate- Number.Basic- Number.Polynomial- Number.Prime- Crypto.Cipher.ElGamal ghc-options: -Wall Test-Suite test-cryptocipher