crypto-pubkey-0.2.8/0000755000000000000000000000000012456261417012534 5ustar0000000000000000crypto-pubkey-0.2.8/crypto-pubkey.cabal0000644000000000000000000000551412456261417016342 0ustar0000000000000000Name: crypto-pubkey Version: 0.2.8 Description: Public Key cryptography . Supports RSA PKCS15, RSA OAEP, RSA PSS, DSA, ElGamal signature. . Also have primitive support for Diffie Hellman, and ElGamal encryption License: BSD3 License-file: LICENSE Copyright: Vincent Hanquez Author: Vincent Hanquez Maintainer: Vincent Hanquez Synopsis: Public Key cryptography Category: Cryptography Build-Type: Simple Homepage: https://github.com/vincenthz/hs-crypto-pubkey Cabal-Version: >=1.8 Extra-Source-Files: Tests/*.hs Tests/KAT/*.hs Benchs/PregenKeys.hs Library Build-Depends: base >= 4 && < 5 , bytestring , byteable , crypto-random >= 0.0 && < 0.1 , crypto-pubkey-types >= 0.4.1 && < 0.5 , cryptohash >= 0.9.1 , crypto-numbers >= 0.2.2 Exposed-modules: Crypto.PubKey.RSA Crypto.PubKey.RSA.PKCS15 Crypto.PubKey.RSA.OAEP Crypto.PubKey.RSA.PSS Crypto.PubKey.RSA.Prim Crypto.PubKey.DSA Crypto.PubKey.DH Crypto.PubKey.HashDescr Crypto.PubKey.MaskGenFunction Crypto.PubKey.ECC.Generate Crypto.PubKey.ECC.Prim Crypto.PubKey.ECC.DH Crypto.PubKey.ECC.ECDSA other-modules: Crypto.PubKey.ElGamal Crypto.PubKey.RSA.Types Crypto.PubKey.Internal ghc-options: -Wall -O2 Test-Suite test-crypto-pubkey type: exitcode-stdio-1.0 hs-source-dirs: Tests Main-Is: Tests.hs Build-depends: base >= 4 && < 5 , bytestring , byteable , cryptohash , crypto-pubkey , crypto-pubkey-types , crypto-numbers , crypto-random , tasty , tasty-quickcheck , tasty-hunit , tasty-kat Benchmark bench-crypto-pubkey hs-source-dirs: Benchs Main-Is: Bench.hs type: exitcode-stdio-1.0 Build-depends: base >= 4 && < 5 , bytestring , cryptohash , crypto-random , crypto-pubkey , crypto-pubkey-types , criterion , mtl , deepseq source-repository head type: git location: https://github.com/vincenthz/hs-crypto-pubkey crypto-pubkey-0.2.8/LICENSE0000644000000000000000000000243612456261417013546 0ustar0000000000000000Copyright (c) 2010-2012 Vincent Hanquez All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. crypto-pubkey-0.2.8/Setup.hs0000644000000000000000000000005612456261417014171 0ustar0000000000000000import Distribution.Simple main = defaultMain crypto-pubkey-0.2.8/Benchs/0000755000000000000000000000000012456261417013736 5ustar0000000000000000crypto-pubkey-0.2.8/Benchs/Bench.hs0000644000000000000000000001075112456261417015315 0ustar0000000000000000{-# LANGUAGE BangPatterns #-} module Main where import Criterion.Main import PregenKeys import qualified Crypto.Hash.SHA1 as SHA1 import Crypto.PubKey.RSA as RSA import Crypto.PubKey.RSA.PKCS15 as PKCS15 import Crypto.PubKey.RSA.OAEP as OAEP import Crypto.PubKey.RSA.PSS as PSS import Crypto.PubKey.HashDescr import Crypto.PubKey.ECC.ECDSA as ECDSA import Crypto.Random import Control.DeepSeq import qualified Data.ByteString as B right (Right r) = r right (Left _) = error "left received" instance NFData Signature where rnf (Signature r s) = rnf r `seq` rnf s main = do rng <- cprgCreate `fmap` createEntropyPool :: IO SystemRNG let !bs = B.replicate 32 0 !encryptedMsgPKCS = (right . fst . PKCS15.encrypt rng rsaPublickey) bs !encryptedMsgOAEP = (right . fst . OAEP.encrypt rng oaepParams rsaPublickey) bs !signedMsgPKCS = (right . PKCS15.sign Nothing hashDescrSHA1 rsaPrivatekey) bs !signedMsgPSS = (right . fst . PSS.sign rng Nothing pssParams rsaPrivatekey) bs privateKeySlow = rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 } !blinder = fst $ generateBlinder rng (RSA.public_n rsaPublickey) oaepParams = OAEP.defaultOAEPParams SHA1.hash pssParams = PSS.defaultPSSParamsSHA1 ecdsaSignatureP = fst $ ECDSA.sign rng ecdsaPrivatekeyP SHA1.hash bs ecdsaSignatureB = fst $ ECDSA.sign rng ecdsaPrivatekeyB SHA1.hash bs defaultMain [ bgroup "RSA" [ bgroup "PKCS15" [ bench "encryption" $ nf (right . fst . PKCS15.encrypt rng rsaPublickey) bs , bgroup "decryption" [ bench "slow" $ nf (right . PKCS15.decrypt Nothing privateKeySlow) encryptedMsgPKCS , bench "fast" $ nf (right . PKCS15.decrypt Nothing rsaPrivatekey) encryptedMsgPKCS , bench "slow+blinding" $ nf (right . PKCS15.decrypt (Just blinder) privateKeySlow) encryptedMsgPKCS , bench "fast+blinding" $ nf (right . PKCS15.decrypt (Just blinder) rsaPrivatekey) encryptedMsgPKCS ] , bgroup "signing" [ bench "slow" $ nf (right . PKCS15.sign Nothing hashDescrSHA1 privateKeySlow) bs , bench "fast" $ nf (right . PKCS15.sign Nothing hashDescrSHA1 rsaPrivatekey) bs , bench "slow+blinding" $ nf (right . PKCS15.sign (Just blinder) hashDescrSHA1 privateKeySlow) bs , bench "fast+blinding" $ nf (right . PKCS15.sign (Just blinder) hashDescrSHA1 rsaPrivatekey) bs ] , bench "verify" $ nf (PKCS15.verify hashDescrSHA1 rsaPublickey bs) signedMsgPKCS ] , bgroup "OAEP" [ bench "encryption" $ nf (right . fst . OAEP.encrypt rng oaepParams rsaPublickey) bs , bgroup "decryption" [ bench "slow" $ nf (right . OAEP.decrypt Nothing oaepParams privateKeySlow) encryptedMsgOAEP , bench "fast" $ nf (right . OAEP.decrypt Nothing oaepParams rsaPrivatekey) encryptedMsgOAEP , bench "slow+blinding" $ nf (right . OAEP.decrypt (Just blinder) oaepParams privateKeySlow) encryptedMsgOAEP , bench "fast+blinding" $ nf (right . OAEP.decrypt (Just blinder) oaepParams rsaPrivatekey) encryptedMsgOAEP ] ] , bgroup "PSS" [ bgroup "signing" [ bench "slow" $ nf (right . fst . PSS.sign rng Nothing pssParams privateKeySlow) bs , bench "fast" $ nf (right . fst . PSS.sign rng Nothing pssParams rsaPrivatekey) bs , bench "slow+blinding" $ nf (right . fst . PSS.sign rng (Just blinder) pssParams privateKeySlow) bs , bench "fast+blinding" $ nf (right . fst . PSS.sign rng (Just blinder) pssParams rsaPrivatekey) bs ] , bench "verify" $ nf (PSS.verify pssParams rsaPublickey bs) signedMsgPSS ] ] , bgroup "ECDSA" [ bgroup "secp160r1" [ bench "sign" $ nf (fst . ECDSA.sign rng ecdsaPrivatekeyP SHA1.hash) bs , bench "verify" $ nf (ECDSA.verify SHA1.hash ecdsaPublickeyP ecdsaSignatureP) bs ] , bgroup "sect163k1" [ bench "sign" $ nf (fst . ECDSA.sign rng ecdsaPrivatekeyB SHA1.hash) bs , bench "verify" $ nf (ECDSA.verify SHA1.hash ecdsaPublickeyB ecdsaSignatureB) bs ] ] ] crypto-pubkey-0.2.8/Benchs/PregenKeys.hs0000644000000000000000000000656412456261417016361 0ustar0000000000000000module PregenKeys where import qualified Crypto.PubKey.RSA as RSA import qualified Crypto.PubKey.DSA as DSA import qualified Crypto.PubKey.DH as DH import qualified Crypto.PubKey.ECC.ECDSA as ECDSA import qualified Crypto.Types.PubKey.ECC as ECC 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 } dsaParams = DSA.Params { DSA.params_p = p, DSA.params_g = g, DSA.params_q = 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 } ecdsaCurveP = ECC.getCurveByName ECC.SEC_p160r1 ecdsaPrivatekeyP = ECDSA.PrivateKey ecdsaCurveP 971761939728640320549601132085879836204587084162 ecdsaPublickeyP = ECDSA.PublicKey ecdsaCurveP (ECC.Point 466448783855397898016055842232266600516272889280 1110706324081757720403272427311003102474457754220) ecdsaCurveB = ECC.getCurveByName ECC.SEC_t163k1 ecdsaPrivatekeyB = ECDSA.PrivateKey ecdsaCurveB 5321230001203043918714616464614664646674949479949 ecdsaPublickeyB = ECDSA.PublicKey ecdsaCurveB (ECC.Point 0x37d529fa37e42195f10111127ffb2bb38644806bc 0x447026eee8b34157f3eb51be5185d2be0249ed776) crypto-pubkey-0.2.8/Crypto/0000755000000000000000000000000012456261417014014 5ustar0000000000000000crypto-pubkey-0.2.8/Crypto/PubKey/0000755000000000000000000000000012456261417015213 5ustar0000000000000000crypto-pubkey-0.2.8/Crypto/PubKey/DH.hs0000644000000000000000000000376612456261417016056 0ustar0000000000000000{-# LANGUAGE GeneralizedNewtypeDeriving #-} -- | -- Module : Crypto.PubKey.DH -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- module Crypto.PubKey.DH ( Params(..) , PublicNumber , PrivateNumber , SharedKey , generateParams , generatePrivate , calculatePublic , generatePublic , getShared ) where import Crypto.Number.ModArithmetic (expSafe) import Crypto.Number.Prime (generateSafePrime) import Crypto.Number.Generate (generateMax) 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 :: CPRG g => g -> Int -> Integer -> (Params, g) generateParams rng bits generator = first (\p -> Params p generator) $ generateSafePrime rng bits -- | generate a private number with no specific property -- this number is usually called X in DH text. generatePrivate :: CPRG g => g -> Params -> (PrivateNumber, g) generatePrivate rng (Params p _) = first PrivateNumber $ generateMax rng p -- | calculate the public number from the parameters and the private key -- this number is usually called Y in DH text. calculatePublic :: Params -> PrivateNumber -> PublicNumber calculatePublic (Params p g) (PrivateNumber x) = PublicNumber $ expSafe g x p -- | calculate the public number from the parameters and the private key -- this number is usually called Y in DH text. -- -- DEPRECATED use calculatePublic generatePublic :: Params -> PrivateNumber -> PublicNumber generatePublic = calculatePublic -- commented until 0.3 {-# DEPRECATED generatePublic "use calculatePublic" #-} -- | generate a shared key using our private number and the other party public number getShared :: Params -> PrivateNumber -> PublicNumber -> SharedKey getShared (Params p _) (PrivateNumber x) (PublicNumber y) = SharedKey $ expSafe y x p crypto-pubkey-0.2.8/Crypto/PubKey/DSA.hs0000644000000000000000000000545712456261417016171 0ustar0000000000000000-- | -- Module : Crypto.PubKey.DSA -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- -- An implementation of the Digital Signature Algorithm (DSA) module Crypto.PubKey.DSA ( Params(..) , Signature(..) , PublicKey(..) , PrivateKey(..) -- * generation , generatePrivate , calculatePublic -- * signature primitive , sign , signWith -- * verification primitive , verify ) where import Crypto.Random import Data.Maybe import Data.ByteString (ByteString) import Crypto.Number.ModArithmetic (expFast, expSafe, inverse) import Crypto.Number.Serialize import Crypto.Number.Generate import Crypto.Types.PubKey.DSA import Crypto.PubKey.HashDescr -- | generate a private number with no specific property -- this number is usually called X in DSA text. generatePrivate :: CPRG g => g -> Params -> (PrivateNumber, g) generatePrivate rng (Params _ _ q) = generateMax rng q -- | Calculate the public number from the parameters and the private key calculatePublic :: Params -> PrivateNumber -> PublicNumber calculatePublic (Params p g _) x = expSafe g x p -- | sign message using the private key and an explicit k number. signWith :: Integer -- ^ k random number -> PrivateKey -- ^ private key -> HashFunction -- ^ hash function -> ByteString -- ^ message to sign -> Maybe Signature signWith k pk hash msg | r == 0 || s == 0 = Nothing | otherwise = Just $ Signature r s where -- parameters (Params p g q) = private_params pk x = private_x pk -- compute r,s kInv = fromJust $ inverse k q hm = os2ip $ hash msg r = expSafe g k p `mod` q s = (kInv * (hm + x * r)) `mod` q -- | sign message using the private key. sign :: CPRG g => g -> PrivateKey -> HashFunction -> ByteString -> (Signature, g) sign rng pk hash msg = case signWith k pk hash msg of Nothing -> sign rng' pk hash msg Just sig -> (sig, rng') where (Params _ _ q) = private_params pk (k, rng') = generateMax rng q -- | verify a bytestring using the public key. verify :: HashFunction -> PublicKey -> Signature -> ByteString -> Bool verify hash pk (Signature r s) m -- Reject the signature if either 0 < r < q or 0 < s < q is not satisfied. | r <= 0 || r >= q || s <= 0 || s >= q = False | otherwise = v == r where (Params 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 = ((expFast g u1 p) * (expFast y u2 p)) `mod` p `mod` q crypto-pubkey-0.2.8/Crypto/PubKey/ElGamal.hs0000644000000000000000000001221012456261417017045 0ustar0000000000000000-- | -- Module : Crypto.PubKey.ElGamal -- License : BSD-style -- Maintainer : Vincent Hanquez -- 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.PubKey.ElGamal ( Params , PublicNumber , PrivateNumber , EphemeralKey(..) , SharedKey , Signature -- * generation , generatePrivate , generatePublic -- * encryption and decryption with no scheme , encryptWith , encrypt , decrypt -- * signature primitives , signWith , sign -- * verification primitives , verify ) where import Data.ByteString (ByteString) import Crypto.Number.ModArithmetic (expSafe, expFast, inverse) import Crypto.Number.Generate (generateMax) import Crypto.Number.Serialize (os2ip) import Crypto.Number.Basic (gcde_binary) import Crypto.Types.PubKey.DH import Crypto.Random.API import Control.Arrow (first) import Data.Maybe (fromJust) import Crypto.PubKey.HashDescr (HashFunction) -- | ElGamal Signature data Signature = Signature (Integer, Integer) -- | ElGamal Ephemeral key. also called Temporary key. newtype EphemeralKey = EphemeralKey Integer -- | generate a private number with no specific property -- this number is usually called a and need to be between -- 0 and q (order of the group G). -- generatePrivate :: CPRG g => g -> Integer -> (PrivateNumber, g) generatePrivate rng q = first PrivateNumber $ generateMax rng q -- | generate an ephemeral key which is a number with no specific property, -- and need to be between 0 and q (order of the group G). -- generateEphemeral :: CPRG g => g -> Integer -> (EphemeralKey, g) generateEphemeral rng q = first toEphemeral $ generatePrivate rng q where toEphemeral (PrivateNumber n) = EphemeralKey n -- | generate a public number that is for the other party benefits. -- this number is usually called h=g^a generatePublic :: Params -> PrivateNumber -> PublicNumber generatePublic (Params p g) (PrivateNumber a) = PublicNumber $ expSafe g a p -- | encrypt with a specified ephemeral key -- do not reuse ephemeral key. encryptWith :: EphemeralKey -> Params -> PublicNumber -> Integer -> (Integer,Integer) encryptWith (EphemeralKey b) (Params p g) (PublicNumber h) m = (c1,c2) where s = expSafe h b p c1 = expSafe g b p c2 = (s * m) `mod` p -- | encrypt a message using params and public keys -- will generate b (called the ephemeral key) encrypt :: CPRG g => g -> Params -> PublicNumber -> Integer -> ((Integer,Integer), g) encrypt rng params@(Params p _) public m = first (\b -> encryptWith b params public m) $ generateEphemeral rng q where q = p-1 -- p is prime, hence order of the group is p-1 -- | decrypt message decrypt :: Params -> PrivateNumber -> (Integer, Integer) -> Integer decrypt (Params p _) (PrivateNumber a) (c1,c2) = (c2 * sm1) `mod` p where s = expSafe c1 a p sm1 = fromJust $ inverse s p -- always inversible in Zp -- | sign a message with an explicit k number -- -- if k is not appropriate, then no signature is returned. -- -- with some appropriate value of k, the signature generation can fail, -- and no signature is returned. User of this function need to retry -- with a different k value. signWith :: Integer -- ^ random number k, between 0 and p-1 and gcd(k,p-1)=1 -> Params -- ^ DH params (p,g) -> PrivateNumber -- ^ DH private key -> HashFunction -- ^ collision resistant hash function -> ByteString -- ^ message to sign -> Maybe Signature signWith k (Params p g) (PrivateNumber x) hashF msg | k >= p-1 || d > 1 = Nothing -- gcd(k,p-1) is not 1 | s == 0 = Nothing | otherwise = Just $ Signature (r,s) where r = expSafe g k p h = os2ip $ hashF msg s = ((h - x*r) * kInv) `mod` (p-1) (kInv,_,d) = gcde_binary k (p-1) -- | sign message -- -- This function will generate a random number, however -- as the signature might fail, the function will automatically retry -- until a proper signature has been created. -- sign :: CPRG g => g -- ^ random number generator -> Params -- ^ DH params (p,g) -> PrivateNumber -- ^ DH private key -> HashFunction -- ^ collision resistant hash function -> ByteString -- ^ message to sign -> (Signature, g) sign rng params@(Params p _) priv hashF msg = let (k, rng') = generateMax rng (p-1) in case signWith k params priv hashF msg of Nothing -> sign rng' params priv hashF msg Just sig -> (sig, rng') -- | verify a signature verify :: Params -> PublicNumber -> HashFunction -> ByteString -> Signature -> Bool verify (Params p g) (PublicNumber y) hashF msg (Signature (r,s)) | or [r <= 0,r >= p,s <= 0,s >= (p-1)] = False | otherwise = lhs == rhs where h = os2ip $ hashF msg lhs = expFast g h p rhs = (expFast y r p * expFast r s p) `mod` p crypto-pubkey-0.2.8/Crypto/PubKey/HashDescr.hs0000644000000000000000000000750612456261417017423 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} -- | -- Module : Crypto.PubKey.HashDescr -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- -- Standard digests wrapped in ASN1 structure -- module Crypto.PubKey.HashDescr ( -- * Types HashFunction , HashDescr(..) -- * List of known hash description , hashDescrMD2 , hashDescrMD5 , hashDescrSHA1 , hashDescrSHA224 , hashDescrSHA256 , hashDescrSHA384 , hashDescrSHA512 , hashDescrRIPEMD160 ) where import Data.ByteString (ByteString) import Data.Byteable (toBytes) import qualified Data.ByteString as B import Crypto.Hash -- | A standard hash function returning a digest object type HashFunction = ByteString -> ByteString -- | Describe a hash function and a way to wrap the digest into -- an DER encoded ASN1 marshalled structure. data HashDescr = HashDescr { hashFunction :: HashFunction -- ^ hash function , digestToASN1 :: ByteString -> ByteString -- ^ convertion to an ASN1 wrapped digest bytestring } -- | Describe the MD2 hashing algorithm hashDescrMD2 :: HashDescr hashDescrMD2 = HashDescr { hashFunction = toBytes . (hash :: ByteString -> Digest MD2) , digestToASN1 = toHashWithInfo "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x02\x05\x00\x04\x10" } -- | Describe the MD5 hashing algorithm hashDescrMD5 :: HashDescr hashDescrMD5 = HashDescr { hashFunction = toBytes . (hash :: ByteString -> Digest MD5) , digestToASN1 = toHashWithInfo "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10" } -- | Describe the SHA1 hashing algorithm hashDescrSHA1 :: HashDescr hashDescrSHA1 = HashDescr { hashFunction = toBytes . (hash :: ByteString -> Digest SHA1) , digestToASN1 = toHashWithInfo "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14" } -- | Describe the SHA224 hashing algorithm hashDescrSHA224 :: HashDescr hashDescrSHA224 = HashDescr { hashFunction = toBytes . (hash :: ByteString -> Digest SHA224) , digestToASN1 = toHashWithInfo "\x30\x2d\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04\x05\x00\x04\x1c" } -- | Describe the SHA256 hashing algorithm hashDescrSHA256 :: HashDescr hashDescrSHA256 = HashDescr { hashFunction = toBytes . (hash :: ByteString -> Digest SHA256) , digestToASN1 = toHashWithInfo "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20" } -- | Describe the SHA384 hashing algorithm hashDescrSHA384 :: HashDescr hashDescrSHA384 = HashDescr { hashFunction = toBytes . (hash :: ByteString -> Digest SHA384) , digestToASN1 = toHashWithInfo "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30" } -- | Describe the SHA512 hashing algorithm hashDescrSHA512 :: HashDescr hashDescrSHA512 = HashDescr { hashFunction = toBytes . (hash :: ByteString -> Digest SHA512) , digestToASN1 = toHashWithInfo "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40" } -- | Describe the RIPEMD160 hashing algorithm hashDescrRIPEMD160 :: HashDescr hashDescrRIPEMD160 = HashDescr { hashFunction = toBytes . (hash :: ByteString -> Digest RIPEMD160) , digestToASN1 = toHashWithInfo "\x30\x21\x30\x09\x06\x05\x2b\x24\x03\x02\x01\x05\x00\x04\x14" } -- | Generate the marshalled structure with the following ASN1 structure: -- -- Start Sequence -- ,Start Sequence -- ,OID oid -- ,Null -- ,End Sequence -- ,OctetString digest -- ,End Sequence -- toHashWithInfo :: ByteString -> ByteString -> ByteString toHashWithInfo pre digest = pre `B.append` digest crypto-pubkey-0.2.8/Crypto/PubKey/Internal.hs0000644000000000000000000000101512456261417017320 0ustar0000000000000000-- | -- Module : Crypto.PubKey.Internal -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- module Crypto.PubKey.Internal ( and' , (&&!) ) where import Data.List (foldl') -- | This is a strict version of and and' :: [Bool] -> Bool and' l = foldl' (&&!) True l -- | This is a strict version of &&. (&&!) :: Bool -> Bool -> Bool True &&! True = True True &&! False = False False &&! True = False False &&! False = False crypto-pubkey-0.2.8/Crypto/PubKey/MaskGenFunction.hs0000644000000000000000000000204412456261417020602 0ustar0000000000000000-- | -- Module : Crypto.PubKey.MaskGenFunction -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- module Crypto.PubKey.MaskGenFunction ( MaskGenAlgorithm , mgf1 ) where import Data.ByteString (ByteString) import qualified Data.ByteString as B import Crypto.PubKey.HashDescr import Crypto.Number.Serialize (i2ospOf_) -- | Represent a mask generation algorithm type MaskGenAlgorithm = HashFunction -- ^ hash function to use -> ByteString -- ^ seed -> Int -- ^ length to generate -> ByteString -- | Mask generation algorithm MGF1 mgf1 :: MaskGenAlgorithm mgf1 hashF seed len = loop B.empty 0 where loop t counter | B.length t >= len = B.take len t | otherwise = let counterBS = i2ospOf_ 4 counter newT = t `B.append` hashF (seed `B.append` counterBS) in loop newT (counter+1) crypto-pubkey-0.2.8/Crypto/PubKey/RSA.hs0000644000000000000000000000632412456261417016201 0ustar0000000000000000-- | -- Module : Crypto.PubKey.RSA -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- module Crypto.PubKey.RSA ( Error(..) , PublicKey(..) , PrivateKey(..) , Blinder(..) -- * generation function , generateWith , generate , generateBlinder ) where import Crypto.Random import Crypto.Types.PubKey.RSA import Crypto.Number.ModArithmetic (inverse, inverseCoprimes) import Crypto.Number.Generate (generateMax) import Crypto.Number.Prime (generatePrime) import Crypto.PubKey.RSA.Types -- | Generate a key pair given p and q. -- -- p and q need to be distinct prime numbers. -- -- e need to be coprime to phi=(p-1)*(q-1). If that's not the -- case, the function will not return a key pair. -- A small hamming weight results in better performance. -- -- * e=0x10001 is a popular choice -- -- * e=3 is popular as well, but proven to not be as secure for some cases. -- generateWith :: (Integer, Integer) -- ^ chosen distinct primes p and q -> Int -- ^ size in bytes -> Integer -- ^ RSA public exponant 'e' -> Maybe (PublicKey, PrivateKey) generateWith (p,q) size e = case inverse e phi of Nothing -> Nothing Just d -> Just (pub,priv d) where n = p*q phi = (p-1)*(q-1) -- q and p should be *distinct* *prime* numbers, hence always coprime qinv = inverseCoprimes q p pub = PublicKey { public_size = size , public_n = n , public_e = e } priv d = 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 = qinv } -- | generate a pair of (private, public) key of size in bytes. generate :: CPRG g => g -- ^ CPRG -> Int -- ^ size in bytes -> Integer -- ^ RSA public exponant 'e' -> ((PublicKey, PrivateKey), g) generate rng size e = loop rng where loop g = -- loop until we find a valid key pair given e let (pq, g') = generatePQ g in case generateWith pq size e of Nothing -> loop g' Just pp -> (pp, g') generatePQ g = let (p, g') = generatePrime g (8 * (size `div` 2)) (q, g'') = generateQ p g' in ((p,q), g'') generateQ p h = let (q, h') = generatePrime h (8 * (size - (size `div` 2))) in if p == q then generateQ p h' else (q, h') -- | Generate a blinder to use with decryption and signing operation -- -- the unique parameter apart from the random number generator is the -- public key value N. generateBlinder :: CPRG g => g -- ^ CPRG to use. -> Integer -- ^ RSA public N parameter. -> (Blinder, g) generateBlinder rng n = (Blinder r (inverseCoprimes r n), rng') where (r, rng') = generateMax rng n crypto-pubkey-0.2.8/Crypto/PubKey/ECC/0000755000000000000000000000000012456261417015605 5ustar0000000000000000crypto-pubkey-0.2.8/Crypto/PubKey/ECC/DH.hs0000644000000000000000000000205712456261417016440 0ustar0000000000000000module Crypto.PubKey.ECC.DH ( Curve , PublicPoint , PrivateNumber , SharedKey(..) , generatePrivate , calculatePublic , getShared ) where import Crypto.Number.Generate (generateMax) import Crypto.PubKey.ECC.Prim (pointMul) import Crypto.Random (CPRG) import Crypto.Types.PubKey.DH (SharedKey(..)) import Crypto.Types.PubKey.ECC (PublicPoint, PrivateNumber, Curve, Point(..)) import Crypto.Types.PubKey.ECC (ecc_n, ecc_g, common_curve) -- | Generating a private number d. generatePrivate :: CPRG g => g -> Curve -> (PrivateNumber, g) generatePrivate rng curve = generateMax rng n where n = ecc_n $ common_curve curve -- | Generating a public point Q. calculatePublic :: Curve -> PrivateNumber -> PublicPoint calculatePublic curve d = q where g = ecc_g $ common_curve curve q = pointMul curve d g -- | Generating a shared key using our private number and -- the other party public point. getShared :: Curve -> PrivateNumber -> PublicPoint -> SharedKey getShared curve db qa = SharedKey x where Point x _ = pointMul curve db qa crypto-pubkey-0.2.8/Crypto/PubKey/ECC/ECDSA.hs0000644000000000000000000000523712456261417016767 0ustar0000000000000000-- | /WARNING:/ Signature operations may leak the private key. Signature verification -- should be safe. module Crypto.PubKey.ECC.ECDSA ( module Crypto.Types.PubKey.ECDSA , signWith , sign , verify ) where import Control.Monad import Crypto.Random import Data.Bits (shiftR) import Data.ByteString (ByteString) import Crypto.Number.ModArithmetic (inverse) import Crypto.Number.Serialize import Crypto.Number.Generate import Crypto.Types.PubKey.ECDSA import Crypto.Types.PubKey.ECC import Crypto.PubKey.HashDescr import Crypto.PubKey.ECC.Prim -- | Sign message using the private key and an explicit k number. -- -- /WARNING:/ Vulnerable to timing attacks. signWith :: Integer -- ^ k random number -> PrivateKey -- ^ private key -> HashFunction -- ^ hash function -> ByteString -- ^ message to sign -> Maybe Signature signWith k (PrivateKey curve d) hash msg = do let z = tHash hash msg n CurveCommon _ _ g n _ = common_curve curve let point = pointMul curve k g r <- case point of PointO -> Nothing Point x _ -> return $ x `mod` n kInv <- inverse k n let s = kInv * (z + r * d) `mod` n when (r == 0 || s == 0) Nothing return $ Signature r s -- | Sign message using the private key. -- -- /WARNING:/ Vulnerable to timing attacks. sign :: CPRG g => g -> PrivateKey -> HashFunction -> ByteString -> (Signature, g) sign rng pk hash msg = case signWith k pk hash msg of Nothing -> sign rng' pk hash msg Just sig -> (sig, rng') where n = ecc_n . common_curve $ private_curve pk (k, rng') = generateBetween rng 1 (n - 1) -- | Verify a bytestring using the public key. verify :: HashFunction -> PublicKey -> Signature -> ByteString -> Bool verify _ (PublicKey _ PointO) _ _ = False verify hash pk@(PublicKey curve q) (Signature r s) msg | r < 1 || r >= n || s < 1 || s >= n = False | otherwise = maybe False (r ==) $ do w <- inverse s n let z = tHash hash msg n u1 = z * w `mod` n u2 = r * w `mod` n -- TODO: Use Shamir's trick g' = pointMul curve u1 g q' = pointMul curve u2 q x = pointAdd curve g' q' case x of PointO -> Nothing Point x1 _ -> return $ x1 `mod` n where n = ecc_n cc g = ecc_g cc cc = common_curve $ public_curve pk -- | Truncate and hash. tHash :: HashFunction -> ByteString -> Integer -> Integer tHash hash m n | d > 0 = shiftR e d | otherwise = e where e = os2ip $ hash m d = log2 e - log2 n log2 = ceiling . logBase (2 :: Double) . fromIntegral crypto-pubkey-0.2.8/Crypto/PubKey/ECC/Generate.hs0000644000000000000000000000150712456261417017676 0ustar0000000000000000-- | Signature generation. module Crypto.PubKey.ECC.Generate where import Crypto.Random (CPRG) import Crypto.Types.PubKey.ECC import Crypto.Types.PubKey.ECDSA import Crypto.Number.Generate import Crypto.PubKey.ECC.Prim -- | Generate Q given d. -- -- /WARNING:/ Vulnerable to timing attacks. generateQ :: Curve -> Integer -> Point generateQ curve d = pointMul curve d g where g = ecc_g $ common_curve curve -- | Generate a pair of (private, public) key. -- -- /WARNING:/ Vulnerable to timing attacks. generate :: CPRG g => g -- ^ CPRG -> Curve -- ^ Elliptic Curve -> ((PublicKey, PrivateKey), g) generate rng curve = ((PublicKey curve q, PrivateKey curve d), rng') where (d, rng') = generateBetween rng 1 (n - 1) q = generateQ curve d n = ecc_n $ common_curve curve crypto-pubkey-0.2.8/Crypto/PubKey/ECC/Prim.hs0000644000000000000000000001015212456261417017047 0ustar0000000000000000-- | Elliptic Curve Arithmetic. -- -- /WARNING:/ These functions are vulnerable to timing attacks. module Crypto.PubKey.ECC.Prim ( pointAdd , pointDouble , pointMul , isPointAtInfinity , isPointValid ) where import Data.Maybe import Crypto.Number.ModArithmetic import Crypto.Number.F2m import Crypto.Types.PubKey.ECC --TODO: Extract helper function for `fromMaybe PointO...` -- | Elliptic Curve point addition. -- -- /WARNING:/ Vulnerable to timing attacks. pointAdd :: Curve -> Point -> Point -> Point pointAdd _ PointO PointO = PointO pointAdd _ PointO q = q pointAdd _ p PointO = p pointAdd c@(CurveFP (CurvePrime pr _)) p@(Point xp yp) q@(Point xq yq) | p == Point xq (-yq) = PointO | p == q = pointDouble c p | otherwise = fromMaybe PointO $ do s <- divmod (yp - yq) (xp - xq) pr let xr = (s ^ (2::Int) - xp - xq) `mod` pr yr = (s * (xp - xr) - yp) `mod` pr return $ Point xr yr pointAdd c@(CurveF2m (CurveBinary fx cc)) p@(Point xp yp) q@(Point xq yq) | p == Point xq (xq `addF2m` yq) = PointO | p == q = pointDouble c p | otherwise = fromMaybe PointO $ do s <- divF2m fx (yp `addF2m` yq) (xp `addF2m` xq) let xr = mulF2m fx s s `addF2m` s `addF2m` xp `addF2m` xq `addF2m` a yr = mulF2m fx s (xp `addF2m` xr) `addF2m` xr `addF2m` yp return $ Point xr yr where a = ecc_a cc -- | Elliptic Curve point doubling. -- -- /WARNING:/ Vulnerable to timing attacks. -- -- This perform the following calculation: -- > lambda = (3 * xp ^ 2 + a) / 2 yp -- > xr = lambda ^ 2 - 2 xp -- > yr = lambda (xp - xr) - yp -- -- With binary curve: -- > xp == 0 => P = O -- > otherwise => -- > s = xp + (yp / xp) -- > xr = s ^ 2 + s + a -- > yr = xp ^ 2 + (s+1) * xr -- pointDouble :: Curve -> Point -> Point pointDouble _ PointO = PointO pointDouble (CurveFP (CurvePrime pr cc)) (Point xp yp) = fromMaybe PointO $ do lambda <- divmod (3 * xp ^ (2::Int) + a) (2 * yp) pr let xr = (lambda ^ (2::Int) - 2 * xp) `mod` pr yr = (lambda * (xp - xr) - yp) `mod` pr return $ Point xr yr where a = ecc_a cc pointDouble (CurveF2m (CurveBinary fx cc)) (Point xp yp) | xp == 0 = PointO | otherwise = fromMaybe PointO $ do s <- return . addF2m xp =<< divF2m fx yp xp let xr = mulF2m fx s s `addF2m` s `addF2m` a yr = mulF2m fx xp xp `addF2m` mulF2m fx xr (s `addF2m` 1) return $ Point xr yr where a = ecc_a cc -- | Elliptic curve point multiplication (double and add algorithm). -- -- /WARNING:/ Vulnerable to timing attacks. pointMul :: Curve -> Integer -> Point -> Point pointMul _ _ PointO = PointO pointMul c n p@(Point xp yp) | n < 0 = pointMul c (-n) (Point xp (-yp)) | n == 0 = PointO | n == 1 = p | odd n = pointAdd c p (pointMul c (n - 1) p) | otherwise = pointMul c (n `div` 2) (pointDouble c p) -- | Check if a point is the point at infinity. isPointAtInfinity :: Point -> Bool isPointAtInfinity PointO = True isPointAtInfinity _ = False -- | check if a point is on specific curve -- -- This perform three checks: -- -- * x is not out of range -- * y is not out of range -- * the equation @y^2 = x^3 + a*x + b (mod p)@ holds isPointValid :: Curve -> Point -> Bool isPointValid _ PointO = True isPointValid (CurveFP (CurvePrime p cc)) (Point x y) = isValid x && isValid y && (y ^ (2 :: Int)) `eqModP` (x ^ (3 :: Int) + a * x + b) where a = ecc_a cc b = ecc_b cc eqModP z1 z2 = (z1 `mod` p) == (z2 `mod` p) isValid e = e >= 0 && e < p isPointValid curve@(CurveF2m (CurveBinary fx cc)) pt@(Point x y) = and [ isValid x , isValid y , ((((x `add` a) `mul` x `add` y) `mul` x) `add` b `add` (squareF2m fx y)) == 0 ] where a = ecc_a cc b = ecc_b cc add = addF2m mul = mulF2m fx isValid e = modF2m fx e == e -- | div and mod divmod :: Integer -> Integer -> Integer -> Maybe Integer divmod y x m = do i <- inverse (x `mod` m) m return $ y * i `mod` m crypto-pubkey-0.2.8/Crypto/PubKey/RSA/0000755000000000000000000000000012456261417015640 5ustar0000000000000000crypto-pubkey-0.2.8/Crypto/PubKey/RSA/OAEP.hs0000644000000000000000000001343612456261417016727 0ustar0000000000000000-- | -- Module : Crypto.PubKey.RSA.OAEP -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- -- RSA OAEP mode -- -- {-# LANGUAGE OverloadedStrings #-} module Crypto.PubKey.RSA.OAEP ( OAEPParams(..) , defaultOAEPParams -- * OAEP encryption , encryptWithSeed , encrypt -- * OAEP decryption , decrypt , decryptSafer ) where import Crypto.Random import Crypto.Types.PubKey.RSA import Crypto.PubKey.HashDescr import Crypto.PubKey.MaskGenFunction import Crypto.PubKey.RSA.Prim import Crypto.PubKey.RSA.Types import Crypto.PubKey.RSA (generateBlinder) import Crypto.PubKey.Internal (and') import Data.ByteString (ByteString) import qualified Data.ByteString as B import Data.Bits (xor) -- | Parameters for OAEP encryption/decryption data OAEPParams = OAEPParams { oaepHash :: HashFunction -- ^ Hash function to use. , oaepMaskGenAlg :: MaskGenAlgorithm -- ^ Mask Gen algorithm to use. , oaepLabel :: Maybe ByteString -- ^ Optional label prepended to message. } -- | Default Params with a specified hash function defaultOAEPParams :: HashFunction -> OAEPParams defaultOAEPParams hashF = OAEPParams { oaepHash = hashF , oaepMaskGenAlg = mgf1 , oaepLabel = Nothing } -- | Encrypt a message using OAEP with a predefined seed. encryptWithSeed :: ByteString -- ^ Seed -> OAEPParams -- ^ OAEP params to use for encryption -> PublicKey -- ^ Public key. -> ByteString -- ^ Message to encrypt -> Either Error ByteString encryptWithSeed seed oaep pk msg | k < 2*hashLen+2 = Left InvalidParameters | B.length seed /= hashLen = Left InvalidParameters | mLen > k - 2*hashLen-2 = Left MessageTooLong | otherwise = Right $ ep pk em where -- parameters k = public_size pk mLen = B.length msg hashF = oaepHash oaep mgf = (oaepMaskGenAlg oaep) hashF labelHash = hashF $ maybe B.empty id $ oaepLabel oaep hashLen = B.length labelHash -- put fields ps = B.replicate (k - mLen - 2*hashLen - 2) 0 db = B.concat [labelHash, ps, B.singleton 0x1, msg] dbmask = mgf seed (k - hashLen - 1) maskedDB = B.pack $ B.zipWith xor db dbmask seedMask = mgf maskedDB hashLen maskedSeed = B.pack $ B.zipWith xor seed seedMask em = B.concat [B.singleton 0x0,maskedSeed,maskedDB] -- | Encrypt a message using OAEP encrypt :: CPRG g => g -- ^ random number generator. -> OAEPParams -- ^ OAEP params to use for encryption. -> PublicKey -- ^ Public key. -> ByteString -- ^ Message to encrypt -> (Either Error ByteString, g) encrypt g oaep pk msg = (encryptWithSeed seed oaep pk msg, g') where hashF = oaepHash oaep hashLen = B.length (hashF B.empty) (seed, g') = cprgGenerate hashLen g -- | un-pad a OAEP encoded message. -- -- It doesn't apply the RSA decryption primitive unpad :: OAEPParams -- ^ OAEP params to use -> Int -- ^ size of the key in bytes -> ByteString -- ^ encoded message (not encrypted) -> Either Error ByteString unpad oaep k em | paddingSuccess = Right msg | otherwise = Left MessageNotRecognized where -- parameters hashF = oaepHash oaep mgf = (oaepMaskGenAlg oaep) hashF labelHash = hashF $ maybe B.empty id $ oaepLabel oaep hashLen = B.length labelHash -- getting em's fields (pb, em0) = B.splitAt 1 em (maskedSeed,maskedDB) = B.splitAt hashLen em0 seedMask = mgf maskedDB hashLen seed = B.pack $ B.zipWith xor maskedSeed seedMask dbmask = mgf seed (k - hashLen - 1) db = B.pack $ B.zipWith xor maskedDB dbmask -- getting db's fields (labelHash',db1) = B.splitAt hashLen db (_,db2) = B.break (/= 0) db1 (ps1,msg) = B.splitAt 1 db2 paddingSuccess = and' [ labelHash' == labelHash -- no need for constant eq , ps1 == "\x01" , pb == "\x00" ] -- | Decrypt a ciphertext using OAEP -- -- When the signature is not in a context where an attacker could gain -- information from the timing of the operation, the blinder can be set to None. -- -- If unsure always set a blinder or use decryptSafer decrypt :: Maybe Blinder -- ^ Optional blinder -> OAEPParams -- ^ OAEP params to use for decryption -> PrivateKey -- ^ Private key -> ByteString -- ^ Cipher text -> Either Error ByteString decrypt blinder oaep pk cipher | B.length cipher /= k = Left MessageSizeIncorrect | k < 2*hashLen+2 = Left InvalidParameters | otherwise = unpad oaep (private_size pk) $ dp blinder pk cipher where -- parameters k = private_size pk hashF = oaepHash oaep hashLen = B.length (hashF B.empty) -- | Decrypt a ciphertext using OAEP and by automatically generating a blinder. decryptSafer :: CPRG g => g -- ^ random number generator -> OAEPParams -- ^ OAEP params to use for decryption -> PrivateKey -- ^ Private key -> ByteString -- ^ Cipher text -> (Either Error ByteString, g) decryptSafer rng oaep pk cipher = (decrypt (Just blinder) oaep pk cipher, rng') where (blinder, rng') = generateBlinder rng (private_n pk) crypto-pubkey-0.2.8/Crypto/PubKey/RSA/PKCS15.hs0000644000000000000000000001270312456261417017105 0ustar0000000000000000-- | -- Module : Crypto.PubKey.RSA.PKCS15 -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- {-# LANGUAGE OverloadedStrings #-} module Crypto.PubKey.RSA.PKCS15 ( -- * padding and unpadding pad , padSignature , unpad -- * private key operations , decrypt , decryptSafer , sign , signSafer -- * public key operations , encrypt , verify ) where import Crypto.Random import Crypto.PubKey.Internal (and') import Crypto.Types.PubKey.RSA import Data.ByteString (ByteString) import qualified Data.ByteString as B import Crypto.PubKey.RSA.Prim import Crypto.PubKey.RSA.Types import Crypto.PubKey.RSA (generateBlinder) import Crypto.PubKey.HashDescr -- | This produce a standard PKCS1.5 padding for encryption pad :: CPRG g => g -> Int -> ByteString -> Either Error (ByteString, g) pad rng len m | B.length m > len - 11 = Left MessageTooLong | otherwise = let (padding, rng') = getNonNullRandom rng (len - B.length m - 3) in Right (B.concat [ B.singleton 0, B.singleton 2, padding, B.singleton 0, m ], rng') where {- get random non-null bytes -} getNonNullRandom :: CPRG g => g -> Int -> (ByteString, g) getNonNullRandom g n = let (bs0,g') = cprgGenerate n g bytes = B.pack $ filter (/= 0) $ B.unpack $ bs0 left = (n - B.length bytes) in if left == 0 then (bytes, g') else let (bend, g'') = getNonNullRandom g' left in (bytes `B.append` bend, g'') -- | Produce a standard PKCS1.5 padding for signature padSignature :: Int -> ByteString -> Either Error ByteString padSignature klen signature | klen < siglen+1 = Left SignatureTooLong | otherwise = Right $ B.concat [B.singleton 0,B.singleton 1,padding,B.singleton 0,signature] where siglen = B.length signature padding = B.replicate (klen - siglen - 3) 0xff -- | Try to remove a standard PKCS1.5 encryption padding. unpad :: ByteString -> Either Error ByteString unpad packed | paddingSuccess = Right m | otherwise = Left MessageNotRecognized where (zt, ps0m) = B.splitAt 2 packed (ps, zm) = B.span (/= 0) ps0m (z, m) = B.splitAt 1 zm paddingSuccess = and' [ zt == "\x00\x02" , z == "\x00" , B.length ps >= 8 ] -- | decrypt message using the private key. -- -- When the decryption is not in a context where an attacker could gain -- information from the timing of the operation, the blinder can be set to None. -- -- If unsure always set a blinder or use decryptSafer decrypt :: Maybe Blinder -- ^ optional blinder -> PrivateKey -- ^ RSA private key -> ByteString -- ^ cipher text -> Either Error ByteString decrypt blinder pk c | B.length c /= (private_size pk) = Left MessageSizeIncorrect | otherwise = unpad $ dp blinder pk c -- | decrypt message using the private key and by automatically generating a blinder. decryptSafer :: CPRG g => g -- ^ random generator -> PrivateKey -- ^ RSA private key -> ByteString -- ^ cipher text -> (Either Error ByteString, g) decryptSafer rng pk b = let (blinder, rng') = generateBlinder rng (private_n pk) in (decrypt (Just blinder) pk b, rng') -- | encrypt a bytestring using the public key and a CPRG random generator. -- -- the message need to be smaller than the key size - 11 encrypt :: CPRG g => g -> PublicKey -> ByteString -> (Either Error ByteString, g) encrypt rng pk m = do case pad rng (public_size pk) m of Left err -> (Left err, rng) Right (em, rng') -> (Right (ep pk em), rng') -- | sign message using private key, a hash and its ASN1 description -- -- When the signature is not in a context where an attacker could gain -- information from the timing of the operation, the blinder can be set to None. -- -- If unsure always set a blinder or use signSafer sign :: Maybe Blinder -- ^ optional blinder -> HashDescr -- ^ hash descriptor -> PrivateKey -- ^ private key -> ByteString -- ^ message to sign -> Either Error ByteString sign blinder hashDescr pk m = dp blinder pk `fmap` makeSignature hashDescr (private_size pk) m -- | sign message using the private key and by automatically generating a blinder. signSafer :: CPRG g => g -- ^ random generator -> HashDescr -- ^ Hash descriptor -> PrivateKey -- ^ private key -> ByteString -- ^ message to sign -> (Either Error ByteString, g) signSafer rng hashDescr pk m = let (blinder, rng') = generateBlinder rng (private_n pk) in (sign (Just blinder) hashDescr pk m, rng') -- | verify message with the signed message verify :: HashDescr -> PublicKey -> ByteString -> ByteString -> Bool verify hashDescr pk m sm = case makeSignature hashDescr (public_size pk) m of Left _ -> False Right s -> s == (ep pk sm) {- makeSignature for sign and verify -} makeSignature :: HashDescr -> Int -> ByteString -> Either Error ByteString makeSignature hashDescr klen m = padSignature klen signature where signature = (digestToASN1 hashDescr) $ (hashFunction hashDescr) m crypto-pubkey-0.2.8/Crypto/PubKey/RSA/Prim.hs0000644000000000000000000000470712456261417017113 0ustar0000000000000000-- | -- Module : Crypto.PubKey.RSA.Prim -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- module Crypto.PubKey.RSA.Prim ( -- * decrypt primitive dp -- * encrypt primitive , ep ) where import Data.ByteString (ByteString) import Crypto.PubKey.RSA.Types (Blinder(..)) import Crypto.Types.PubKey.RSA import Crypto.Number.ModArithmetic (expFast, expSafe) import Crypto.Number.Serialize (os2ip, i2ospOf_) {- dpSlow computes the decrypted message not using any precomputed cache value. only n and d need to valid. -} dpSlow :: PrivateKey -> ByteString -> ByteString dpSlow pk c = i2ospOf_ (private_size pk) $ expSafe (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 :: Blinder -> PrivateKey -> ByteString -> ByteString dpFast (Blinder r rm1) pk c = i2ospOf_ (private_size pk) (multiplication rm1 (m2 + h * (private_q pk)) (private_n pk)) where re = expFast r (public_e $ private_pub pk) (private_n pk) iC = multiplication re (os2ip c) (private_n pk) m1 = expSafe iC (private_dP pk) (private_p pk) m2 = expSafe iC (private_dQ pk) (private_q pk) h = ((private_qinv pk) * (m1 - m2)) `mod` (private_p pk) dpFastNoBlinder :: PrivateKey -> ByteString -> ByteString dpFastNoBlinder pk c = i2ospOf_ (private_size pk) (m2 + h * (private_q pk)) where iC = os2ip c m1 = expSafe iC (private_dP pk) (private_p pk) m2 = expSafe iC (private_dQ pk) (private_q pk) h = ((private_qinv pk) * (m1 - m2)) `mod` (private_p pk) -- | Compute the RSA decrypt primitive. -- if the p and q numbers are available, then dpFast is used -- otherwise, we use dpSlow which only need d and n. dp :: Maybe Blinder -> PrivateKey -> ByteString -> ByteString dp blinder pk | private_p pk /= 0 && private_q pk /= 0 = maybe dpFastNoBlinder dpFast blinder $ pk | otherwise = dpSlow pk -- | Compute the RSA encrypt primitive ep :: PublicKey -> ByteString -> ByteString ep pk m = i2ospOf_ (public_size pk) $ expFast (os2ip m) (public_e pk) (public_n pk) -- | multiply 2 integers in Zm only performing the modulo operation if necessary multiplication :: Integer -> Integer -> Integer -> Integer multiplication a b m = (a * b) `mod` m crypto-pubkey-0.2.8/Crypto/PubKey/RSA/PSS.hs0000644000000000000000000001310712456261417016643 0ustar0000000000000000-- | -- Module : Crypto.PubKey.RSA.PSS -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- module Crypto.PubKey.RSA.PSS ( PSSParams(..) , defaultPSSParams , defaultPSSParamsSHA1 -- * Sign and verify functions , signWithSalt , sign , signSafer , verify ) where import Crypto.Random import Crypto.Types.PubKey.RSA import Data.ByteString (ByteString) import Data.Byteable import qualified Data.ByteString as B import Crypto.PubKey.RSA.Prim import Crypto.PubKey.RSA.Types import Crypto.PubKey.RSA (generateBlinder) import Crypto.PubKey.HashDescr import Crypto.PubKey.MaskGenFunction import Crypto.Hash import Data.Bits (xor, shiftR, (.&.)) import Data.Word -- | Parameters for PSS signature/verification. data PSSParams = PSSParams { pssHash :: HashFunction -- ^ Hash function to use , pssMaskGenAlg :: MaskGenAlgorithm -- ^ Mask Gen algorithm to use , pssSaltLength :: Int -- ^ Length of salt. need to be <= to hLen. , pssTrailerField :: Word8 -- ^ Trailer field, usually 0xbc } -- | Default Params with a specified hash function defaultPSSParams :: HashFunction -> PSSParams defaultPSSParams hashF = PSSParams { pssHash = hashF , pssMaskGenAlg = mgf1 , pssSaltLength = B.length $ hashF B.empty , pssTrailerField = 0xbc } -- | Default Params using SHA1 algorithm. defaultPSSParamsSHA1 :: PSSParams defaultPSSParamsSHA1 = defaultPSSParams (toBytes . (hash :: ByteString -> Digest SHA1)) -- | Sign using the PSS parameters and the salt explicitely passed as parameters. -- -- the function ignore SaltLength from the PSS Parameters signWithSalt :: ByteString -- ^ Salt to use -> Maybe Blinder -- ^ optional blinder to use -> PSSParams -- ^ PSS Parameters to use -> PrivateKey -- ^ RSA Private Key -> ByteString -- ^ Message to sign -> Either Error ByteString signWithSalt salt blinder params pk m | k < hashLen + saltLen + 2 = Left InvalidParameters | otherwise = Right $ dp blinder pk em where mHash = (pssHash params) m k = private_size pk dbLen = k - hashLen - 1 saltLen = B.length salt hashLen = B.length (hashF B.empty) hashF = pssHash params pubBits = private_size pk * 8 -- to change if public_size is converted in bytes m' = B.concat [B.replicate 8 0,mHash,salt] h = hashF m' db = B.concat [B.replicate (dbLen - saltLen - 1) 0,B.singleton 1,salt] dbmask = (pssMaskGenAlg params) hashF h dbLen maskedDB = B.pack $ normalizeToKeySize pubBits $ B.zipWith xor db dbmask em = B.concat [maskedDB, h, B.singleton (pssTrailerField params)] -- | Sign using the PSS Parameters sign :: CPRG g => g -- ^ random generator to use to generate the salt -> Maybe Blinder -- ^ optional blinder to use -> PSSParams -- ^ PSS Parameters to use -> PrivateKey -- ^ RSA Private Key -> ByteString -- ^ Message to sign -> (Either Error ByteString, g) sign rng blinder params pk m = (signWithSalt salt blinder params pk m, rng') where (salt,rng') = cprgGenerate (pssSaltLength params) rng -- | Sign using the PSS Parameters and an automatically generated blinder. signSafer :: CPRG g => g -- ^ random generator -> PSSParams -- ^ PSS Parameters to use -> PrivateKey -- ^ private key -> ByteString -- ^ message to sign -> (Either Error ByteString, g) signSafer rng params pk m = sign rng' (Just blinder) params pk m where (blinder, rng') = generateBlinder rng (private_n pk) -- | Verify a signature using the PSS Parameters verify :: PSSParams -- ^ PSS Parameters to use to verify, -- this need to be identical to the parameters when signing -> PublicKey -- ^ RSA Public Key -> ByteString -- ^ Message to verify -> ByteString -- ^ Signature -> Bool verify params pk m s | public_size pk /= B.length s = False | B.last em /= pssTrailerField params = False | not (B.all (== 0) ps0) = False | b1 /= B.singleton 1 = False | otherwise = h == h' where -- parameters hashF = pssHash params hashLen = B.length (hashF B.empty) dbLen = public_size pk - hashLen - 1 pubBits = public_size pk * 8 -- to change if public_size is converted in bytes -- unmarshall fields em = ep pk s maskedDB = B.take (B.length em - hashLen - 1) em h = B.take hashLen $ B.drop (B.length maskedDB) em dbmask = (pssMaskGenAlg params) hashF h dbLen db = B.pack $ normalizeToKeySize pubBits $ B.zipWith xor maskedDB dbmask (ps0,z) = B.break (== 1) db (b1,salt) = B.splitAt 1 z mHash = hashF m m' = B.concat [B.replicate 8 0,mHash,salt] h' = hashF m' normalizeToKeySize :: Int -> [Word8] -> [Word8] normalizeToKeySize _ [] = [] -- very unlikely normalizeToKeySize bits (x:xs) = x .&. mask : xs where mask = if sh > 0 then 0xff `shiftR` (8-sh) else 0xff sh = ((bits-1) .&. 0x7) crypto-pubkey-0.2.8/Crypto/PubKey/RSA/Types.hs0000644000000000000000000000171212456261417017301 0ustar0000000000000000-- | -- Module : Crypto.PubKey.RSA.Types -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good -- module Crypto.PubKey.RSA.Types ( Error(..) , Blinder(..) ) where -- | Blinder which is used to obfuscate the timing -- of the decryption primitive (used by decryption and signing). data Blinder = Blinder !Integer !Integer deriving (Show,Eq) -- | error possible during encryption, decryption or signing. 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 | MessageNotRecognized -- ^ the message decrypted doesn't have a PKCS15 structure (0 2 .. 0 msg) | SignatureTooLong -- ^ the message's digest is too long | InvalidParameters -- ^ some parameters lead to breaking assumptions. deriving (Show,Eq) crypto-pubkey-0.2.8/Tests/0000755000000000000000000000000012456261417013636 5ustar0000000000000000crypto-pubkey-0.2.8/Tests/EccArithmetic.hs0000644000000000000000000000232612456261417016701 0ustar0000000000000000module EccArithmetic (properties_ecc_arithmetic) where import Test.Tasty.QuickCheck import Crypto.Types.PubKey.ECC import Crypto.PubKey.ECC.Generate import Crypto.PubKey.ECC.Prim data GeneratePoint1 = GeneratePoint1 Curve Point deriving (Show,Eq) data GeneratePoint2 = GeneratePoint2 Curve Point Point deriving (Show,Eq) arbitraryPoint curve = do sec <- choose (1,n) return $ pointMul curve sec g where common = common_curve curve n = ecc_n common g = ecc_g common instance Arbitrary Curve where arbitrary = elements $ map getCurveByName $ enumFrom SEC_p112r1 instance Arbitrary GeneratePoint1 where arbitrary = do curve <- arbitrary p1 <- arbitraryPoint curve return $ GeneratePoint1 curve p1 instance Arbitrary GeneratePoint2 where arbitrary = do curve <- arbitrary p1 <- arbitraryPoint curve p2 <- arbitraryPoint curve return $ GeneratePoint2 curve p1 p2 properties_ecc_arithmetic = [ testProperty "commutative" $ \(GeneratePoint2 curve p1 p2) -> pointAdd curve p1 p2 == pointAdd curve p2 p1 , testProperty "add-neutral" $ \(GeneratePoint1 curve p1) -> pointAdd curve p1 PointO == p1 ] crypto-pubkey-0.2.8/Tests/KAT.hs0000644000000000000000000000274412456261417014620 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module KAT where import Test.Tasty import Test.Tasty.HUnit import Test.Tasty.QuickCheck import System.IO (hFlush, stdout) import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import Crypto.PubKey.RSA import Crypto.PubKey.MaskGenFunction import qualified Crypto.Hash.SHA1 as SHA1 import KAT.OAEP import KAT.PSS import KAT.DSA import KAT.ECC import KAT.ECDSA data VectorMgf = VectorMgf { seed :: ByteString , dbMask :: ByteString } doMGFTest (i, vmgf) = testCase (show i) (dbMask vmgf @=? actual) where actual = mgf1 SHA1.hash (seed vmgf) (B.length $ dbMask vmgf) vectorsMGF = [ VectorMgf { seed = "\xdf\x1a\x89\x6f\x9d\x8b\xc8\x16\xd9\x7c\xd7\xa2\xc4\x3b\xad\x54\x6f\xbe\x8c\xfe" , dbMask = "\x66\xe4\x67\x2e\x83\x6a\xd1\x21\xba\x24\x4b\xed\x65\x76\xb8\x67\xd9\xa4\x47\xc2\x8a\x6e\x66\xa5\xb8\x7d\xee\x7f\xbc\x7e\x65\xaf\x50\x57\xf8\x6f\xae\x89\x84\xd9\xba\x7f\x96\x9a\xd6\xfe\x02\xa4\xd7\x5f\x74\x45\xfe\xfd\xd8\x5b\x6d\x3a\x47\x7c\x28\xd2\x4b\xa1\xe3\x75\x6f\x79\x2d\xd1\xdc\xe8\xca\x94\x44\x0e\xcb\x52\x79\xec\xd3\x18\x3a\x31\x1f\xc8\x97\x39\xa9\x66\x43\x13\x6e\x8b\x0f\x46\x5e\x87\xa4\x53\x5c\xd4\xc5\x9b\x10\x02\x8d" } ] katTests = [ testGroup "MGF1" $ map doMGFTest (zip [0..] vectorsMGF) , pssTests , oaepTests , dsaTests , eccTests , ecdsaTests ] newKats = [ eccKatTests ] crypto-pubkey-0.2.8/Tests/PregenKeys.hs0000644000000000000000000000656412456261417016261 0ustar0000000000000000module PregenKeys where import qualified Crypto.PubKey.RSA as RSA import qualified Crypto.PubKey.DSA as DSA import qualified Crypto.PubKey.ECC.ECDSA as ECDSA import qualified Crypto.Types.PubKey.ECC as ECC import qualified Crypto.PubKey.DH as DH 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 } dsaParams = DSA.Params { DSA.params_p = p, DSA.params_g = g, DSA.params_q = 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 } ecdsaCurveP = ECC.getCurveByName ECC.SEC_p160r1 ecdsaPrivatekeyP = ECDSA.PrivateKey ecdsaCurveP 971761939728640320549601132085879836204587084162 ecdsaPublickeyP = ECDSA.PublicKey ecdsaCurveP (ECC.Point 466448783855397898016055842232266600516272889280 1110706324081757720403272427311003102474457754220) ecdsaCurveB = ECC.getCurveByName ECC.SEC_t163k1 ecdsaPrivatekeyB = ECDSA.PrivateKey ecdsaCurveB 5321230001203043918714616464614664646674949479949 ecdsaPublickeyB = ECDSA.PublicKey ecdsaCurveB (ECC.Point 0x37d529fa37e42195f10111127ffb2bb38644806bc 0x447026eee8b34157f3eb51be5185d2be0249ed776) crypto-pubkey-0.2.8/Tests/RNG.hs0000644000000000000000000000335012456261417014621 0ustar0000000000000000module RNG where import Data.Word import Data.List (foldl') import Data.Byteable import qualified Data.ByteString as B import Crypto.Random import Control.Arrow (first) {- 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)) = (r, g) where mz2 = 36969 * (mz `mod` 65536) mw2 = 18070 * (mw `mod` 65536) r = fromIntegral (mz2 + mw2) g = Rng (mz2, mw2) getBytes :: Int -> Rng -> ([Word8], Rng) getBytes 0 g = ([], g) getBytes n g = let (b, g') = getByte g (l, g'') = getBytes (n-1) g' in (b:l, g'') instance CPRG Rng where cprgCreate pool = let ent = grabEntropy 4 pool in generate (B.unpack $ toBytes ent) cprgSetReseedThreshold _ g = g cprgGenerate len g = first B.pack $ getBytes len g cprgGenerateWithEntropy = cprgGenerate cprgFork g = let (bs, g') = getBytes 4 g in case bs of [a,b,c,d] -> let g2 = Rng (fromIntegral a * 256 + fromIntegral b, fromIntegral c * 256 + fromIntegral d) in (g2, g') _ -> error "getBytes assertion" generate :: [Word8] -> Rng generate [a,b,c,d] = Rng (fromIntegral a * 256 + fromIntegral b, fromIntegral c * 256 + fromIntegral d) generate _ = error "generate assertion: need 4 bytes" reseed :: B.ByteString -> Rng -> Rng reseed bs (Rng (a,b)) = Rng (fromIntegral a', b') where a' = foldl' (\v i -> ((fromIntegral v) + (fromIntegral i) * 36969) `mod` 65536) a l b' = foldl' (\v i -> ((fromIntegral v) + (fromIntegral i) * 18070) `mod` 65536) b l l = B.unpack bs rng :: Rng rng = Rng (2,2) crypto-pubkey-0.2.8/Tests/Tests.hs0000644000000000000000000001654212456261417015304 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} import Test.Tasty import Test.Tasty.QuickCheck import System.IO (hFlush, stdout) import Control.Monad import Control.Arrow (first) import Control.Applicative ((<$>)) import Data.List (intercalate) import Data.Char import Data.Bits import Data.Word import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import qualified Crypto.PubKey.RSA as RSA import qualified Crypto.PubKey.RSA.PKCS15 as RSAPKCS15 import qualified Crypto.PubKey.RSA.OAEP as RSAOAEP import qualified Crypto.PubKey.DSA as DSA import qualified Crypto.PubKey.ECC.ECDSA as ECDSA import Crypto.Types.PubKey.ECC import Crypto.PubKey.ECC.Generate import qualified Crypto.PubKey.DH as DH import Crypto.Number.Serialize (i2osp) import Crypto.PubKey.HashDescr import qualified Crypto.Hash.SHA1 as SHA1 import RNG import KAT import PregenKeys import EccArithmetic withAleasInteger :: Rng -> Seed -> (Rng -> (a,Rng)) -> a withAleasInteger rng (Seed i) f = fst $ f $ reseed (i2osp (if i < 0 then -i else i)) rng withRNG :: Seed -> (Rng -> (a,Rng)) -> a withRNG seed f = withAleasInteger rng seed f --withArbitraryRNG :: (Rng -> (a,Rng)) -> Arbitrary a withArbitraryRNG f = arbitrary >>= \seed -> return (withAleasInteger rng seed f) newtype PositiveSmall = PositiveSmall Integer deriving (Show,Eq) instance Arbitrary PositiveSmall where arbitrary = PositiveSmall `fmap` (resize (2^5) (arbitrarySizedIntegral `suchThat` (\i -> i > 0 && i < 2^5))) data Range = Range Integer Integer deriving (Show,Eq) instance Arbitrary Range where arbitrary = do x <- resize (2^30) (arbitrarySizedIntegral `suchThat` (\i -> i >= 40000 && i < 2^30)) o <- resize (2^10) (arbitrarySizedIntegral `suchThat` (\i -> i >= 1000 && i < 2^10)) return $ Range x (x+o) newtype Seed = Seed Integer deriving (Eq) instance Show Seed where show s = "Seed " ++ show s -- "seed" instance Arbitrary Seed where arbitrary = Seed `fmap` (resize (2^30) (arbitrarySizedIntegral `suchThat` (\x -> x > 2^6 && x < 2^30))) data RSAMessage = RSAMessage RSA.Blinder B.ByteString deriving (Show, Eq) data RSAOAEPMessage = RSAOAEPMessage RSA.Blinder B.ByteString RSAOAEP.OAEPParams instance Show RSAOAEPMessage where show (RSAOAEPMessage a1 b1 _) = "RSAOAEPMessage " ++ show a1 ++ " " ++ show b1 instance Eq RSAOAEPMessage where (RSAOAEPMessage a1 b1 _) == (RSAOAEPMessage a2 b2 _) = a1 == a2 && b1 == b2 genBS :: Int -> Gen B.ByteString genBS sz = (B.pack . map fromIntegral) `fmap` replicateM sz (choose (0,255) :: Gen Int) instance Arbitrary RSAOAEPMessage where arbitrary = do let hashLen = B.length (SHA1.hash B.empty) sz <- choose (0, 128 - 2*hashLen - 2) blinder <- withArbitraryRNG (\g -> RSA.generateBlinder g (RSA.public_n rsaPublickey)) ws <- genBS sz return $ RSAOAEPMessage blinder ws (RSAOAEP.defaultOAEPParams SHA1.hash) instance Arbitrary RSAMessage where arbitrary = do sz <- choose (0, 128 - 11) blinder <- withArbitraryRNG (\g -> RSA.generateBlinder g (RSA.public_n rsaPublickey)) ws <- genBS sz return $ RSAMessage blinder ws prop_rsa_pkcs15_valid fast blinding (RSAMessage blindR msg) = (either Left (doDecrypt pk) $ fst $ RSAPKCS15.encrypt rng rsaPublickey msg) == Right msg where pk = if fast then rsaPrivatekey else rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 } doDecrypt = RSAPKCS15.decrypt (if blinding then Just blindR else Nothing) prop_rsa_oaep_valid fast blinding (RSAOAEPMessage blindR msg oaepParams) = (either Left (doDecrypt oaepParams pk) $ fst $ RSAOAEP.encrypt rng oaepParams rsaPublickey msg) `assertEq` Right msg where pk = if fast then rsaPrivatekey else rsaPrivatekey { RSA.private_p = 0, RSA.private_q = 0 } doDecrypt = RSAOAEP.decrypt (if blinding then Just blindR else Nothing) assertEq (Right got) (Right exp) = if got == exp then True else error ("got: " ++ show got ++ "\nexp: " ++ show exp) assertEq (Left got) (Right exp) = error ("got Left: " ++ show got) prop_rsa_sign_valid fast (RSAMessage _ msg) = (either (const False) (\smsg -> verify msg smsg) $ sign msg) == True where verify = RSAPKCS15.verify hashDescrSHA1 rsaPublickey sign = RSAPKCS15.sign Nothing hashDescrSHA1 pk 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 prop_dsa_valid (RSAMessage _ msg) = DSA.verify (SHA1.hash) dsaPublickey signature msg where (signature, rng') = DSA.sign rng dsaPrivatekey (SHA1.hash) msg prop_ecdsa_prime_valid (RSAMessage _ msg) = ECDSA.verify SHA1.hash ecdsaPublickeyP signature msg where (signature, rng') = ECDSA.sign rng ecdsaPrivatekeyP SHA1.hash msg prop_ecdsa_binary_valid (RSAMessage _ msg) = ECDSA.verify SHA1.hash ecdsaPublickeyB signature msg where (signature, rng') = ECDSA.sign rng ecdsaPrivatekeyB SHA1.hash msg prop_ecdsa_curve_valid keypair = ECDSA.verify SHA1.hash pubkey signature "test" where (signature, rng') = ECDSA.sign rng privkey SHA1.hash "test" pubkey = ECDSA.toPublicKey keypair privkey = ECDSA.toPrivateKey keypair instance Arbitrary ECDSA.KeyPair where arbitrary = do curve <- arbitrary d <- getPositive <$> (arbitrary :: Gen (Positive Integer)) let q = generateQ curve d return $ ECDSA.KeyPair curve q d 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 = DH.Params { DH.params_p = 11, DH.params_g = 7 } asymEncryptionTests = testGroup "assymmetric cipher encryption" [ testProperty "RSA(PKCS15) (slow)" (prop_rsa_pkcs15_valid False False) , testProperty "RSA(PKCS15) (fast)" (prop_rsa_pkcs15_valid True False) , testProperty "RSA(PKCS15) (slow+blind)" (prop_rsa_pkcs15_valid False True) , testProperty "RSA(PKCS15) (fast+blind)" (prop_rsa_pkcs15_valid True True) , testProperty "RSA(OAEP) (slow)" (prop_rsa_oaep_valid False False) , testProperty "RSA(OAEP) (fast)" (prop_rsa_oaep_valid True False) , testProperty "RSA(OAEP) (slow+blind)" (prop_rsa_oaep_valid False True) , testProperty "RSA(OAEP) (fast+blind)" (prop_rsa_oaep_valid True True) ] asymSignatureTests = testGroup "assymmetric cipher signature" [ testProperty "RSA(PKCS15) (slow)" prop_rsa_sign_slow_valid , testProperty "RSA(PKCS15) (fast)" prop_rsa_sign_fast_valid , testProperty "DSA" prop_dsa_valid , testProperty "ECDSA Prime" prop_ecdsa_prime_valid , testProperty "ECDSA Binary" prop_ecdsa_binary_valid , testProperty "ECDSA Curve" prop_ecdsa_curve_valid ] asymOtherTests = testGroup "assymetric other tests" [ testProperty "DH valid" prop_dh_valid , testGroup "ECC arithmetic" properties_ecc_arithmetic ] main = do kats <- sequence newKats defaultMain $ testGroup "crypto-pubkey" [ testGroup "KATs" katTests , testGroup "KAT2s" kats , asymEncryptionTests , asymSignatureTests , asymOtherTests ] crypto-pubkey-0.2.8/Tests/KAT/0000755000000000000000000000000012456261417014255 5ustar0000000000000000crypto-pubkey-0.2.8/Tests/KAT/DSA.hs0000644000000000000000000003134412456261417015225 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module KAT.DSA (dsaTests) where import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import qualified Crypto.PubKey.DSA as DSA import qualified Crypto.Hash.SHA1 as SHA1 import Test.Tasty import Test.Tasty.HUnit data VectorDSA = VectorDSA { pgq :: DSA.Params , msg :: ByteString , x :: Integer , y :: Integer , k :: Integer , r :: Integer , s :: Integer } vectorsSHA1 = [ VectorDSA { msg = "\x3b\x46\x73\x6d\x55\x9b\xd4\xe0\xc2\xc1\xb2\x55\x3a\x33\xad\x3c\x6c\xf2\x3c\xac\x99\x8d\x3d\x0c\x0e\x8f\xa4\xb1\x9b\xca\x06\xf2\xf3\x86\xdb\x2d\xcf\xf9\xdc\xa4\xf4\x0a\xd8\xf5\x61\xff\xc3\x08\xb4\x6c\x5f\x31\xa7\x73\x5b\x5f\xa7\xe0\xf9\xe6\xcb\x51\x2e\x63\xd7\xee\xa0\x55\x38\xd6\x6a\x75\xcd\x0d\x42\x34\xb5\xcc\xf6\xc1\x71\x5c\xca\xaf\x9c\xdc\x0a\x22\x28\x13\x5f\x71\x6e\xe9\xbd\xee\x7f\xc1\x3e\xc2\x7a\x03\xa6\xd1\x1c\x5c\x5b\x36\x85\xf5\x19\x00\xb1\x33\x71\x53\xbc\x6c\x4e\x8f\x52\x92\x0c\x33\xfa\x37\xf4\xe7" , x = 0xc53eae6d45323164c7d07af5715703744a63fc3a , y = 0x313fd9ebca91574e1c2eebe1517c57e0c21b0209872140c5328761bbb2450b33f1b18b409ce9ab7c4cd8fda3391e8e34868357c199e16a6b2eba06d6749def791d79e95d3a4d09b24c392ad89dbf100995ae19c01062056bb14bce005e8731efde175f95b975089bdcdaea562b32786d96f5a31aedf75364008ad4fffebb970b , k = 0x98cbcc4969d845e2461b5f66383dd503712bbcfa , r = 0x50ed0e810e3f1c7cb6ac62332058448bd8b284c0 , s = 0xc6aded17216b46b7e4b6f2a97c1ad7cc3da83fde , pgq = dsaParams } , VectorDSA { msg = "\xd2\xbc\xb5\x3b\x04\x4b\x3e\x2e\x4b\x61\xba\x2f\x91\xc0\x99\x5f\xb8\x3a\x6a\x97\x52\x5e\x66\x44\x1a\x3b\x48\x9d\x95\x94\x23\x8b\xc7\x40\xbd\xee\xa0\xf7\x18\xa7\x69\xc9\x77\xe2\xde\x00\x38\x77\xb5\xd7\xdc\x25\xb1\x82\xae\x53\x3d\xb3\x3e\x78\xf2\xc3\xff\x06\x45\xf2\x13\x7a\xbc\x13\x7d\x4e\x7d\x93\xcc\xf2\x4f\x60\xb1\x8a\x82\x0b\xc0\x7c\x7b\x4b\x5f\xe0\x8b\x4f\x9e\x7d\x21\xb2\x56\xc1\x8f\x3b\x9d\x49\xac\xc4\xf9\x3e\x2c\xe6\xf3\x75\x4c\x78\x07\x75\x7d\x2e\x11\x76\x04\x26\x12\xcb\x32\xfc\x3f\x4f\x70\x70\x0e\x25" , x = 0xe65131d73470f6ad2e5878bdc9bef536faf78831 , y = 0x29bdd759aaa62d4bf16b4861c81cf42eac2e1637b9ecba512bdbc13ac12a80ae8de2526b899ae5e4a231aef884197c944c732693a634d7659abc6975a773f8d3cd5a361fe2492386a3c09aaef12e4a7e73ad7dfc3637f7b093f2c40d6223a195c136adf2ea3fbf8704a675aa7817aa7ec7f9adfb2854d4e05c3ce7f76560313b , k = 0x87256a64e98cf5be1034ecfa766f9d25d1ac7ceb , r = 0xa26c00b5750a2d27fe7435b93476b35438b4d8ab , s = 0x61c9bfcb2938755afa7dad1d1e07c6288617bf70 , pgq = dsaParams } , VectorDSA { msg = "\xd5\x43\x1e\x6b\x16\xfd\xae\x31\x48\x17\x42\xbd\x39\x47\x58\xbe\xb8\xe2\x4f\x31\x94\x7e\x19\xb7\xea\x7b\x45\x85\x21\x88\x22\x70\xc1\xf4\x31\x92\xaa\x05\x0f\x44\x85\x14\x5a\xf8\xf3\xf9\xc5\x14\x2d\x68\xb8\x50\x18\xd2\xec\x9c\xb7\xa3\x7b\xa1\x2e\xd2\x3e\x73\xb9\x5f\xd6\x80\xfb\xa3\xc6\x12\x65\xe9\xf5\xa0\xa0\x27\xd7\x0f\xad\x0c\x8a\xa0\x8a\x3c\xbf\xbe\x99\x01\x8d\x00\x45\x38\x61\x73\xe5\xfa\xe2\x25\xfa\xeb\xe0\xce\xf5\xdd\x45\x91\x0f\x40\x0a\x86\xc2\xbe\x4e\x15\x25\x2a\x16\xde\x41\x20\xa2\x67\xbe\x2b\x59\x4d" , x = 0x20bcabc6d9347a6e79b8e498c60c44a19c73258c , y = 0x23b4f404aa3c575e550bb320fdb1a085cd396a10e5ebc6771da62f037cab19eacd67d8222b6344038c4f7af45f5e62b55480cbe2111154ca9697ca76d87b56944138084e74c6f90a05cf43660dff8b8b3fabfcab3f0e4416775fdf40055864be102b4587392e77752ed2aeb182ee4f70be4a291dbe77b84a44ee34007957b1e0 , k = 0x7d9bcfc9225432de9860f605a38d389e291ca750 , r = 0x3f0a4ad32f0816821b8affb518e9b599f35d57c2 , s = 0xea06638f2b2fc9d1dfe99c2a492806b497e2b0ea , pgq = dsaParams } , VectorDSA { msg = "\x85\x66\x2b\x69\x75\x50\xe4\x91\x5c\x29\xe3\x38\xb6\x24\xb9\x12\x84\x5d\x6d\x1a\x92\x0d\x9e\x4c\x16\x04\xdd\x47\xd6\x92\xbc\x7c\x0f\xfb\x95\xae\x61\x4e\x85\x2b\xeb\xaf\x15\x73\x75\x8a\xd0\x1c\x71\x3c\xac\x0b\x47\x6e\x2f\x12\x17\x45\xa3\xcf\xee\xff\xb2\x44\x1f\xf6\xab\xfb\x9b\xbe\xb9\x8a\xa6\x34\xca\x6f\xf5\x41\x94\x7d\xcc\x99\x27\x65\x9d\x44\xf9\x5c\x5f\xf9\x17\x0f\xdc\x3c\x86\x47\x3c\xb6\x01\xba\x31\xb4\x87\xfe\x59\x36\xba\xc5\xd9\xc6\x32\xcb\xcc\x3d\xb0\x62\x46\xba\x01\xc5\x5a\x03\x8d\x79\x7f\xe3\xf6\xc3" , x = 0x52d1fbe687aa0702a51a5bf9566bd51bd569424c , y = 0x6bc36cb3fa61cecc157be08639a7ca9e3de073b8a0ff23574ce5ab0a867dfd60669a56e60d1c989b3af8c8a43f5695d503e3098963990e12b63566784171058eace85c728cd4c08224c7a6efea75dca20df461013c75f40acbc23799ebee7f3361336dadc4a56f305708667bfe602b8ea75a491a5cf0c06ebd6fdc7161e10497 , k = 0x960c211891c090d05454646ebac1bfe1f381e82b , r = 0x3bc29dee96957050ba438d1b3e17b02c1725d229 , s = 0x0af879cf846c434e08fb6c63782f4d03e0d88865 , pgq = dsaParams } , VectorDSA { msg = "\x87\xb6\xe7\x5b\x9f\x8e\x99\xc4\xdd\x62\xad\xb6\x93\xdd\x58\x90\xed\xff\x1b\xd0\x02\x8f\x4e\xf8\x49\xdf\x0f\x1d\x2c\xe6\xb1\x81\xfc\x3a\x55\xae\xa6\xd0\xa1\xf0\xae\xca\xb8\xed\x9e\x24\x8a\x00\xe9\x6b\xe7\x94\xa7\xcf\xba\x12\x46\xef\xb7\x10\xef\x4b\x37\x47\x1c\xef\x0a\x1b\xcf\x55\xce\xbc\x8d\x5a\xd0\x71\x61\x2b\xd2\x37\xef\xed\xd5\x10\x23\x62\xdb\x07\xa1\xe2\xc7\xa6\xf1\x5e\x09\xfe\x64\xba\x42\xb6\x0a\x26\x28\xd8\x69\xae\x05\xef\x61\x1f\xe3\x8d\x9c\xe1\x5e\xee\xc9\xbb\x3d\xec\xc8\xdc\x17\x80\x9f\x3b\x6e\x95" , x = 0xc86a54ec5c4ec63d7332cf43ddb082a34ed6d5f5 , y = 0x014ac746d3605efcb8a2c7dae1f54682a262e27662b252c09478ce87d0aaa522d7c200043406016c0c42896d21750b15dbd57f9707ec37dcea5651781b67ad8d01f5099fe7584b353b641bb159cc717d8ceb18b66705e656f336f1214b34f0357e577ab83641969e311bf40bdcb3ffd5e0bb59419f229508d2f432cc2859ff75 , k = 0x6c445cee68042553fbe63be61be4ddb99d8134af , r = 0x637e07a5770f3dc65e4506c68c770e5ef6b8ced3 , s = 0x7dfc6f83e24f09745e01d3f7ae0ed1474e811d47 , pgq = dsaParams } , VectorDSA { msg = "\x22\x59\xee\xad\x2d\x6b\xbc\x76\xd4\x92\x13\xea\x0d\xc8\xb7\x35\x0a\x97\x69\x9f\x22\x34\x10\x44\xc3\x94\x07\x82\x36\x4a\xc9\xea\x68\x31\x79\xa4\x38\xa5\xea\x45\x99\x8d\xf9\x7c\x29\x72\xda\xe0\x38\x51\xf5\xbe\x23\xfa\x9f\x04\x18\x2e\x79\xdd\xb2\xb5\x6d\xc8\x65\x23\x93\xec\xb2\x7f\x3f\x3b\x7c\x8a\x8d\x76\x1a\x86\xb3\xb8\xf4\xd4\x1a\x07\xb4\xbe\x7d\x02\xfd\xde\xfc\x42\xb9\x28\x12\x4a\x5a\x45\xb9\xf4\x60\x90\x42\x20\x9b\x3a\x7f\x58\x5b\xd5\x14\xcc\x39\xc0\x0e\xff\xcc\x42\xc7\xfe\x70\xfa\x83\xed\xf8\xa3\x2b\xf4" , x = 0xaee6f213b9903c8069387e64729a08999e5baf65 , y = 0x0fe74045d7b0d472411202831d4932396f242a9765e92be387fd81bbe38d845054528b348c03984179b8e505674cb79d88cc0d8d3e8d7392f9aa773b29c29e54a9e326406075d755c291fcedbcc577934c824af988250f64ed5685fce726cff65e92d708ae11cbfaa958ab8d8b15340a29a137b5b4357f7ed1c7a5190cbf98a4 , k = 0xe1704bae025942e2e63c6d76bab88da79640073a , r = 0x83366ba3fed93dfb38d541203ecbf81c363998e2 , s = 0x1fe299c36a1332f23bf2e10a6c6a4e0d3cdd2bf4 , pgq = dsaParams } , VectorDSA { msg = "\x21\x9e\x8d\xf5\xbf\x88\x15\x90\x43\x0e\xce\x60\x82\x50\xf7\x67\x0d\xc5\x65\x37\x24\x93\x02\x42\x9e\x28\xec\xfe\xb9\xce\xaa\xa5\x49\x10\xa6\x94\x90\xf7\x65\xf3\xdf\x82\xe8\xb0\x1c\xd7\xd7\x6e\x56\x1d\x0f\x6c\xe2\x26\xef\x3c\xf7\x52\xca\xda\x6f\xeb\xdc\x5b\xf0\x0d\x67\x94\x7f\x92\xd4\x20\x51\x6b\x9e\x37\xc9\x6c\x8f\x1f\x2d\xa0\xb0\x75\x09\x7c\x3b\xda\x75\x8a\x8d\x91\xbd\x2e\xbe\x9c\x75\xcf\x14\x7f\x25\x4c\x25\x69\x63\xb3\x3b\x67\xd0\x2b\x6a\xa0\x9e\x7d\x74\x65\xd0\x38\xe5\x01\x95\xec\xe4\x18\x9b\x41\xe7\x68" , x = 0x699f1c07aa458c6786e770b40197235fe49cf21a , y = 0x3a41b0678ff3c4dde20fa39772bac31a2f18bae4bedec9e12ee8e02e30e556b1a136013bef96b0d30b568233dcecc71e485ed75c922afb4d0654e709bee84993792130220e3005fdb06ebdfc0e2df163b5ec424e836465acd6d92e243c86f2b94b26b8d73bd9cf722c757e0b80b0af16f185de70e8ca850b1402d126ea60f309 , k = 0x5bbb795bfa5fa72191fed3434a08741410367491 , r = 0x579761039ae0ddb81106bf4968e320083bbcb947 , s = 0x503ea15dbac9dedeba917fa8e9f386b93aa30353 , pgq = dsaParams } , VectorDSA { msg = "\x2d\xa7\x9d\x06\x78\x85\xeb\x3c\xcf\x5e\x29\x3a\xe3\xb1\xd8\x22\x53\x22\x20\x3a\xbb\x5a\xdf\xde\x3b\x0f\x53\xbb\xe2\x4c\x4f\xe0\x01\x54\x1e\x11\x83\xd8\x70\xa9\x97\xf1\xf9\x46\x01\x00\xb5\xd7\x11\x92\x31\x80\x15\x43\x45\x28\x7a\x02\x14\xcf\x1c\xac\x37\xb7\xa4\x7d\xfb\xb2\xa0\xe8\xce\x49\x16\xf9\x4e\xbd\x6f\xa5\x4e\x31\x5b\x7a\x8e\xb5\xb6\x3c\xd9\x54\xc5\xba\x05\xc1\xbf\x7e\x33\xa4\xe8\xa1\x51\xf3\x2d\x28\x77\xb0\x17\x29\xc1\xad\x0e\x7c\x01\xbb\x8a\xe7\x23\xc9\x95\x18\x38\x03\xe4\x56\x36\x52\x0e\xa3\x8c\xa1" , x = 0xd6e08c20c82949ddba93ea81eb2fea8c595894dc , y = 0x56f7272210f316c51af8bfc45a421fd4e9b1043853271b7e79f40936f0adcf262a86097aa86e19e6cb5307685d863dba761342db6c973b3849b1e060aca926f41fe07323601062515ae85f3172b8f34899c621d59fa21f73d5ae97a3deb5e840b25a18fd580862fd7b1cf416c7ae9fc5842a0197fdb0c5173ff4a4f102a8cf89 , k = 0x6d72c30d4430959800740f2770651095d0c181c2 , r = 0x5dd90d69add67a5fae138eec1aaff0229aa4afc4 , s = 0x47f39c4db2387f10762f45b80dfd027906d7ef04 , pgq = dsaParams } , VectorDSA { msg = "\xba\x30\xd8\x5b\xe3\x57\xe7\xfb\x29\xf8\xa0\x7e\x1f\x12\x7b\xaa\xa2\x4b\x2e\xe0\x27\xf6\x4c\xb5\xef\xee\xc6\xaa\xea\xbc\xc7\x34\x5c\x5d\x55\x6e\xbf\x4b\xdc\x7a\x61\xc7\x7c\x7b\x7e\xa4\x3c\x73\xba\xbc\x18\xf7\xb4\x80\x77\x22\xda\x23\x9e\x45\xdd\xf2\x49\x84\x9c\xbb\xfe\x35\x07\x11\x2e\xbf\x87\xd7\xef\x56\x0c\x2e\x7d\x39\x1e\xd8\x42\x4f\x87\x10\xce\xa4\x16\x85\x14\x3e\x30\x06\xf8\x1b\x68\xfb\xb4\xd5\xf9\x64\x4c\x7c\xd1\x0f\x70\x92\xef\x24\x39\xb8\xd1\x8c\x0d\xf6\x55\xe0\x02\x89\x37\x2a\x41\x66\x38\x5d\x64\x0c" , x = 0x50018482864c1864e9db1f04bde8dbfd3875c76d , y = 0x0942a5b7a72ab116ead29308cf658dfe3d55d5d61afed9e3836e64237f9d6884fdd827d2d5890c9a41ae88e7a69fc9f345ade9c480c6f08cff067c183214c227236cedb6dd1283ca2a602574e8327510221d4c27b162143b7002d8c726916826265937b87be9d5ec6d7bd28fb015f84e0ab730da7a4eaf4ef3174bf0a22a6392 , k = 0xdf3a9348f37b5d2d4c9176db266ae388f1fa7e0f , r = 0x448434b214eee38bde080f8ec433e8d19b3ddf0d , s = 0x0c02e881b777923fe0ea674f2621298e00199d5f , pgq = dsaParams } , VectorDSA { msg = "\x83\x49\x9e\xfb\x06\xbb\x7f\xf0\x2f\xfb\x46\xc2\x78\xa5\xe9\x26\x30\xac\x5b\xc3\xf9\xe5\x3d\xd2\xe7\x8f\xf1\x5e\x36\x8c\x7e\x31\xaa\xd7\x7c\xf7\x71\xf3\x5f\xa0\x2d\x0b\x5f\x13\x52\x08\xa4\xaf\xdd\x86\x7b\xb2\xec\x26\xea\x2e\x7d\xd6\x4c\xde\xf2\x37\x50\x8a\x38\xb2\x7f\x39\xd8\xb2\x2d\x45\xca\xc5\xa6\x8a\x90\xb6\xea\x76\x05\x86\x45\xf6\x35\x6a\x93\x44\xd3\x6f\x00\xec\x66\x52\xea\xa4\xe9\xba\xe7\xb6\x94\xf9\xf1\xfc\x8c\x6c\x5e\x86\xfa\xdc\x7b\x27\xa2\x19\xb5\xc1\xb2\xae\x80\xa7\x25\xe5\xf6\x11\x65\xfe\x2e\xdc" , x = 0xae56f66b0a9405b9cca54c60ec4a3bb5f8be7c3f , y = 0xa01542c3da410dd57930ca724f0f507c4df43d553c7f69459939685941ceb95c7dcc3f175a403b359621c0d4328e98f15f330a63865baf3e7eb1604a0715e16eed64fd14b35d3a534259a6a7ddf888c4dbb5f51bbc6ed339e5bb2a239d5cfe2100ac8e2f9c16e536f25119ab435843af27dc33414a9e4602f96d7c94d6021cec , k = 0x8857ff301ad0169d164fa269977a116e070bac17 , r = 0x8c2fab489c34672140415d41a65cef1e70192e23 , s = 0x3df86a9e2efe944a1c7ea9c30cac331d00599a0e , pgq = dsaParams } ] where -- (p,g,q) dsaParams = DSA.Params { DSA.params_p = 0xa8f9cd201e5e35d892f85f80e4db2599a5676a3b1d4f190330ed3256b26d0e80a0e49a8fffaaad2a24f472d2573241d4d6d6c7480c80b4c67bb4479c15ada7ea8424d2502fa01472e760241713dab025ae1b02e1703a1435f62ddf4ee4c1b664066eb22f2e3bf28bb70a2a76e4fd5ebe2d1229681b5b06439ac9c7e9d8bde283 , DSA.params_g = 0x2b3152ff6c62f14622b8f48e59f8af46883b38e79b8c74deeae9df131f8b856e3ad6c8455dab87cc0da8ac973417ce4f7878557d6cdf40b35b4a0ca3eb310c6a95d68ce284ad4e25ea28591611ee08b8444bd64b25f3f7c572410ddfb39cc728b9c936f85f419129869929cdb909a6a3a99bbe089216368171bd0ba81de4fe33 , DSA.params_q = 0xf85f0f83ac4df7ea0cdf8f469bfeeaea14156495 } vectorToPrivate :: VectorDSA -> DSA.PrivateKey vectorToPrivate vector = DSA.PrivateKey { DSA.private_x = x vector , DSA.private_params = pgq vector } vectorToPublic :: VectorDSA -> DSA.PublicKey vectorToPublic vector = DSA.PublicKey { DSA.public_y = y vector , DSA.public_params = pgq vector } doSignatureTest (i, vector) = testCase (show i) (expected @=? actual) where expected = Just $ DSA.Signature (r vector) (s vector) actual = DSA.signWith (k vector) (vectorToPrivate vector) SHA1.hash (msg vector) doVerifyTest (i, vector) = testCase (show i) (True @=? actual) where actual = DSA.verify SHA1.hash (vectorToPublic vector) (DSA.Signature (r vector) (s vector)) (msg vector) dsaTests = testGroup "DSA" [ testGroup "SHA1" [ testGroup "signature" $ map doSignatureTest (zip [0..] vectorsSHA1) , testGroup "verify" $ map doVerifyTest (zip [0..] vectorsSHA1) ] ] crypto-pubkey-0.2.8/Tests/KAT/ECC.hs0000644000000000000000000001263712456261417015214 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module KAT.ECC (eccTests, eccKatTests) where import Control.Arrow (second) import Control.Applicative import Data.ByteString (ByteString) import Crypto.Number.Serialize import qualified Crypto.Types.PubKey.ECC as ECC import qualified Crypto.PubKey.ECC.Prim as ECC import Test.Tasty.KAT import Test.Tasty.KAT.FileLoader import Test.Tasty import Test.Tasty.HUnit data VectorPoint = VectorPoint { curve :: ECC.Curve , x :: Integer , y :: Integer , valid :: Bool } vectorsPoint = [ VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x491c0c4761b0a4a147b5e4ce03a531546644f5d1e3d05e57 , y = 0x6fa5addd47c5d6be3933fbff88f57a6c8ca0232c471965de , valid = False -- point not on curve } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x646c22e8aa5f7833390e0399155ac198ae42470bba4fc834 , y = 0x8d4afcfffd80e69a4d180178b37c44572495b7b267ee32a9 , valid = True } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x4c6b9ea0dec92ecfff7799470be6a2277b9169daf45d54bb , y = 0xf0eab42826704f51b26ae98036e83230becb639dd1964627 , valid = False -- point not on curve } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x0673c8bb717b055c3d6f55c06acfcfb7260361ed3ec0f414 , y = 0xba8b172826eb0b854026968d2338a180450a27906f6eddea , valid = True } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x82c949295156192df0b52480e38c810751ac570daec460a3 , y = 0x200057ada615c80b8ff256ce8d47f2562b74a438f1921ac3 , valid = False -- point not on curve } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x284fbaa76ce0faae2ca4867d01092fa1ace5724cd12c8dd0 , y = 0xe42af3dbf3206be3fcbcc3a7ccaf60c73dc29e7bb9b44fca , valid = True } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x1b574acd4fb0f60dde3e3b5f3f0e94211f95112e43cba6fd2 , y = 0xbcc1b8a770f01a22e84d7f14e44932ffe094d8e3b1e6ac26 , valid = False -- x or y out of range } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x16ba109f1f1bb44e0d05b80181c03412ea764a59601d17e9f , y = 0x0569a843dbb4e287db420d6b9fe30cd7b5d578b052315f56 , valid = False -- x or y out of range } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x1333308a7c833ede5189d25ea3525919c9bd16370d904938d , y = 0xb10fd01d67df75ff9b726c700c1b50596c9f0766ea56f80e , valid = False -- x or y out of range } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x9671ec444cff24c8a5be80b018fa505ed6109a731e88c91a , y = 0xfe79dae23008e46bf4230c895aab261a95845a77f06d0655 , valid = True } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0x158e8b6f0b14216bc52fe8897b4305d870ede70436a96741d , y = 0xfb3f970b19a313571a1a23be310923f85acc1cab0a157cbd , valid = False -- x or y out of range } , VectorPoint { curve = ECC.getCurveByName ECC.SEC_p192r1 , x = 0xace95b650c08f73dbb4fa7b4bbdebd6b809a25b28ed135ef , y = 0xe9b8679404166d1329dd539ad52aad9a1b6681f5f26bb9aa , valid = False -- point not on curve } ] doPointValidTest (i, vector) = testCase (show i) (valid vector @=? ECC.isPointValid (curve vector) (ECC.Point (x vector) (y vector))) eccTests = testGroup "ECC" [ testGroup "valid-point" $ map doPointValidTest (zip [0..] vectorsPoint) ] eccKatTests = do res <- testKatLoad "KATs/ECC-PKV.txt" (map (second (map toVector)) . katLoaderSimple) return $ testKatDetailed {-Grouped-} "ECC/valid-point" res (\g vect -> do let c = ECC.getCurveByName <$> case g of "P-192" -> Just ECC.SEC_p192r1 "P-224" -> Just ECC.SEC_p224r1 "P-256" -> Just ECC.SEC_p256r1 "P-384" -> Just ECC.SEC_p384r1 "P-521" -> Just ECC.SEC_p521r1 "B-163" -> Just ECC.SEC_t163r2 "B-233" -> Just ECC.SEC_t233r1 "B-283" -> Just ECC.SEC_t283r1 "B-409" -> Just ECC.SEC_t409r1 "B-571" -> Just ECC.SEC_t571r1 "" -> Nothing _ -> Nothing {- "K-163" -> Just ECC.SEC_t163k1 "K-233" -> Just ECC.SEC_t233k1 "K-283" -> Just ECC.SEC_t283k1 "K-409" -> Just ECC.SEC_t409k1 "K-571" -> Just ECC.SEC_t571k1 -} case c of Nothing -> return True Just curve -> do return (ECC.isPointValid curve (ECC.Point (x vect) (y vect)) == valid vect) ) where toVector kvs = case sequence $ map (flip lookup kvs) [ "Qx", "Qy", "Result" ] of Just [qx,qy,res] -> VectorPoint undefined (valueHexInteger qx) (valueHexInteger qy) (head res /= 'F') Nothing -> error ("ERROR CRAP: " ++ show kvs) -- VectorPoint undefined 0 0 True crypto-pubkey-0.2.8/Tests/KAT/ECDSA.hs0000644000000000000000000001156712456261417015442 0ustar0000000000000000-- Test vectors are taken from GEC2: www.secg.org/collateral/gec2.pdf {-# LANGUAGE OverloadedStrings #-} module KAT.ECDSA (ecdsaTests) where import Data.ByteString (ByteString) import Crypto.Number.Serialize import qualified Crypto.PubKey.ECC.ECDSA as ECDSA import qualified Crypto.Types.PubKey.ECC as ECC import qualified Crypto.Hash.SHA1 as SHA1 import Test.Tasty.HUnit import Test.Tasty data VectorECDSA = VectorECDSA { curve :: ECC.Curve , msg :: ByteString , d :: Integer , q :: ECC.Point , k :: Integer , r :: Integer , s :: Integer } vectorsSHA1 = [ VectorECDSA { curve = ECC.getCurveByName ECC.SEC_p160r1 , msg = "abc" , d = 971761939728640320549601132085879836204587084162 , q = ECC.Point 466448783855397898016055842232266600516272889280 1110706324081757720403272427311003102474457754220 , k = 702232148019446860144825009548118511996283736794 , r = 1176954224688105769566774212902092897866168635793 , s = 299742580584132926933316745664091704165278518100 } -- from official ECDSA KATs , VectorECDSA { curve = ECC.getCurveByName ECC.SEC_t163k1 , msg = i2osp 0xa2c1a03fdd00521bb08fc88d20344321977aaf637ef9d5470dd7d2c8628fc8d0d1f1d3587c6b3fd02386f8c13db341b14748a9475cc63baf065df64054b27d5c2cdf0f98e3bbb81d0b5dc94f8cdb87acf75720f6163de394c8c6af360bc1acb85b923a493b7b27cc111a257e36337bd94eb0fab9d5e633befb1ae7f1b244bfaa , d = 0x00000011f2626d90d26cb4c0379043b26e64107fc , q = ECC.Point 0x0389fa5ad7f8304325a8c060ef7dcb83042c045bc 0x0eefa094a5054da196943cc80509dcb9f59e5bc2e , k = 0x0000000c3a4ff97286126dab1e5089395fcc47ebb , r = 0x0dbe6c3a1dc851e7f2338b5c26c62b4b37bf8035c , s = 0x1c76458135b1ff9fbd23009b8414a47996126b56a } , VectorECDSA { curve = ECC.getCurveByName ECC.SEC_t163k1 , msg = i2osp 0x67048080daaeb77d3ac31babdf8be23dbe75ceb4dfb94aa8113db5c5dcb6fe14b70f717b7b0ed0881835a66a86e6d840ffcb7d976c75ef2d1d4322fbbc86357384e24707aef88cea2c41a01a9a3d1b9e72ce650c7fdecc4f9448d3a77df6cdf13647ab295bb3132de0b1b2c402d8d2de7d452f1e003e0695de1470d1064eee16 , d = 0x00000006a3803301daee9af09bb5b6c991a4f49a4 , q = ECC.Point 0x4b500f555e857da8c299780130c5c3f48f02ee322 0x5c1c0ae25b47f06cc46fb86b12d2d8c0ba6a4bf07 , k = 0x0000002f39fbf77f3e0dc046116de692b6cf91b16 , r = 0x3d3eeda42f65d727f4a564f1415654356c6c57a6c , s = 0x35e4d43c5f08baddf138449db1ad0b7872552b7cd } , VectorECDSA { curve = ECC.getCurveByName ECC.SEC_t163k1 , msg = i2osp 0x77e007dc2acd7248256165a4b30e98986f51a81efd926b85f74c81bc2a6d2bcd030060a844091e22fbb0ff3db5a20caaefb5d58ccdcbc27f0ff8a4d940e78f303079ec1ca5b0ca3d4ecc7580f8b34a9f0496c9e719d2ec3e1614b7644bc11179e895d2c0b58a1da204fbf0f6e509f97f983eacb6487092caf6e8e4e6b3c458b2 , d = 0x0000002e28676514bd93fea11b62db0f6e324b18d , q = ECC.Point 0x3f9c90b71f6a1de20a2716f38ef1b5f98c757bd42 0x2ff0a5d266d447ef62d43fbca6c34c08c1ce35a40 , k = 0x00000001233ae699883e74e7f4dfb5279ff22280a , r = 0x39de3cd2cf04145e522b8fba3f23e9218226e0860 , s = 0x2af62bfb3cfa202e2342606ee5bb0934c3b0375b6 } , VectorECDSA { curve = ECC.getCurveByName ECC.SEC_t163k1 , msg = i2osp 0xfbacfcce4688748406ddf5c3495021eef8fb399865b649eb2395a04a1ab28335da2c236d306fcc59f7b65ea931cf0139571e1538ede5688958c3ac69f47a285362f5ad201f89cc735b7b465408c2c41b310fc8908d0be45054df2a7351fae36b390e842f3b5cdd9ad832940df5b2d25c2ed43ce86eaf2508bcf401ae58bb1d47 , d = 0x000000361dd088e3a6d3c910686c8dce57e5d4d8e , q = ECC.Point 0x064f905c1da9d7e9c32d81890ae6f30dcc7839d32 0x06f1faedb6d9032016d3b681e7cf69c29d29eb27b , k = 0x00000022f723e9f5da56d3d0837d5dca2f937395f , r = 0x374cdc8571083fecfbd4e25e1cd69ecc66b715f2d , s = 0x313b10949222929b2f20b15d446c27d6dcae3f086 } ] vectorToPrivate :: VectorECDSA -> ECDSA.PrivateKey vectorToPrivate vector = ECDSA.PrivateKey (curve vector) (d vector) vectorToPublic :: VectorECDSA -> ECDSA.PublicKey vectorToPublic vector = ECDSA.PublicKey (curve vector) (q vector) doSignatureTest (i, vector) = testCase (show i) (expected @=? actual) where expected = Just $ ECDSA.Signature (r vector) (s vector) actual = ECDSA.signWith (k vector) (vectorToPrivate vector) SHA1.hash (msg vector) doVerifyTest (i, vector) = testCase (show i) (True @=? actual) where actual = ECDSA.verify SHA1.hash (vectorToPublic vector) (ECDSA.Signature (r vector) (s vector)) (msg vector) ecdsaTests = testGroup "ECDSA" [ testGroup "SHA1" [ testGroup "signature" $ map doSignatureTest (zip [0..] vectorsSHA1) , testGroup "verify" $ map doVerifyTest (zip [0..] vectorsSHA1) ] ] crypto-pubkey-0.2.8/Tests/KAT/OAEP.hs0000644000000000000000000002314112456261417015336 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module KAT.OAEP (oaepTests) where import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import Crypto.PubKey.RSA import Crypto.PubKey.MaskGenFunction import qualified Crypto.PubKey.RSA.OAEP as OAEP import qualified Crypto.Hash.SHA1 as SHA1 import Test.Tasty import Test.Tasty.HUnit rsaKeyInt = PrivateKey { private_pub = PublicKey { public_n = 0xbbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb , public_e = 0x11 , public_size = 128 } , private_d = 0xa5dafc5341faf289c4b988db30c1cdf83f31251e0668b42784813801579641b29410b3c7998d6bc465745e5c392669d6870da2c082a939e37fdcb82ec93edac97ff3ad5950accfbc111c76f1a9529444e56aaf68c56c092cd38dc3bef5d20a939926ed4f74a13eddfbe1a1cecc4894af9428c2b7b8883fe4463a4bc85b1cb3c1 , private_p = 0xeecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599 , private_q = 0xc97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503 , private_dP = 0x54494ca63eba0337e4e24023fcd69a5aeb07dddc0183a4d0ac9b54b051f2b13ed9490975eab77414ff59c1f7692e9a2e202b38fc910a474174adc93c1f67c981 , private_dQ = 0x471e0290ff0af0750351b7f878864ca961adbd3a8a7e991c5c0556a94c3146a7f9803f8f6f8ae342e931fd8ae47a220d1b99a495849807fe39f9245a9836da3d , private_qinv = 0xb06c4fdabb6301198d265bdbae9423b380f271f73453885093077fcd39e2119fc98632154f5883b167a967bf402b4e9e2e0f9656e698ea3666edfb25798039f7 } rsaKey1 = PrivateKey { private_pub = PublicKey { public_n = 0xa8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb , public_e = 0x010001 , public_size = 128 } , private_d = 0x53339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1 , private_p = 0xd32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d , private_q = 0xcc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d77 , private_dP = 0x0e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c1 , private_dQ = 0x95297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d71583 , private_qinv = 0x4f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1 } data VectorOAEP = VectorOAEP { seed :: ByteString , message :: ByteString , cipherText :: ByteString } vectorInt = VectorOAEP { message = "\xd4\x36\xe9\x95\x69\xfd\x32\xa7\xc8\xa0\x5b\xbc\x90\xd3\x2c\x49" , seed = "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f" , cipherText = "\x12\x53\xe0\x4d\xc0\xa5\x39\x7b\xb4\x4a\x7a\xb8\x7e\x9b\xf2\xa0\x39\xa3\x3d\x1e\x99\x6f\xc8\x2a\x94\xcc\xd3\x00\x74\xc9\x5d\xf7\x63\x72\x20\x17\x06\x9e\x52\x68\xda\x5d\x1c\x0b\x4f\x87\x2c\xf6\x53\xc1\x1d\xf8\x23\x14\xa6\x79\x68\xdf\xea\xe2\x8d\xef\x04\xbb\x6d\x84\xb1\xc3\x1d\x65\x4a\x19\x70\xe5\x78\x3b\xd6\xeb\x96\xa0\x24\xc2\xca\x2f\x4a\x90\xfe\x9f\x2e\xf5\xc9\xc1\x40\xe5\xbb\x48\xda\x95\x36\xad\x87\x00\xc8\x4f\xc9\x13\x0a\xde\xa7\x4e\x55\x8d\x51\xa7\x4d\xdf\x85\xd8\xb5\x0d\xe9\x68\x38\xd6\x06\x3e\x09\x55" } vectorsKey1 = [ VectorOAEP -- 1.1 { message = "\x66\x28\x19\x4e\x12\x07\x3d\xb0\x3b\xa9\x4c\xda\x9e\xf9\x53\x23\x97\xd5\x0d\xba\x79\xb9\x87\x00\x4a\xfe\xfe\x34" , seed = "\x18\xb7\x76\xea\x21\x06\x9d\x69\x77\x6a\x33\xe9\x6b\xad\x48\xe1\xdd\xa0\xa5\xef" , cipherText = "\x35\x4f\xe6\x7b\x4a\x12\x6d\x5d\x35\xfe\x36\xc7\x77\x79\x1a\x3f\x7b\xa1\x3d\xef\x48\x4e\x2d\x39\x08\xaf\xf7\x22\xfa\xd4\x68\xfb\x21\x69\x6d\xe9\x5d\x0b\xe9\x11\xc2\xd3\x17\x4f\x8a\xfc\xc2\x01\x03\x5f\x7b\x6d\x8e\x69\x40\x2d\xe5\x45\x16\x18\xc2\x1a\x53\x5f\xa9\xd7\xbf\xc5\xb8\xdd\x9f\xc2\x43\xf8\xcf\x92\x7d\xb3\x13\x22\xd6\xe8\x81\xea\xa9\x1a\x99\x61\x70\xe6\x57\xa0\x5a\x26\x64\x26\xd9\x8c\x88\x00\x3f\x84\x77\xc1\x22\x70\x94\xa0\xd9\xfa\x1e\x8c\x40\x24\x30\x9c\xe1\xec\xcc\xb5\x21\x00\x35\xd4\x7a\xc7\x2e\x8a" } , VectorOAEP -- 1.2 { message = "\x75\x0c\x40\x47\xf5\x47\xe8\xe4\x14\x11\x85\x65\x23\x29\x8a\xc9\xba\xe2\x45\xef\xaf\x13\x97\xfb\xe5\x6f\x9d\xd5" , seed = "\x0c\xc7\x42\xce\x4a\x9b\x7f\x32\xf9\x51\xbc\xb2\x51\xef\xd9\x25\xfe\x4f\xe3\x5f" , cipherText = "\x64\x0d\xb1\xac\xc5\x8e\x05\x68\xfe\x54\x07\xe5\xf9\xb7\x01\xdf\xf8\xc3\xc9\x1e\x71\x6c\x53\x6f\xc7\xfc\xec\x6c\xb5\xb7\x1c\x11\x65\x98\x8d\x4a\x27\x9e\x15\x77\xd7\x30\xfc\x7a\x29\x93\x2e\x3f\x00\xc8\x15\x15\x23\x6d\x8d\x8e\x31\x01\x7a\x7a\x09\xdf\x43\x52\xd9\x04\xcd\xeb\x79\xaa\x58\x3a\xdc\xc3\x1e\xa6\x98\xa4\xc0\x52\x83\xda\xba\x90\x89\xbe\x54\x91\xf6\x7c\x1a\x4e\xe4\x8d\xc7\x4b\xbb\xe6\x64\x3a\xef\x84\x66\x79\xb4\xcb\x39\x5a\x35\x2d\x5e\xd1\x15\x91\x2d\xf6\x96\xff\xe0\x70\x29\x32\x94\x6d\x71\x49\x2b\x44" } , VectorOAEP -- 1.3 { message = "\xd9\x4a\xe0\x83\x2e\x64\x45\xce\x42\x33\x1c\xb0\x6d\x53\x1a\x82\xb1\xdb\x4b\xaa\xd3\x0f\x74\x6d\xc9\x16\xdf\x24\xd4\xe3\xc2\x45\x1f\xff\x59\xa6\x42\x3e\xb0\xe1\xd0\x2d\x4f\xe6\x46\xcf\x69\x9d\xfd\x81\x8c\x6e\x97\xb0\x51" , seed = "\x25\x14\xdf\x46\x95\x75\x5a\x67\xb2\x88\xea\xf4\x90\x5c\x36\xee\xc6\x6f\xd2\xfd" , cipherText = "\x42\x37\x36\xed\x03\x5f\x60\x26\xaf\x27\x6c\x35\xc0\xb3\x74\x1b\x36\x5e\x5f\x76\xca\x09\x1b\x4e\x8c\x29\xe2\xf0\xbe\xfe\xe6\x03\x59\x5a\xa8\x32\x2d\x60\x2d\x2e\x62\x5e\x95\xeb\x81\xb2\xf1\xc9\x72\x4e\x82\x2e\xca\x76\xdb\x86\x18\xcf\x09\xc5\x34\x35\x03\xa4\x36\x08\x35\xb5\x90\x3b\xc6\x37\xe3\x87\x9f\xb0\x5e\x0e\xf3\x26\x85\xd5\xae\xc5\x06\x7c\xd7\xcc\x96\xfe\x4b\x26\x70\xb6\xea\xc3\x06\x6b\x1f\xcf\x56\x86\xb6\x85\x89\xaa\xfb\x7d\x62\x9b\x02\xd8\xf8\x62\x5c\xa3\x83\x36\x24\xd4\x80\x0f\xb0\x81\xb1\xcf\x94\xeb" } , VectorOAEP { message = "\x52\xe6\x50\xd9\x8e\x7f\x2a\x04\x8b\x4f\x86\x85\x21\x53\xb9\x7e\x01\xdd\x31\x6f\x34\x6a\x19\xf6\x7a\x85" , seed = "\xc4\x43\x5a\x3e\x1a\x18\xa6\x8b\x68\x20\x43\x62\x90\xa3\x7c\xef\xb8\x5d\xb3\xfb" , cipherText = "\x45\xea\xd4\xca\x55\x1e\x66\x2c\x98\x00\xf1\xac\xa8\x28\x3b\x05\x25\xe6\xab\xae\x30\xbe\x4b\x4a\xba\x76\x2f\xa4\x0f\xd3\xd3\x8e\x22\xab\xef\xc6\x97\x94\xf6\xeb\xbb\xc0\x5d\xdb\xb1\x12\x16\x24\x7d\x2f\x41\x2f\xd0\xfb\xa8\x7c\x6e\x3a\xcd\x88\x88\x13\x64\x6f\xd0\xe4\x8e\x78\x52\x04\xf9\xc3\xf7\x3d\x6d\x82\x39\x56\x27\x22\xdd\xdd\x87\x71\xfe\xc4\x8b\x83\xa3\x1e\xe6\xf5\x92\xc4\xcf\xd4\xbc\x88\x17\x4f\x3b\x13\xa1\x12\xaa\xe3\xb9\xf7\xb8\x0e\x0f\xc6\xf7\x25\x5b\xa8\x80\xdc\x7d\x80\x21\xe2\x2a\xd6\xa8\x5f\x07\x55" } , VectorOAEP { message = "\x8d\xa8\x9f\xd9\xe5\xf9\x74\xa2\x9f\xef\xfb\x46\x2b\x49\x18\x0f\x6c\xf9\xe8\x02" , seed = "\xb3\x18\xc4\x2d\xf3\xbe\x0f\x83\xfe\xa8\x23\xf5\xa7\xb4\x7e\xd5\xe4\x25\xa3\xb5" , cipherText = "\x36\xf6\xe3\x4d\x94\xa8\xd3\x4d\xaa\xcb\xa3\x3a\x21\x39\xd0\x0a\xd8\x5a\x93\x45\xa8\x60\x51\xe7\x30\x71\x62\x00\x56\xb9\x20\xe2\x19\x00\x58\x55\xa2\x13\xa0\xf2\x38\x97\xcd\xcd\x73\x1b\x45\x25\x7c\x77\x7f\xe9\x08\x20\x2b\xef\xdd\x0b\x58\x38\x6b\x12\x44\xea\x0c\xf5\x39\xa0\x5d\x5d\x10\x32\x9d\xa4\x4e\x13\x03\x0f\xd7\x60\xdc\xd6\x44\xcf\xef\x20\x94\xd1\x91\x0d\x3f\x43\x3e\x1c\x7c\x6d\xd1\x8b\xc1\xf2\xdf\x7f\x64\x3d\x66\x2f\xb9\xdd\x37\xea\xd9\x05\x91\x90\xf4\xfa\x66\xca\x39\xe8\x69\xc4\xeb\x44\x9c\xbd\xc4\x39" } , VectorOAEP -- 1.6 { message = "\x26\x52\x10\x50\x84\x42\x71" , seed = "\xe4\xec\x09\x82\xc2\x33\x6f\x3a\x67\x7f\x6a\x35\x61\x74\xeb\x0c\xe8\x87\xab\xc2" , cipherText = "\x42\xce\xe2\x61\x7b\x1e\xce\xa4\xdb\x3f\x48\x29\x38\x6f\xbd\x61\xda\xfb\xf0\x38\xe1\x80\xd8\x37\xc9\x63\x66\xdf\x24\xc0\x97\xb4\xab\x0f\xac\x6b\xdf\x59\x0d\x82\x1c\x9f\x10\x64\x2e\x68\x1a\xd0\x5b\x8d\x78\xb3\x78\xc0\xf4\x6c\xe2\xfa\xd6\x3f\x74\xe0\xad\x3d\xf0\x6b\x07\x5d\x7e\xb5\xf5\x63\x6f\x8d\x40\x3b\x90\x59\xca\x76\x1b\x5c\x62\xbb\x52\xaa\x45\x00\x2e\xa7\x0b\xaa\xce\x08\xde\xd2\x43\xb9\xd8\xcb\xd6\x2a\x68\xad\xe2\x65\x83\x2b\x56\x56\x4e\x43\xa6\xfa\x42\xed\x19\x9a\x09\x97\x69\x74\x2d\xf1\x53\x9e\x82\x55" } ] doEncryptionTest key (i, vector) = testCase (show i) (Right (cipherText vector) @=? actual) where actual = OAEP.encryptWithSeed (seed vector) (OAEP.defaultOAEPParams SHA1.hash) key (message vector) doDecryptionTest key (i, vector) = testCase (show i) (Right (message vector) @=? actual) where actual = OAEP.decrypt Nothing (OAEP.defaultOAEPParams SHA1.hash) key (cipherText vector) oaepTests = testGroup "RSA-OAEP" [ testGroup "internal" [ doEncryptionTest (private_pub rsaKeyInt) (0, vectorInt) , doDecryptionTest rsaKeyInt (0, vectorInt) ] , testGroup "encryption key 1024 bits" $ map (doEncryptionTest $ private_pub rsaKey1) (zip [0..] vectorsKey1) , testGroup "decryption key 1024 bits" $ map (doDecryptionTest rsaKey1) (zip [0..] vectorsKey1) ] crypto-pubkey-0.2.8/Tests/KAT/PSS.hs0000644000000000000000000006443512456261417015272 0ustar0000000000000000{-# LANGUAGE OverloadedStrings #-} module KAT.PSS (pssTests) where import Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import Crypto.PubKey.RSA import Crypto.PubKey.MaskGenFunction import qualified Crypto.PubKey.RSA.PSS as PSS import qualified Crypto.Hash.SHA1 as SHA1 import Test.Tasty import Test.Tasty.HUnit data VectorPSS = VectorPSS { message :: ByteString , salt :: ByteString , signature :: ByteString } rsaKeyInt = PrivateKey { private_pub = PublicKey { public_n = 0xa2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5 , public_e = 0x010001 , public_size = 128 } , private_d = 0x50e2c3e38d886110288dfc68a9533e7e12e27d2aa56d2cdb3fb6efa990bcff29e1d2987fb711962860e7391b1ce01ebadb9e812d2fbdfaf25df4ae26110a6d7a26f0b810f54875e17dd5c9fb6d641761245b81e79f8c88f0e55a6dcd5f133abd35f8f4ec80adf1bf86277a582894cb6ebcd2162f1c7534f1f4947b129151b71 , private_p = 0xd17f655bf27c8b16d35462c905cc04a26f37e2a67fa9c0ce0dced472394a0df743fe7f929e378efdb368eddff453cf007af6d948e0ade757371f8a711e278f6b , private_q = 0xc6d92b6fee7414d1358ce1546fb62987530b90bd15e0f14963a5e2635adb69347ec0c01b2ab1763fd8ac1a592fb22757463a982425bb97a3a437c5bf86d03f2f , private_dP = 0x9d0dbf83e5ce9e4b1754dcd5cd05bcb7b55f1508330ea49f14d4e889550f8256cb5f806dff34b17ada44208853577d08e4262890acf752461cea05547601bc4f , private_dQ = 0x1291a524c6b7c059e90e46dc83b2171eb3fa98818fd179b6c8bf6cecaa476303abf283fe05769cfc495788fe5b1ddfde9e884a3cd5e936b7e955ebf97eb563b1 , private_qinv = 0xa63f1da38b950c9ad1c67ce0d677ec2914cd7d40062df42a67eb198a176f9742aac7c5fea14f2297662b84812c4defc49a8025ab4382286be4c03788dd01d69f } rsaKey1 = PrivateKey { private_pub = PublicKey { public_n = 0xa56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137 , public_e = 0x010001 , public_size = 128 } , private_d = 0x33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325 , private_p = 0xe7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443 , private_q = 0xb69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd , private_dP = 0x28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979 , private_dQ = 0x1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729 , private_qinv = 0x27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d } vectorInt = VectorPSS { message = "\x85\x9e\xef\x2f\xd7\x8a\xca\x00\x30\x8b\xdc\x47\x11\x93\xbf\x55\xbf\x9d\x78\xdb\x8f\x8a\x67\x2b\x48\x46\x34\xf3\xc9\xc2\x6e\x64\x78\xae\x10\x26\x0f\xe0\xdd\x8c\x08\x2e\x53\xa5\x29\x3a\xf2\x17\x3c\xd5\x0c\x6d\x5d\x35\x4f\xeb\xf7\x8b\x26\x02\x1c\x25\xc0\x27\x12\xe7\x8c\xd4\x69\x4c\x9f\x46\x97\x77\xe4\x51\xe7\xf8\xe9\xe0\x4c\xd3\x73\x9c\x6b\xbf\xed\xae\x48\x7f\xb5\x56\x44\xe9\xca\x74\xff\x77\xa5\x3c\xb7\x29\x80\x2f\x6e\xd4\xa5\xff\xa8\xba\x15\x98\x90\xfc" , salt = "\xe3\xb5\xd5\xd0\x02\xc1\xbc\xe5\x0c\x2b\x65\xef\x88\xa1\x88\xd8\x3b\xce\x7e\x61" , signature = "\x8d\xaa\x62\x7d\x3d\xe7\x59\x5d\x63\x05\x6c\x7e\xc6\x59\xe5\x44\x06\xf1\x06\x10\x12\x8b\xaa\xe8\x21\xc8\xb2\xa0\xf3\x93\x6d\x54\xdc\x3b\xdc\xe4\x66\x89\xf6\xb7\x95\x1b\xb1\x8e\x84\x05\x42\x76\x97\x18\xd5\x71\x5d\x21\x0d\x85\xef\xbb\x59\x61\x92\x03\x2c\x42\xbe\x4c\x29\x97\x2c\x85\x62\x75\xeb\x6d\x5a\x45\xf0\x5f\x51\x87\x6f\xc6\x74\x3d\xed\xdd\x28\xca\xec\x9b\xb3\x0e\xa9\x9e\x02\xc3\x48\x82\x69\x60\x4f\xe4\x97\xf7\x4c\xcd\x7c\x7f\xca\x16\x71\x89\x71\x23\xcb\xd3\x0d\xef\x5d\x54\xa2\xb5\x53\x6a\xd9\x0a\x74\x7e" } {- # mHash = Hash(M) # salt = random string of octets # M' = Padding || mHash || salt # H = Hash(M') # DB = Padding || salt # dbMask = MGF(H, length(DB)) # maskedDB = DB xor dbMask (leftmost bit set to # zero) # EM = maskedDB || H || 0xbc # mHash: 37 b6 6a e0 44 58 43 35 3d 47 ec b0 b4 fd 14 c1 10 e6 2d 6a # salt: # M': 00 00 00 00 00 00 00 00 37 b6 6a e0 44 58 43 35 3d 47 ec b0 b4 fd 14 c1 10 e6 2d 6a e3 b5 d5 d0 02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8 3b ce 7e 61 # H: df 1a 89 6f 9d 8b c8 16 d9 7c d7 a2 c4 3b ad 54 6f be 8c fe # DB: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 e3 b5 d5 d0 02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8 3b ce 7e 61 # dbMask: 66 e4 67 2e 83 6a d1 21 ba 24 4b ed 65 76 b8 67 d9 a4 47 c2 8a 6e 66 a5 b8 7d ee 7f bc 7e 65 af 50 57 f8 6f ae 89 84 d9 ba 7f 96 9a d6 fe 02 a4 d7 5f 74 45 fe fd d8 5b 6d 3a 47 7c 28 d2 4b a1 e3 75 6f 79 2d d1 dc e8 ca 94 44 0e cb 52 79 ec d3 18 3a 31 1f c8 97 39 a9 66 43 13 6e 8b 0f 46 5e 87 a4 53 5c d4 c5 9b 10 02 8d # maskedDB: 66 e4 67 2e 83 6a d1 21 ba 24 4b ed 65 76 b8 67 d9 a4 47 c2 8a 6e 66 a5 b8 7d ee 7f bc 7e 65 af 50 57 f8 6f ae 89 84 d9 ba 7f 96 9a d6 fe 02 a4 d7 5f 74 45 fe fd d8 5b 6d 3a 47 7c 28 d2 4b a1 e3 75 6f 79 2d d1 dc e8 ca 94 44 0e cb 52 79 ec d3 18 3a 31 1f c8 96 da 1c b3 93 11 af 37 ea 4a 75 e2 4b db fd 5c 1d a0 de 7c ec # Encoded message EM: 66 e4 67 2e 83 6a d1 21 ba 24 4b ed 65 76 b8 67 d9 a4 47 c2 8a 6e 66 a5 b8 7d ee 7f bc 7e 65 af 50 57 f8 6f ae 89 84 d9 ba 7f 96 9a d6 fe 02 a4 d7 5f 74 45 fe fd d8 5b 6d 3a 47 7c 28 d2 4b a1 e3 75 6f 79 2d d1 dc e8 ca 94 44 0e cb 52 79 ec d3 18 3a 31 1f c8 96 da 1c b3 93 11 af 37 ea 4a 75 e2 4b db fd 5c 1d a0 de 7c ec df 1a 89 6f 9d 8b c8 16 d9 7c d7 a2 c4 3b ad 54 6f be 8c fe bc -} vectorsKey1 = [ -- Example 1.1 VectorPSS { message = "\xcd\xc8\x7d\xa2\x23\xd7\x86\xdf\x3b\x45\xe0\xbb\xbc\x72\x13\x26\xd1\xee\x2a\xf8\x06\xcc\x31\x54\x75\xcc\x6f\x0d\x9c\x66\xe1\xb6\x23\x71\xd4\x5c\xe2\x39\x2e\x1a\xc9\x28\x44\xc3\x10\x10\x2f\x15\x6a\x0d\x8d\x52\xc1\xf4\xc4\x0b\xa3\xaa\x65\x09\x57\x86\xcb\x76\x97\x57\xa6\x56\x3b\xa9\x58\xfe\xd0\xbc\xc9\x84\xe8\xb5\x17\xa3\xd5\xf5\x15\xb2\x3b\x8a\x41\xe7\x4a\xa8\x67\x69\x3f\x90\xdf\xb0\x61\xa6\xe8\x6d\xfa\xae\xe6\x44\x72\xc0\x0e\x5f\x20\x94\x57\x29\xcb\xeb\xe7\x7f\x06\xce\x78\xe0\x8f\x40\x98\xfb\xa4\x1f\x9d\x61\x93\xc0\x31\x7e\x8b\x60\xd4\xb6\x08\x4a\xcb\x42\xd2\x9e\x38\x08\xa3\xbc\x37\x2d\x85\xe3\x31\x17\x0f\xcb\xf7\xcc\x72\xd0\xb7\x1c\x29\x66\x48\xb3\xa4\xd1\x0f\x41\x62\x95\xd0\x80\x7a\xa6\x25\xca\xb2\x74\x4f\xd9\xea\x8f\xd2\x23\xc4\x25\x37\x02\x98\x28\xbd\x16\xbe\x02\x54\x6f\x13\x0f\xd2\xe3\x3b\x93\x6d\x26\x76\xe0\x8a\xed\x1b\x73\x31\x8b\x75\x0a\x01\x67\xd0" , salt = "\xde\xe9\x59\xc7\xe0\x64\x11\x36\x14\x20\xff\x80\x18\x5e\xd5\x7f\x3e\x67\x76\xaf" , signature = "\x90\x74\x30\x8f\xb5\x98\xe9\x70\x1b\x22\x94\x38\x8e\x52\xf9\x71\xfa\xac\x2b\x60\xa5\x14\x5a\xf1\x85\xdf\x52\x87\xb5\xed\x28\x87\xe5\x7c\xe7\xfd\x44\xdc\x86\x34\xe4\x07\xc8\xe0\xe4\x36\x0b\xc2\x26\xf3\xec\x22\x7f\x9d\x9e\x54\x63\x8e\x8d\x31\xf5\x05\x12\x15\xdf\x6e\xbb\x9c\x2f\x95\x79\xaa\x77\x59\x8a\x38\xf9\x14\xb5\xb9\xc1\xbd\x83\xc4\xe2\xf9\xf3\x82\xa0\xd0\xaa\x35\x42\xff\xee\x65\x98\x4a\x60\x1b\xc6\x9e\xb2\x8d\xeb\x27\xdc\xa1\x2c\x82\xc2\xd4\xc3\xf6\x6c\xd5\x00\xf1\xff\x2b\x99\x4d\x8a\x4e\x30\xcb\xb3\x3c" } -- Example 1.2 , VectorPSS { message = "\x85\x13\x84\xcd\xfe\x81\x9c\x22\xed\x6c\x4c\xcb\x30\xda\xeb\x5c\xf0\x59\xbc\x8e\x11\x66\xb7\xe3\x53\x0c\x4c\x23\x3e\x2b\x5f\x8f\x71\xa1\xcc\xa5\x82\xd4\x3e\xcc\x72\xb1\xbc\xa1\x6d\xfc\x70\x13\x22\x6b\x9e" , salt = "\xef\x28\x69\xfa\x40\xc3\x46\xcb\x18\x3d\xab\x3d\x7b\xff\xc9\x8f\xd5\x6d\xf4\x2d" , signature = "\x3e\xf7\xf4\x6e\x83\x1b\xf9\x2b\x32\x27\x41\x42\xa5\x85\xff\xce\xfb\xdc\xa7\xb3\x2a\xe9\x0d\x10\xfb\x0f\x0c\x72\x99\x84\xf0\x4e\xf2\x9a\x9d\xf0\x78\x07\x75\xce\x43\x73\x9b\x97\x83\x83\x90\xdb\x0a\x55\x05\xe6\x3d\xe9\x27\x02\x8d\x9d\x29\xb2\x19\xca\x2c\x45\x17\x83\x25\x58\xa5\x5d\x69\x4a\x6d\x25\xb9\xda\xb6\x60\x03\xc4\xcc\xcd\x90\x78\x02\x19\x3b\xe5\x17\x0d\x26\x14\x7d\x37\xb9\x35\x90\x24\x1b\xe5\x1c\x25\x05\x5f\x47\xef\x62\x75\x2c\xfb\xe2\x14\x18\xfa\xfe\x98\xc2\x2c\x4d\x4d\x47\x72\x4f\xdb\x56\x69\xe8\x43" } -- Example 1.3 , VectorPSS { message = "\xa4\xb1\x59\x94\x17\x61\xc4\x0c\x6a\x82\xf2\xb8\x0d\x1b\x94\xf5\xaa\x26\x54\xfd\x17\xe1\x2d\x58\x88\x64\x67\x9b\x54\xcd\x04\xef\x8b\xd0\x30\x12\xbe\x8d\xc3\x7f\x4b\x83\xaf\x79\x63\xfa\xff\x0d\xfa\x22\x54\x77\x43\x7c\x48\x01\x7f\xf2\xbe\x81\x91\xcf\x39\x55\xfc\x07\x35\x6e\xab\x3f\x32\x2f\x7f\x62\x0e\x21\xd2\x54\xe5\xdb\x43\x24\x27\x9f\xe0\x67\xe0\x91\x0e\x2e\x81\xca\x2c\xab\x31\xc7\x45\xe6\x7a\x54\x05\x8e\xb5\x0d\x99\x3c\xdb\x9e\xd0\xb4\xd0\x29\xc0\x6d\x21\xa9\x4c\xa6\x61\xc3\xce\x27\xfa\xe1\xd6\xcb\x20\xf4\x56\x4d\x66\xce\x47\x67\x58\x3d\x0e\x5f\x06\x02\x15\xb5\x90\x17\xbe\x85\xea\x84\x89\x39\x12\x7b\xd8\xc9\xc4\xd4\x7b\x51\x05\x6c\x03\x1c\xf3\x36\xf1\x7c\x99\x80\xf3\xb8\xf5\xb9\xb6\x87\x8e\x8b\x79\x7a\xa4\x3b\x88\x26\x84\x33\x3e\x17\x89\x3f\xe9\xca\xa6\xaa\x29\x9f\x7e\xd1\xa1\x8e\xe2\xc5\x48\x64\xb7\xb2\xb9\x9b\x72\x61\x8f\xb0\x25\x74\xd1\x39\xef\x50\xf0\x19\xc9\xee\xf4\x16\x97\x13\x38\xe7\xd4\x70" , salt = "\x71\x0b\x9c\x47\x47\xd8\x00\xd4\xde\x87\xf1\x2a\xfd\xce\x6d\xf1\x81\x07\xcc\x77" , signature = "\x66\x60\x26\xfb\xa7\x1b\xd3\xe7\xcf\x13\x15\x7c\xc2\xc5\x1a\x8e\x4a\xa6\x84\xaf\x97\x78\xf9\x18\x49\xf3\x43\x35\xd1\x41\xc0\x01\x54\xc4\x19\x76\x21\xf9\x62\x4a\x67\x5b\x5a\xbc\x22\xee\x7d\x5b\xaa\xff\xaa\xe1\xc9\xba\xca\x2c\xc3\x73\xb3\xf3\x3e\x78\xe6\x14\x3c\x39\x5a\x91\xaa\x7f\xac\xa6\x64\xeb\x73\x3a\xfd\x14\xd8\x82\x72\x59\xd9\x9a\x75\x50\xfa\xca\x50\x1e\xf2\xb0\x4e\x33\xc2\x3a\xa5\x1f\x4b\x9e\x82\x82\xef\xdb\x72\x8c\xc0\xab\x09\x40\x5a\x91\x60\x7c\x63\x69\x96\x1b\xc8\x27\x0d\x2d\x4f\x39\xfc\xe6\x12\xb1" } -- Example 1.4 , VectorPSS { message = "\xbc\x65\x67\x47\xfa\x9e\xaf\xb3\xf0" , salt = "\x05\x6f\x00\x98\x5d\xe1\x4d\x8e\xf5\xce\xa9\xe8\x2f\x8c\x27\xbe\xf7\x20\x33\x5e" , signature = "\x46\x09\x79\x3b\x23\xe9\xd0\x93\x62\xdc\x21\xbb\x47\xda\x0b\x4f\x3a\x76\x22\x64\x9a\x47\xd4\x64\x01\x9b\x9a\xea\xfe\x53\x35\x9c\x17\x8c\x91\xcd\x58\xba\x6b\xcb\x78\xbe\x03\x46\xa7\xbc\x63\x7f\x4b\x87\x3d\x4b\xab\x38\xee\x66\x1f\x19\x96\x34\xc5\x47\xa1\xad\x84\x42\xe0\x3d\xa0\x15\xb1\x36\xe5\x43\xf7\xab\x07\xc0\xc1\x3e\x42\x25\xb8\xde\x8c\xce\x25\xd4\xf6\xeb\x84\x00\xf8\x1f\x7e\x18\x33\xb7\xee\x6e\x33\x4d\x37\x09\x64\xca\x79\xfd\xb8\x72\xb4\xd7\x52\x23\xb5\xee\xb0\x81\x01\x59\x1f\xb5\x32\xd1\x55\xa6\xde\x87" } -- Example 1.5 , VectorPSS { message = "\xb4\x55\x81\x54\x7e\x54\x27\x77\x0c\x76\x8e\x8b\x82\xb7\x55\x64\xe0\xea\x4e\x9c\x32\x59\x4d\x6b\xff\x70\x65\x44\xde\x0a\x87\x76\xc7\xa8\x0b\x45\x76\x55\x0e\xee\x1b\x2a\xca\xbc\x7e\x8b\x7d\x3e\xf7\xbb\x5b\x03\xe4\x62\xc1\x10\x47\xea\xdd\x00\x62\x9a\xe5\x75\x48\x0a\xc1\x47\x0f\xe0\x46\xf1\x3a\x2b\xf5\xaf\x17\x92\x1d\xc4\xb0\xaa\x8b\x02\xbe\xe6\x33\x49\x11\x65\x1d\x7f\x85\x25\xd1\x0f\x32\xb5\x1d\x33\xbe\x52\x0d\x3d\xdf\x5a\x70\x99\x55\xa3\xdf\xe7\x82\x83\xb9\xe0\xab\x54\x04\x6d\x15\x0c\x17\x7f\x03\x7f\xdc\xcc\x5b\xe4\xea\x5f\x68\xb5\xe5\xa3\x8c\x9d\x7e\xdc\xcc\xc4\x97\x5f\x45\x5a\x69\x09\xb4" , salt = "\x80\xe7\x0f\xf8\x6a\x08\xde\x3e\xc6\x09\x72\xb3\x9b\x4f\xbf\xdc\xea\x67\xae\x8e" , signature = "\x1d\x2a\xad\x22\x1c\xa4\xd3\x1d\xdf\x13\x50\x92\x39\x01\x93\x98\xe3\xd1\x4b\x32\xdc\x34\xdc\x5a\xf4\xae\xae\xa3\xc0\x95\xaf\x73\x47\x9c\xf0\xa4\x5e\x56\x29\x63\x5a\x53\xa0\x18\x37\x76\x15\xb1\x6c\xb9\xb1\x3b\x3e\x09\xd6\x71\xeb\x71\xe3\x87\xb8\x54\x5c\x59\x60\xda\x5a\x64\x77\x6e\x76\x8e\x82\xb2\xc9\x35\x83\xbf\x10\x4c\x3f\xdb\x23\x51\x2b\x7b\x4e\x89\xf6\x33\xdd\x00\x63\xa5\x30\xdb\x45\x24\xb0\x1c\x3f\x38\x4c\x09\x31\x0e\x31\x5a\x79\xdc\xd3\xd6\x84\x02\x2a\x7f\x31\xc8\x65\xa6\x64\xe3\x16\x97\x8b\x75\x9f\xad" } -- Example 1.6 , VectorPSS { message = "\x10\xaa\xe9\xa0\xab\x0b\x59\x5d\x08\x41\x20\x7b\x70\x0d\x48\xd7\x5f\xae\xdd\xe3\xb7\x75\xcd\x6b\x4c\xc8\x8a\xe0\x6e\x46\x94\xec\x74\xba\x18\xf8\x52\x0d\x4f\x5e\xa6\x9c\xbb\xe7\xcc\x2b\xeb\xa4\x3e\xfd\xc1\x02\x15\xac\x4e\xb3\x2d\xc3\x02\xa1\xf5\x3d\xc6\xc4\x35\x22\x67\xe7\x93\x6c\xfe\xbf\x7c\x8d\x67\x03\x57\x84\xa3\x90\x9f\xa8\x59\xc7\xb7\xb5\x9b\x8e\x39\xc5\xc2\x34\x9f\x18\x86\xb7\x05\xa3\x02\x67\xd4\x02\xf7\x48\x6a\xb4\xf5\x8c\xad\x5d\x69\xad\xb1\x7a\xb8\xcd\x0c\xe1\xca\xf5\x02\x5a\xf4\xae\x24\xb1\xfb\x87\x94\xc6\x07\x0c\xc0\x9a\x51\xe2\xf9\x91\x13\x11\xe3\x87\x7d\x00\x44\xc7\x1c\x57\xa9\x93\x39\x50\x08\x80\x6b\x72\x3a\xc3\x83\x73\xd3\x95\x48\x18\x18\x52\x8c\x1e\x70\x53\x73\x92\x82\x05\x35\x29\x51\x0e\x93\x5c\xd0\xfa\x77\xb8\xfa\x53\xcc\x2d\x47\x4b\xd4\xfb\x3c\xc5\xc6\x72\xd6\xff\xdc\x90\xa0\x0f\x98\x48\x71\x2c\x4b\xcf\xe4\x6c\x60\x57\x36\x59\xb1\x1e\x64\x57\xe8\x61\xf0\xf6\x04\xb6\x13\x8d\x14\x4f\x8c\xe4\xe2\xda\x73" , salt = "\xa8\xab\x69\xdd\x80\x1f\x00\x74\xc2\xa1\xfc\x60\x64\x98\x36\xc6\x16\xd9\x96\x81" , signature = "\x2a\x34\xf6\x12\x5e\x1f\x6b\x0b\xf9\x71\xe8\x4f\xbd\x41\xc6\x32\xbe\x8f\x2c\x2a\xce\x7d\xe8\xb6\x92\x6e\x31\xff\x93\xe9\xaf\x98\x7f\xbc\x06\xe5\x1e\x9b\xe1\x4f\x51\x98\xf9\x1f\x3f\x95\x3b\xd6\x7d\xa6\x0a\x9d\xf5\x97\x64\xc3\xdc\x0f\xe0\x8e\x1c\xbe\xf0\xb7\x5f\x86\x8d\x10\xad\x3f\xba\x74\x9f\xef\x59\xfb\x6d\xac\x46\xa0\xd6\xe5\x04\x36\x93\x31\x58\x6f\x58\xe4\x62\x8f\x39\xaa\x27\x89\x82\x54\x3b\xc0\xee\xb5\x37\xdc\x61\x95\x80\x19\xb3\x94\xfb\x27\x3f\x21\x58\x58\xa0\xa0\x1a\xc4\xd6\x50\xb9\x55\xc6\x7f\x4c\x58" } ] {- # =================================== # Example 10: A 2048-bit RSA Key Pair # =================================== # ------------------------------ # Components of the RSA Key Pair # ------------------------------ # RSA modulus n: a5 dd 86 7a c4 cb 02 f9 0b 94 57 d4 8c 14 a7 70 ef 99 1c 56 c3 9c 0e c6 5f d1 1a fa 89 37 ce a5 7b 9b e7 ac 73 b4 5c 00 17 61 5b 82 d6 22 e3 18 75 3b 60 27 c0 fd 15 7b e1 2f 80 90 fe e2 a7 ad cd 0e ef 75 9f 88 ba 49 97 c7 a4 2d 58 c9 aa 12 cb 99 ae 00 1f e5 21 c1 3b b5 43 14 45 a8 d5 ae 4f 5e 4c 7e 94 8a c2 27 d3 60 40 71 f2 0e 57 7e 90 5f be b1 5d fa f0 6d 1d e5 ae 62 53 d6 3a 6a 21 20 b3 1a 5d a5 da bc 95 50 60 0e 20 f2 7d 37 39 e2 62 79 25 fe a3 cc 50 9f 21 df f0 4e 6e ea 45 49 c5 40 d6 80 9f f9 30 7e ed e9 1f ff 58 73 3d 83 85 a2 37 d6 d3 70 5a 33 e3 91 90 09 92 07 0d f7 ad f1 35 7c f7 e3 70 0c e3 66 7d e8 3f 17 b8 df 17 78 db 38 1d ce 09 cb 4a d0 58 a5 11 00 1a 73 81 98 ee 27 cf 55 a1 3b 75 45 39 90 65 82 ec 8b 17 4b d5 8d 5d 1f 3d 76 7c 61 37 21 ae 05 # RSA public exponent e: 01 00 01 # RSA private exponent d: 2d 2f f5 67 b3 fe 74 e0 61 91 b7 fd ed 6d e1 12 29 0c 67 06 92 43 0d 59 69 18 40 47 da 23 4c 96 93 de ed 16 73 ed 42 95 39 c9 69 d3 72 c0 4d 6b 47 e0 f5 b8 ce e0 84 3e 5c 22 83 5d bd 3b 05 a0 99 79 84 ae 60 58 b1 1b c4 90 7c bf 67 ed 84 fa 9a e2 52 df b0 d0 cd 49 e6 18 e3 5d fd fe 59 bc a3 dd d6 6c 33 ce bb c7 7a d4 41 aa 69 5e 13 e3 24 b5 18 f0 1c 60 f5 a8 5c 99 4a d1 79 f2 a6 b5 fb e9 34 02 b1 17 67 be 01 bf 07 34 44 d6 ba 1d d2 bc a5 bd 07 4d 4a 5f ae 35 31 ad 13 03 d8 4b 30 d8 97 31 8c bb ba 04 e0 3c 2e 66 de 6d 91 f8 2f 96 ea 1d 4b b5 4a 5a ae 10 2d 59 46 57 f5 c9 78 95 53 51 2b 29 6d ea 29 d8 02 31 96 35 7e 3e 3a 6e 95 8f 39 e3 c2 34 40 38 ea 60 4b 31 ed c6 f0 f7 ff 6e 71 81 a5 7c 92 82 6a 26 8f 86 76 8e 96 f8 78 56 2f c7 1d 85 d6 9e 44 86 12 f7 04 8f # Prime p: cf d5 02 83 fe ee b9 7f 6f 08 d7 3c bc 7b 38 36 f8 2b bc d4 99 47 9f 5e 6f 76 fd fc b8 b3 8c 4f 71 dc 9e 88 bd 6a 6f 76 37 1a fd 65 d2 af 18 62 b3 2a fb 34 a9 5f 71 b8 b1 32 04 3f fe be 3a 95 2b af 75 92 44 81 48 c0 3f 9c 69 b1 d6 8e 4c e5 cf 32 c8 6b af 46 fe d3 01 ca 1a b4 03 06 9b 32 f4 56 b9 1f 71 89 8a b0 81 cd 8c 42 52 ef 52 71 91 5c 97 94 b8 f2 95 85 1d a7 51 0f 99 cb 73 eb # Prime q: cc 4e 90 d2 a1 b3 a0 65 d3 b2 d1 f5 a8 fc e3 1b 54 44 75 66 4e ab 56 1d 29 71 b9 9f b7 be f8 44 e8 ec 1f 36 0b 8c 2a c8 35 96 92 97 1e a6 a3 8f 72 3f cc 21 1f 5d bc b1 77 a0 fd ac 51 64 a1 d4 ff 7f bb 4e 82 99 86 35 3c b9 83 65 9a 14 8c dd 42 0c 7d 31 ba 38 22 ea 90 a3 2b e4 6c 03 0e 8c 17 e1 fa 0a d3 78 59 e0 6b 0a a6 fa 3b 21 6d 9c be 6c 0e 22 33 97 69 c0 a6 15 91 3e 5d a7 19 cf # p's CRT exponent dP: 1c 2d 1f c3 2f 6b c4 00 4f d8 5d fd e0 fb bf 9a 4c 38 f9 c7 c4 e4 1d ea 1a a8 82 34 a2 01 cd 92 f3 b7 da 52 65 83 a9 8a d8 5b b3 60 fb 98 3b 71 1e 23 44 9d 56 1d 17 78 d7 a5 15 48 6b cb f4 7b 46 c9 e9 e1 a3 a1 f7 70 00 ef be b0 9a 8a fe 47 e5 b8 57 cd a9 9c b1 6d 7f ff 9b 71 2e 3b d6 0c a9 6d 9c 79 73 d6 16 d4 69 34 a9 c0 50 28 1c 00 43 99 ce ff 1d b7 dd a7 87 66 a8 a9 b9 cb 08 73 # q's CRT exponent dQ: cb 3b 3c 04 ca a5 8c 60 be 7d 9b 2d eb b3 e3 96 43 f4 f5 73 97 be 08 23 6a 1e 9e af aa 70 65 36 e7 1c 3a cf e0 1c c6 51 f2 3c 9e 05 85 8f ee 13 bb 6a 8a fc 47 df 4e dc 9a 4b a3 0b ce cb 73 d0 15 78 52 32 7e e7 89 01 5c 2e 8d ee 7b 9f 05 a0 f3 1a c9 4e b6 17 31 64 74 0c 5c 95 14 7c d5 f3 b5 ae 2c b4 a8 37 87 f0 1d 8a b3 1f 27 c2 d0 ee a2 dd 8a 11 ab 90 6a ba 20 7c 43 c6 ee 12 53 31 # CRT coefficient qInv: 12 f6 b2 cf 13 74 a7 36 fa d0 56 16 05 0f 96 ab 4b 61 d1 17 7c 7f 9d 52 5a 29 f3 d1 80 e7 76 67 e9 9d 99 ab f0 52 5d 07 58 66 0f 37 52 65 5b 0f 25 b8 df 84 31 d9 a8 ff 77 c1 6c 12 a0 a5 12 2a 9f 0b f7 cf d5 a2 66 a3 5c 15 9f 99 12 08 b9 03 16 ff 44 4f 3e 0b 6b d0 e9 3b 8a 7a 24 48 e9 57 e3 dd a6 cf cf 22 66 b1 06 01 3a c4 68 08 d3 b3 88 7b 3b 00 34 4b aa c9 53 0b 4c e7 08 fc 32 b6 # --------------------------------- # RSASSA-PSS Signature Example 10.1 # --------------------------------- # Message to be signed: 88 31 77 e5 12 6b 9b e2 d9 a9 68 03 27 d5 37 0c 6f 26 86 1f 58 20 c4 3d a6 7a 3a d6 09 # Salt: 04 e2 15 ee 6f f9 34 b9 da 70 d7 73 0c 87 34 ab fc ec de 89 # Signature: 82 c2 b1 60 09 3b 8a a3 c0 f7 52 2b 19 f8 73 54 06 6c 77 84 7a bf 2a 9f ce 54 2d 0e 84 e9 20 c5 af b4 9f fd fd ac e1 65 60 ee 94 a1 36 96 01 14 8e ba d7 a0 e1 51 cf 16 33 17 91 a5 72 7d 05 f2 1e 74 e7 eb 81 14 40 20 69 35 d7 44 76 5a 15 e7 9f 01 5c b6 6c 53 2c 87 a6 a0 59 61 c8 bf ad 74 1a 9a 66 57 02 28 94 39 3e 72 23 73 97 96 c0 2a 77 45 5d 0f 55 5b 0e c0 1d df 25 9b 62 07 fd 0f d5 76 14 ce f1 a5 57 3b aa ff 4e c0 00 69 95 16 59 b8 5f 24 30 0a 25 16 0c a8 52 2d c6 e6 72 7e 57 d0 19 d7 e6 36 29 b8 fe 5e 89 e2 5c c1 5b eb 3a 64 75 77 55 92 99 28 0b 9b 28 f7 9b 04 09 00 0b e2 5b bd 96 40 8b a3 b4 3c c4 86 18 4d d1 c8 e6 25 53 fa 1a f4 04 0f 60 66 3d e7 f5 e4 9c 04 38 8e 25 7f 1c e8 9c 95 da b4 8a 31 5d 9b 66 b1 b7 62 82 33 87 6f f2 38 52 30 d0 70 d0 7e 16 66 # --------------------------------- # RSASSA-PSS Signature Example 10.2 # --------------------------------- # Message to be signed: dd 67 0a 01 46 58 68 ad c9 3f 26 13 19 57 a5 0c 52 fb 77 7c db aa 30 89 2c 9e 12 36 11 64 ec 13 97 9d 43 04 81 18 e4 44 5d b8 7b ee 58 dd 98 7b 34 25 d0 20 71 d8 db ae 80 70 8b 03 9d bb 64 db d1 de 56 57 d9 fe d0 c1 18 a5 41 43 74 2e 0f f3 c8 7f 74 e4 58 57 64 7a f3 f7 9e b0 a1 4c 9d 75 ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e 80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac # Salt: 8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb 57 f9 b7 1b # Signature: 14 ae 35 d9 dd 06 ba 92 f7 f3 b8 97 97 8a ed 7c d4 bf 5f f0 b5 85 a4 0b d4 6c e1 b4 2c d2 70 30 53 bb 90 44 d6 4e 81 3d 8f 96 db 2d d7 00 7d 10 11 8f 6f 8f 84 96 09 7a d7 5e 1f f6 92 34 1b 28 92 ad 55 a6 33 a1 c5 5e 7f 0a 0a d5 9a 0e 20 3a 5b 82 78 ae c5 4d d8 62 2e 28 31 d8 71 74 f8 ca ff 43 ee 6c 46 44 53 45 d8 4a 59 65 9b fb 92 ec d4 c8 18 66 86 95 f3 47 06 f6 68 28 a8 99 59 63 7f 2b f3 e3 25 1c 24 bd ba 4d 4b 76 49 da 00 22 21 8b 11 9c 84 e7 9a 65 27 ec 5b 8a 5f 86 1c 15 99 52 e2 3e c0 5e 1e 71 73 46 fa ef e8 b1 68 68 25 bd 2b 26 2f b2 53 10 66 c0 de 09 ac de 2e 42 31 69 07 28 b5 d8 5e 11 5a 2f 6b 92 b7 9c 25 ab c9 bd 93 99 ff 8b cf 82 5a 52 ea 1f 56 ea 76 dd 26 f4 3b aa fa 18 bf a9 2a 50 4c bd 35 69 9e 26 d1 dc c5 a2 88 73 85 f3 c6 32 32 f0 6f 32 44 c3 # --------------------------------- # RSASSA-PSS Signature Example 10.3 # --------------------------------- # Message to be signed: 48 b2 b6 a5 7a 63 c8 4c ea 85 9d 65 c6 68 28 4b 08 d9 6b dc aa be 25 2d b0 e4 a9 6c b1 ba c6 01 93 41 db 6f be fb 8d 10 6b 0e 90 ed a6 bc c6 c6 26 2f 37 e7 ea 9c 7e 5d 22 6b d7 df 85 ec 5e 71 ef ff 2f 54 c5 db 57 7f f7 29 ff 91 b8 42 49 1d e2 74 1d 0c 63 16 07 df 58 6b 90 5b 23 b9 1a f1 3d a1 23 04 bf 83 ec a8 a7 3e 87 1f f9 db # Salt: 4e 96 fc 1b 39 8f 92 b4 46 71 01 0c 0d c3 ef d6 e2 0c 2d 73 # Signature: 6e 3e 4d 7b 6b 15 d2 fb 46 01 3b 89 00 aa 5b bb 39 39 cf 2c 09 57 17 98 70 42 02 6e e6 2c 74 c5 4c ff d5 d7 d5 7e fb bf 95 0a 0f 5c 57 4f a0 9d 3f c1 c9 f5 13 b0 5b 4f f5 0d d8 df 7e df a2 01 02 85 4c 35 e5 92 18 01 19 a7 0c e5 b0 85 18 2a a0 2d 9e a2 aa 90 d1 df 03 f2 da ae 88 5b a2 f5 d0 5a fd ac 97 47 6f 06 b9 3b 5b c9 4a 1a 80 aa 91 16 c4 d6 15 f3 33 b0 98 89 2b 25 ff ac e2 66 f5 db 5a 5a 3b cc 10 a8 24 ed 55 aa d3 5b 72 78 34 fb 8c 07 da 28 fc f4 16 a5 d9 b2 22 4f 1f 8b 44 2b 36 f9 1e 45 6f de a2 d7 cf e3 36 72 68 de 03 07 a4 c7 4e 92 41 59 ed 33 39 3d 5e 06 55 53 1c 77 32 7b 89 82 1b de df 88 01 61 c7 8c d4 19 6b 54 19 f7 ac c3 f1 3e 5e bf 16 1b 6e 7c 67 24 71 6c a3 3b 85 c2 e2 56 40 19 2a c2 85 96 51 d5 0b de 7e b9 76 e5 1c ec 82 8b 98 b6 56 3b 86 bb # --------------------------------- # RSASSA-PSS Signature Example 10.4 # --------------------------------- # Message to be signed: 0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 75 5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 c4 e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b 82 db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 2a 62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 45 1a # Salt: c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e b0 e0 1c b5 41 ec # Signature: 34 04 7f f9 6c 4d c0 dc 90 b2 d4 ff 59 a1 a3 61 a4 75 4b 25 5d 2e e0 af 7d 8b f8 7c 9b c9 e7 dd ee de 33 93 4c 63 ca 1c 0e 3d 26 2c b1 45 ef 93 2a 1f 2c 0a 99 7a a6 a3 4f 8e ae e7 47 7d 82 cc f0 90 95 a6 b8 ac ad 38 d4 ee c9 fb 7e ab 7a d0 2d a1 d1 1d 8e 54 c1 82 5e 55 bf 58 c2 a2 32 34 b9 02 be 12 4f 9e 90 38 a8 f6 8f a4 5d ab 72 f6 6e 09 45 bf 1d 8b ac c9 04 4c 6f 07 09 8c 9f ce c5 8a 3a ab 10 0c 80 51 78 15 5f 03 0a 12 4c 45 0e 5a cb da 47 d0 e4 f1 0b 80 a2 3f 80 3e 77 4d 02 3b 00 15 c2 0b 9f 9b be 7c 91 29 63 38 d5 ec b4 71 ca fb 03 20 07 b6 7a 60 be 5f 69 50 4a 9f 01 ab b3 cb 46 7b 26 0e 2b ce 86 0b e8 d9 5b f9 2c 0c 8e 14 96 ed 1e 52 85 93 a4 ab b6 df 46 2d de 8a 09 68 df fe 46 83 11 68 57 a2 32 f5 eb f6 c8 5b e2 38 74 5a d0 f3 8f 76 7a 5f db f4 86 fb # --------------------------------- # RSASSA-PSS Signature Example 10.5 # --------------------------------- # Message to be signed: f1 03 6e 00 8e 71 e9 64 da dc 92 19 ed 30 e1 7f 06 b4 b6 8a 95 5c 16 b3 12 b1 ed df 02 8b 74 97 6b ed 6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98 01 65 23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b b7 c7 bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9 16 # Salt: ef a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52 65 5f 5d fb # Signature: 7e 09 35 ea 18 f4 d6 c1 d1 7c e8 2e b2 b3 83 6c 55 b3 84 58 9c e1 9d fe 74 33 63 ac 99 48 d1 f3 46 b7 bf dd fe 92 ef d7 8a db 21 fa ef c8 9a de 42 b1 0f 37 40 03 fe 12 2e 67 42 9a 1c b8 cb d1 f8 d9 01 45 64 c4 4d 12 01 16 f4 99 0f 1a 6e 38 77 4c 19 4b d1 b8 21 32 86 b0 77 b0 49 9d 2e 7b 3f 43 4a b1 22 89 c5 56 68 4d ee d7 81 31 93 4b b3 dd 65 37 23 6f 7c 6f 3d cb 09 d4 76 be 07 72 1e 37 e1 ce ed 9b 2f 7b 40 68 87 bd 53 15 73 05 e1 c8 b4 f8 4d 73 3b c1 e1 86 fe 06 cc 59 b6 ed b8 f4 bd 7f fe fd f4 f7 ba 9c fb 9d 57 06 89 b5 a1 a4 10 9a 74 6a 69 08 93 db 37 99 25 5a 0c b9 21 5d 2d 1c d4 90 59 0e 95 2e 8c 87 86 aa 00 11 26 52 52 47 0c 04 1d fb c3 ee c7 c3 cb f7 1c 24 86 9d 11 5c 0c b4 a9 56 f5 6d 53 0b 80 ab 58 9a cf ef c6 90 75 1d df 36 e8 d3 83 f8 3c ed d2 cc # --------------------------------- # RSASSA-PSS Signature Example 10.6 # --------------------------------- # Message to be signed: 25 f1 08 95 a8 77 16 c1 37 45 0b b9 51 9d fa a1 f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 98 00 85 b5 55 ae ba b7 62 64 ae 2a 3a b9 3c 2d 12 98 11 91 dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 40 f0 07 52 c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 b6 88 f2 03 23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 dc 21 17 c0 74 34 fc f9 72 e0 58 cf 8c 41 ca 4b 4f f5 54 f7 d5 06 8a d3 15 5f ce d0 f3 12 5b c0 4f 91 93 37 8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d 30 ec ca 6e aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b af 09 9d ef b8 af d7 # Salt: ad 8b 15 23 70 36 46 22 4b 66 0b 55 08 85 91 7c a2 d1 df 28 # Signature: 6d 3b 5b 87 f6 7e a6 57 af 21 f7 54 41 97 7d 21 80 f9 1b 2c 5f 69 2d e8 29 55 69 6a 68 67 30 d9 b9 77 8d 97 07 58 cc b2 60 71 c2 20 9f fb d6 12 5b e2 e9 6e a8 1b 67 cb 9b 93 08 23 9f da 17 f7 b2 b6 4e cd a0 96 b6 b9 35 64 0a 5a 1c b4 2a 91 55 b1 c9 ef 7a 63 3a 02 c5 9f 0d 6e e5 9b 85 2c 43 b3 50 29 e7 3c 94 0f f0 41 0e 8f 11 4e ed 46 bb d0 fa e1 65 e4 2b e2 52 8a 40 1c 3b 28 fd 81 8e f3 23 2d ca 9f 4d 2a 0f 51 66 ec 59 c4 23 96 d6 c1 1d bc 12 15 a5 6f a1 71 69 db 95 75 34 3e f3 4f 9d e3 2a 49 cd c3 17 49 22 f2 29 c2 3e 18 e4 5d f9 35 31 19 ec 43 19 ce dc e7 a1 7c 64 08 8c 1f 6f 52 be 29 63 41 00 b3 91 9d 38 f3 d1 ed 94 e6 89 1e 66 a7 3b 8f b8 49 f5 87 4d f5 94 59 e2 98 c7 bb ce 2e ee 78 2a 19 5a a6 6f e2 d0 73 2b 25 e5 95 f5 7d 3e 06 1b 1f c3 e4 06 3b f9 8f -} doSignTest key (i, vector) = testCase (show i) (Right (signature vector) @=? actual) where actual = PSS.signWithSalt (salt vector) Nothing PSS.defaultPSSParamsSHA1 key (message vector) doVerifyTest key (i, vector) = testCase (show i) (True @=? actual) where actual = PSS.verify PSS.defaultPSSParamsSHA1 (private_pub key) (message vector) (signature vector) pssTests = testGroup "RSA-PSS" [ testGroup "signature internal" [ doSignTest rsaKeyInt (0, vectorInt) ] , testGroup "verify internal" [ doVerifyTest rsaKeyInt (0, vectorInt) ] , testGroup "signature key 1024" $ map (doSignTest rsaKey1) (zip [0..] vectorsKey1) , testGroup "verify key 1024" $ map (doVerifyTest rsaKey1) (zip [0..] vectorsKey1) ]