RSA 2.1.0.3 → 2.4.1
raw patch · 4 files changed
Files
- RSA.cabal +4/−4
- Test.hs +20/−25
- src/Codec/Crypto/RSA/Exceptions.hs +2/−5
- src/Codec/Crypto/RSA/Pure.hs +13/−21
RSA.cabal view
@@ -1,6 +1,6 @@ name: RSA category: Cryptography, Codec-version: 2.1.0.3+version: 2.4.1 license: BSD3 license-file: LICENSE author: Adam Wick <awick@galois.com>@@ -24,8 +24,9 @@ bytestring > 0.8 && < 0.12, crypto-api >= 0.10 && < 0.14, crypto-pubkey-types >= 0.2 && < 0.6,- pureMD5 >= 2.1 && < 2.3, SHA >= 1.6.4.1 && < 2.0+ if impl(ghc < 8.0)+ build-depends: cipher-aes128 < 0.7.0.4 exposed-modules: Codec.Crypto.RSA, Codec.Crypto.RSA.Exceptions, Codec.Crypto.RSA.Pure@@ -36,13 +37,12 @@ type: exitcode-stdio-1.0 Main-Is: Test.hs hs-source-dirs: src,.+ other-modules: Codec.Crypto.RSA.Pure build-depends: base >= 4.6 && < 7.0, binary > 0.7 && < 1.0, bytestring > 0.8 && < 0.12, crypto-api >= 0.10 && < 0.14, crypto-pubkey-types >= 0.4 && < 0.6,- DRBG >= 0.5.2 && < 0.7,- pureMD5 >= 2.1 && < 2.3, QuickCheck >= 2.5 && < 3, tagged >= 0.2 && < 0.9, test-framework >= 0.8.0.3 && < 0.10,
Test.hs view
@@ -1,15 +1,12 @@ import Codec.Crypto.RSA.Pure import Control.Monad import Data.Binary-import qualified Data.ByteString as BSS import Data.ByteString.Lazy(ByteString) import qualified Data.ByteString.Lazy as BS-import qualified Data.Digest.Pure.MD5 as MD5 import Data.Digest.Pure.SHA import System.IO import Test.QuickCheck import Crypto.Random-import Crypto.Random.DRBG import Test.Framework (defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty)@@ -26,7 +23,7 @@ main = do putStr "Generating testing keys ... " hFlush stdout- g :: GenAutoReseed HashDRBG HashDRBG <- newGenIO+ g :: SystemRandom <- newGenIO let (keys, g') = buildRandomKeyPairs g (cycle keySizes) numRandomKeyPairs unless (all ((> 5) . public_n . fst) keys) $ fail "Something odd." putStrLn "done!"@@ -38,7 +35,7 @@ , testGroup "Testing basic helper functions" [ testProperty "ByteString chunking works" prop_chunkifyWorks , testProperty "Modular exponentiation works" prop_modExpWorks- , testProperty "Modular inversion works" prop_modInvWorks+ , testProperty "Modular inversion works" (prop_modInvWorks g') ] , testGroup "Testing RSA core functions" [ testProperty "Can roundtrip from Integer to BS and back" prop_i2o2iIdent@@ -81,7 +78,6 @@ instance Show HashInfo where show (HashInfo ident _)- | ident == algorithmIdent hashMD5 = "<MD5>" | ident == algorithmIdent hashSHA1 = "<SHA1>" | ident == algorithmIdent hashSHA224 = "<SHA224>" | ident == algorithmIdent hashSHA256 = "<SHA256>"@@ -90,19 +86,9 @@ | otherwise = "<unknownHASH>" instance Arbitrary HashInfo where- arbitrary = elements [hashMD5, hashSHA1, hashSHA224,+ arbitrary = elements [hashSHA1, hashSHA224, hashSHA256, hashSHA384, hashSHA512] -newtype LargePrime = LP Integer- deriving (Show)--instance Arbitrary LargePrime where- arbitrary =- do Right (g :: HashDRBG) <- (newGen . BSS.pack) `fmap` replicateM 4096 arbitrary- case largeRandomPrime g 64 of- Left _ -> fail "Large prime generation failure."- Right (i, _) -> return (LP i)- data KeyPairIdx = KPI Int deriving (Show) @@ -115,8 +101,7 @@ show (HF s _) = "<" ++ s ++ ">" instance Arbitrary HashFun where- arbitrary = elements [HF "MD5" (encode . MD5.md5),- HF "SHA1" (bytestringDigest . sha1),+ arbitrary = elements [HF "SHA1" (bytestringDigest . sha1), HF "SHA256" (bytestringDigest . sha256), HF "SHA384" (bytestringDigest . sha384), HF "SHA512" (bytestringDigest . sha512)]@@ -149,12 +134,22 @@ e' = getPositive e m' = getPositive m -prop_modInvWorks :: LargePrime -> LargePrime -> Bool-prop_modInvWorks (LP p) (LP q) = (e * d) `mod` phi == 1- where - e = 65537- phi = (p - 1) * (q - 1)- d = modular_inverse e phi+prop_modInvWorks :: CryptoRandomGen g => g -> Word16 -> Bool+prop_modInvWorks g0 x =+ let (p, g1) = primeGen (x `mod` 512) g0+ (q, _) = primeGen (x `mod` 512) g1+ e = 65537+ phi = (p - 1) * (q - 1)+ d = modular_inverse e phi+ in (e * d) `mod` phi == 1+ where+ primeGen pre g =+ case randomBS g (fromIntegral pre) of+ Left e -> error ("Error prefetching bytestring:" ++ show e)+ Right (_, g') ->+ case largeRandomPrime g' 64 of+ Left _ -> error "Large prime generation failure."+ Right res -> res prop_i2o2iIdent :: Positive Integer -> Bool prop_i2o2iIdent px =
src/Codec/Crypto/RSA/Exceptions.hs view
@@ -27,7 +27,7 @@ , rsassa_pkcs1_v1_5_sign , rsassa_pkcs1_v1_5_verify -- * Hashing algorithm declarations for use in RSA functions- , hashMD5, hashSHA1+ , hashSHA1 , hashSHA224, hashSHA256, hashSHA384, hashSHA512 -- * Other mathematical functions that are handy for implementing -- other RSA primitives.@@ -259,7 +259,7 @@ -- or 35. -- -- Thus,--- * for MD5, SHA1, and SHA256, use 512+ bit keys+-- * for SHA1 and SHA256, use 512+ bit keys -- * for SHA384 and SHA512, use 1024+ bit keys -- rsassa_pkcs1_v1_5_sign :: HashInfo {- ^The hash function to use -} ->@@ -358,9 +358,6 @@ modular_inverse = Pure.modular_inverse -- ------------------------------------------------------------------------------hashMD5 :: HashInfo-hashMD5 = Pure.hashMD5 hashSHA1 :: HashInfo hashSHA1 = Pure.hashSHA1
src/Codec/Crypto/RSA/Pure.hs view
@@ -29,7 +29,7 @@ , rsassa_pkcs1_v1_5_sign , rsassa_pkcs1_v1_5_verify -- * Hashing algorithm declarations for use in RSA functions- , hashMD5, hashSHA1+ , hashSHA1 , hashSHA224, hashSHA256, hashSHA384, hashSHA512 -- * Other mathematical functions that are handy for implementing -- other RSA primitives.@@ -56,7 +56,6 @@ import Data.Bits import Data.ByteString.Lazy(ByteString) import qualified Data.ByteString.Lazy as BS-import qualified Data.Digest.Pure.MD5 as MD5 import Data.Digest.Pure.SHA import Data.Int import Data.Typeable@@ -73,7 +72,7 @@ | RSAIncorrectMsgSize | RSADecryptionError | RSAGenError GenError- deriving (Show, Typeable)+ deriving (Eq, Show, Typeable) instance Exception RSAError @@ -113,7 +112,7 @@ return (PrivateKey pub d 0 0 0 0 0) failOnError :: (Monad m, Show a) => Either a b -> m b-failOnError (Left e) = fail (show e)+failOnError (Left e) = error (show e) failOnError (Right b) = return b -- ----------------------------------------------------------------------------@@ -325,7 +324,7 @@ -- generate an error, represented by the Left constructor. -- -- Futher, k (the length of the ciphertext in bytes) must be greater than or--- equal to (2 * hLen + 2), where hLen is the length of the output of the +-- equal to (2 * hLen + 2), where hLen is the length of the output of the -- hash function in bytes. If this equation does not hold, a (different) -- error will be generated. --@@ -345,7 +344,7 @@ keySize = private_size k -- WARNING: Step 1a is missing! unless (BS.length c == fromIntegral keySize) $ -- Step 1b- Left RSADecryptionError + Left RSADecryptionError unless (fromIntegral keySize >= ((2 * hashLength) + 2)) $ -- Step 1c Left RSADecryptionError let c_ip = os2ip c -- Step 2a@@ -417,7 +416,7 @@ em <- i2osp m_i (private_size k) -- Step 2c let (zt, ps_z_m) = BS.splitAt 2 em -- Step 3... (ps, z_m) = BS.span (/= 0) ps_z_m- (z, m) = BS.splitAt 1 z_m + (z, m) = BS.splitAt 1 z_m when (BS.unpack zt /= [0,2]) $ Left RSADecryptionError when (BS.unpack z /= [0]) $ Left RSADecryptionError when (BS.length ps < 8 ) $ Left RSADecryptionError@@ -449,7 +448,7 @@ -- or 35. -- -- Thus,--- * for MD5, SHA1, and SHA256, use 512+ bit keys+-- * for SHA1 and SHA256, use 512+ bit keys -- * for SHA384 and SHA512, use 1024+ bit keys -- rsassa_pkcs1_v1_5_sign :: HashInfo {- ^The hash function to use -} ->@@ -483,17 +482,17 @@ -- ---------------------------------------------------------------------------- -- |A 'mask generation function'. The input is a bytestring, and the output--- is a hash of the given length. Unless you know what you're doing, you +-- is a hash of the given length. Unless you know what you're doing, you -- should probably use a MGF1 formulation created with generate_MGF1. type MGF = ByteString -> Int64 -> Either RSAError ByteString --- |Generate a mask generation function for the rsaes_oaep_*. As +-- |Generate a mask generation function for the rsaes_oaep_*. As -- suggested by the name, the generated function is an instance of the MGF1--- function. The arguments are the underlying hash function to use and the +-- function. The arguments are the underlying hash function to use and the -- size of a hash in bytes. -- -- The bytestring passed to the generated function cannot be longer than--- 2^32 * hLen, where hLen is the passed length of the hash. +-- 2^32 * hLen, where hLen is the passed length of the hash. generateMGF1 :: (ByteString -> ByteString) -> MGF generateMGF1 hash mgfSeed maskLen | BS.length mgfSeed > ((2 ^ (32::Integer)) * hLen) = Left RSAMaskTooLong@@ -573,7 +572,7 @@ in if r /= 0 then (q + 1) else q -- Generate p and q. This is not necessarily the best way to do this, but it--- appears to work. +-- appears to work. generatePQ :: CryptoRandomGen g => g -> Int ->@@ -677,7 +676,7 @@ | n == 1 = Right (False, g) | n == 2 = Right (True, g) | n == 3 = Right (True, g)- | otherwise = + | otherwise = -- write (n-1) as 2^s*d with d odd by factoring powers of 2 from n-1 let (s, d) = oddify 0 (n - 1) in checkLoop g s d k@@ -747,13 +746,6 @@ in (g, x - ((b `div` a) * y), y) -- ------------------------------------------------------------------------------hashMD5 :: HashInfo-hashMD5 = HashInfo {- algorithmIdent = BS.pack [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,- 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10]- , hashFunction = encode . MD5.md5- } hashSHA1 :: HashInfo hashSHA1 = HashInfo {