Merge branch 'pubkey-merge'

This commit is contained in:
Vincent Hanquez 2015-04-03 07:34:04 +01:00
commit f428843322
26 changed files with 3019 additions and 0 deletions

1
.gitignore vendored
View File

@ -3,4 +3,5 @@
*.tix
*.mix
gen/Gen
gen/Crypto
dist

74
Crypto/PubKey/DH.hs Normal file
View File

@ -0,0 +1,74 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-- |
-- Module : Crypto.PubKey.DH
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
{-# LANGUAGE DeriveDataTypeable #-}
module Crypto.PubKey.DH
( Params(..)
, PublicNumber(..)
, PrivateNumber(..)
, SharedKey(..)
, generateParams
, generatePrivate
, calculatePublic
, generatePublic
, getShared
) where
import Control.Applicative
import Crypto.Number.ModArithmetic (expSafe)
import Crypto.Number.Prime (generateSafePrime)
import Crypto.Number.Generate (generateMax)
import Crypto.Random.Types
import Data.Data
-- | Represent Diffie Hellman parameters namely P (prime), and G (generator).
data Params = Params
{ params_p :: Integer
, params_g :: Integer
} deriving (Show,Read,Eq,Data,Typeable)
-- | Represent Diffie Hellman public number Y.
newtype PublicNumber = PublicNumber Integer
deriving (Show,Read,Eq,Enum,Real,Num,Ord)
-- | Represent Diffie Hellman private number X.
newtype PrivateNumber = PrivateNumber Integer
deriving (Show,Read,Eq,Enum,Real,Num,Ord)
-- | Represent Diffie Hellman shared secret.
newtype SharedKey = SharedKey Integer
deriving (Show,Read,Eq,Enum,Real,Num,Ord)
-- | 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 :: MonadRandom m => Int -> Integer -> m Params
generateParams bits generator =
(\p -> Params p generator) <$> generateSafePrime bits
-- | generate a private number with no specific property
-- this number is usually called X in DH text.
generatePrivate :: MonadRandom m => Params -> m PrivateNumber
generatePrivate (Params p _) = PrivateNumber <$> generateMax 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

130
Crypto/PubKey/DSA.hs Normal file
View File

@ -0,0 +1,130 @@
-- |
-- Module : Crypto.PubKey.DSA
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
-- An implementation of the Digital Signature Algorithm (DSA)
{-# LANGUAGE DeriveDataTypeable #-}
module Crypto.PubKey.DSA
( Params(..)
, Signature(..)
, PublicKey(..)
, PrivateKey(..)
-- * generation
, generatePrivate
, calculatePublic
-- * signature primitive
, sign
, signWith
-- * verification primitive
, verify
) where
import Crypto.Random.Types
import Data.Data
import Data.Maybe
import Data.ByteString (ByteString)
import Crypto.Number.ModArithmetic (expFast, expSafe, inverse)
import Crypto.Number.Serialize
import Crypto.Number.Generate
import Crypto.PubKey.HashDescr
-- | DSA Public Number, usually embedded in DSA Public Key
type PublicNumber = Integer
-- | DSA Private Number, usually embedded in DSA Private Key
type PrivateNumber = Integer
-- | Represent DSA parameters namely P, G, and Q.
data Params = Params
{ params_p :: Integer -- ^ DSA p
, params_g :: Integer -- ^ DSA g
, params_q :: Integer -- ^ DSA q
} deriving (Show,Read,Eq,Data,Typeable)
-- | Represent a DSA signature namely R and S.
data Signature = Signature
{ sign_r :: Integer -- ^ DSA r
, sign_s :: Integer -- ^ DSA s
} deriving (Show,Read,Eq,Data,Typeable)
-- | Represent a DSA public key.
data PublicKey = PublicKey
{ public_params :: Params -- ^ DSA parameters
, public_y :: PublicNumber -- ^ DSA public Y
} deriving (Show,Read,Eq,Data,Typeable)
-- | Represent a DSA private key.
--
-- Only x need to be secret.
-- the DSA parameters are publicly shared with the other side.
data PrivateKey = PrivateKey
{ private_params :: Params -- ^ DSA parameters
, private_x :: PrivateNumber -- ^ DSA private X
} deriving (Show,Read,Eq,Data,Typeable)
-- | Represent a DSA key pair
data KeyPair = KeyPair Params PublicNumber PrivateNumber
deriving (Show,Read,Eq,Data,Typeable)
-- | Public key of a DSA Key pair
toPublicKey :: KeyPair -> PublicKey
toPublicKey (KeyPair params pub _) = PublicKey params pub
-- | Private key of a DSA Key pair
toPrivateKey :: KeyPair -> PrivateKey
toPrivateKey (KeyPair params _ priv) = PrivateKey params priv
-- | generate a private number with no specific property
-- this number is usually called X in DSA text.
generatePrivate :: MonadRandom m => Params -> m PrivateNumber
generatePrivate (Params _ _ q) = generateMax 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 :: MonadRandom m => PrivateKey -> HashFunction -> ByteString -> m Signature
sign pk hash msg = do
k <- generateMax q
case signWith k pk hash msg of
Nothing -> sign pk hash msg
Just sig -> return sig
where
(Params _ _ q) = private_params pk
-- | 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

36
Crypto/PubKey/ECC/DH.hs Normal file
View File

@ -0,0 +1,36 @@
module 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.Types
import Crypto.PubKey.DH (SharedKey(..))
import Crypto.PubKey.ECC.Types (PublicPoint, PrivateNumber, Curve, Point(..))
import Crypto.PubKey.ECC.Types (ecc_n, ecc_g, common_curve)
-- | Generating a private number d.
generatePrivate :: MonadRandom m => Curve -> m PrivateNumber
generatePrivate curve = generateMax 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

119
Crypto/PubKey/ECC/ECDSA.hs Normal file
View File

@ -0,0 +1,119 @@
-- | /WARNING:/ Signature operations may leak the private key. Signature verification
-- should be safe.
{-# LANGUAGE DeriveDataTypeable #-}
module Crypto.PubKey.ECC.ECDSA
( Signature(..)
, PublicPoint
, PublicKey(..)
, PrivateNumber
, PrivateKey(..)
, KeyPair(..)
, toPublicKey
, toPrivateKey
, signWith
, sign
, verify
) where
import Control.Monad
import Crypto.Random.Types
import Data.Bits (shiftR)
import Data.ByteString (ByteString)
import Data.Data
import Crypto.Number.ModArithmetic (inverse)
import Crypto.Number.Serialize
import Crypto.Number.Generate
import Crypto.PubKey.ECC.Types
import Crypto.PubKey.HashDescr
import Crypto.PubKey.ECC.Prim
-- | Represent a ECDSA signature namely R and S.
data Signature = Signature
{ sign_r :: Integer -- ^ ECDSA r
, sign_s :: Integer -- ^ ECDSA s
} deriving (Show,Read,Eq,Data,Typeable)
-- | ECDSA Private Key.
data PrivateKey = PrivateKey
{ private_curve :: Curve
, private_d :: PrivateNumber
} deriving (Show,Read,Eq,Data,Typeable)
-- | ECDSA Public Key.
data PublicKey = PublicKey
{ public_curve :: Curve
, public_q :: PublicPoint
} deriving (Show,Read,Eq,Data,Typeable)
-- | ECDSA Key Pair.
data KeyPair = KeyPair Curve PublicPoint PrivateNumber
deriving (Show,Read,Eq,Data,Typeable)
-- | Public key of a ECDSA Key pair.
toPublicKey :: KeyPair -> PublicKey
toPublicKey (KeyPair curve pub _) = PublicKey curve pub
-- | Private key of a ECDSA Key pair.
toPrivateKey :: KeyPair -> PrivateKey
toPrivateKey (KeyPair curve _ priv) = PrivateKey curve priv
-- | 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 :: MonadRandom m => PrivateKey -> HashFunction -> ByteString -> m Signature
sign pk hash msg = do
k <- generateBetween 1 (n - 1)
case signWith k pk hash msg of
Nothing -> sign pk hash msg
Just sig -> return sig
where n = ecc_n . common_curve $ private_curve pk
-- | 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

View File

@ -0,0 +1,30 @@
-- | Signature generation.
module Crypto.PubKey.ECC.Generate where
import Crypto.Random.Types
import Crypto.PubKey.ECC.Types
import Crypto.PubKey.ECC.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 :: MonadRandom m
=> Curve -- ^ Elliptic Curve
-> m (PublicKey, PrivateKey)
generate curve = do
d <- generateBetween 1 (n - 1)
let q = generateQ curve d
return (PublicKey curve q, PrivateKey curve d)
where
n = ecc_n $ common_curve curve

124
Crypto/PubKey/ECC/Prim.hs Normal file
View File

@ -0,0 +1,124 @@
-- | 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.PubKey.ECC.Types
--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

485
Crypto/PubKey/ECC/Types.hs Normal file
View File

@ -0,0 +1,485 @@
{-# LANGUAGE DeriveDataTypeable #-}
-- |
-- Module : Crypto.PubKey.ECC.types
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : Experimental
-- Portability : Excellent
--
-- references:
-- <https://tools.ietf.org/html/rfc5915>
--
module Crypto.PubKey.ECC.Types
( Curve(..)
, Point(..)
, PublicPoint
, PrivateNumber
, CurveBinary(..)
, CurvePrime(..)
, common_curve
, ecc_fx
, ecc_p
, CurveCommon(..)
-- * recommended curves definition
, CurveName(..)
, getCurveByName
) where
import Data.Data
import Data.Tuple (swap)
-- | Define either a binary curve or a prime curve.
data Curve = CurveF2m CurveBinary -- ^ 𝔽(2^m)
| CurveFP CurvePrime -- ^ 𝔽p
deriving (Show,Read,Eq,Data,Typeable)
-- | ECC Public Point
type PublicPoint = Point
-- | ECC Private Number
type PrivateNumber = Integer
-- | Define a point on a curve.
data Point = Point Integer Integer
| PointO -- ^ Point at Infinity
deriving (Show,Read,Eq,Data,Typeable)
-- | Define an elliptic curve in 𝔽(2^m).
-- The firt parameter is the Integer representatioin of the irreducible polynomial f(x).
data CurveBinary = CurveBinary Integer CurveCommon
deriving (Show,Read,Eq,Data,Typeable)
-- | Define an elliptic curve in 𝔽p.
-- The first parameter is the Prime Number.
data CurvePrime = CurvePrime Integer CurveCommon
deriving (Show,Read,Eq,Data,Typeable)
-- | Parameters in common between binary and prime curves.
common_curve :: Curve -> CurveCommon
common_curve (CurveF2m (CurveBinary _ cc)) = cc
common_curve (CurveFP (CurvePrime _ cc)) = cc
-- | Irreducible polynomial representing the characteristic of a CurveBinary.
ecc_fx :: CurveBinary -> Integer
ecc_fx (CurveBinary fx _) = fx
-- | Prime number representing the characteristic of a CurvePrime.
ecc_p :: CurvePrime -> Integer
ecc_p (CurvePrime p _) = p
-- | Define common parameters in a curve definition
-- of the form: y^2 = x^3 + ax + b.
data CurveCommon = CurveCommon
{ ecc_a :: Integer -- ^ curve parameter a
, ecc_b :: Integer -- ^ curve parameter b
, ecc_g :: Point -- ^ base point
, ecc_n :: Integer -- ^ order of G
, ecc_h :: Integer -- ^ cofactor
} deriving (Show,Read,Eq,Data,Typeable)
-- | Define names for known recommended curves.
data CurveName =
SEC_p112r1
| SEC_p112r2
| SEC_p128r1
| SEC_p128r2
| SEC_p160k1
| SEC_p160r1
| SEC_p160r2
| SEC_p192k1
| SEC_p192r1 -- aka prime192v1
| SEC_p224k1
| SEC_p224r1
| SEC_p256k1
| SEC_p256r1 -- aka prime256v1
| SEC_p384r1
| SEC_p521r1
| SEC_t113r1
| SEC_t113r2
| SEC_t131r1
| SEC_t131r2
| SEC_t163k1
| SEC_t163r1
| SEC_t163r2
| SEC_t193r1
| SEC_t193r2
| SEC_t233k1 -- aka NIST K-233
| SEC_t233r1
| SEC_t239k1
| SEC_t283k1
| SEC_t283r1
| SEC_t409k1
| SEC_t409r1
| SEC_t571k1
| SEC_t571r1
deriving (Show,Read,Eq,Ord,Enum,Data,Typeable)
curvesOIDs :: [ (CurveName, [Integer]) ]
curvesOIDs =
[ (SEC_p112r1, [1,3,132,0,6])
, (SEC_p112r2, [1,3,132,0,7])
, (SEC_p128r1, [1,3,132,0,28])
, (SEC_p128r2, [1,3,132,0,29])
, (SEC_p160k1, [1,3,132,0,9])
, (SEC_p160r1, [1,3,132,0,8])
, (SEC_p160r2, [1,3,132,0,30])
, (SEC_p192k1, [1,3,132,0,31])
, (SEC_p192r1, [1,2,840,10045,3,1,1])
, (SEC_p224k1, [1,3,132,0,32])
, (SEC_p224r1, [1,3,132,0,33])
, (SEC_p256k1, [1,3,132,0,10])
, (SEC_p256r1, [1,2,840,10045,3,1,7])
, (SEC_p384r1, [1,3,132,0,34])
, (SEC_p521r1, [1,3,132,0,35])
, (SEC_t113r1, [1,3,132,0,4])
, (SEC_t113r2, [1,3,132,0,5])
, (SEC_t131r1, [1,3,132,0,22])
, (SEC_t131r2, [1,3,132,0,23])
, (SEC_t163k1, [1,3,132,0,1])
, (SEC_t163r1, [1,3,132,0,2])
, (SEC_t163r2, [1,3,132,0,15])
, (SEC_t193r1, [1,3,132,0,24])
, (SEC_t193r2, [1,3,132,0,25])
, (SEC_t233k1, [1,3,132,0,26])
, (SEC_t233r1, [1,3,132,0,27])
, (SEC_t239k1, [1,3,132,0,3])
, (SEC_t283k1, [1,3,132,0,16])
, (SEC_t283r1, [1,3,132,0,17])
, (SEC_t409k1, [1,3,132,0,36])
, (SEC_t409r1, [1,3,132,0,37])
, (SEC_t571k1, [1,3,132,0,38])
, (SEC_t571r1, [1,3,132,0,39])
]
-- | Get the curve definition associated with a recommended known curve name.
getCurveByName :: CurveName -> Curve
getCurveByName SEC_p112r1 = CurveFP $ CurvePrime
0xdb7c2abf62e35e668076bead208b
(CurveCommon
{ ecc_a = 0xdb7c2abf62e35e668076bead2088
, ecc_b = 0x659ef8ba043916eede8911702b22
, ecc_g = Point 0x09487239995a5ee76b55f9c2f098
0xa89ce5af8724c0a23e0e0ff77500
, ecc_n = 0xdb7c2abf62e35e7628dfac6561c5
, ecc_h = 1
})
getCurveByName SEC_p112r2 = CurveFP $ CurvePrime
0xdb7c2abf62e35e668076bead208b
(CurveCommon
{ ecc_a = 0x6127c24c05f38a0aaaf65c0ef02c
, ecc_b = 0x51def1815db5ed74fcc34c85d709
, ecc_g = Point 0x4ba30ab5e892b4e1649dd0928643
0xadcd46f5882e3747def36e956e97
, ecc_n = 0x36df0aafd8b8d7597ca10520d04b
, ecc_h = 4
})
getCurveByName SEC_p128r1 = CurveFP $ CurvePrime
0xfffffffdffffffffffffffffffffffff
(CurveCommon
{ ecc_a = 0xfffffffdfffffffffffffffffffffffc
, ecc_b = 0xe87579c11079f43dd824993c2cee5ed3
, ecc_g = Point 0x161ff7528b899b2d0c28607ca52c5b86
0xcf5ac8395bafeb13c02da292dded7a83
, ecc_n = 0xfffffffe0000000075a30d1b9038a115
, ecc_h = 1
})
getCurveByName SEC_p128r2 = CurveFP $ CurvePrime
0xfffffffdffffffffffffffffffffffff
(CurveCommon
{ ecc_a = 0xd6031998d1b3bbfebf59cc9bbff9aee1
, ecc_b = 0x5eeefca380d02919dc2c6558bb6d8a5d
, ecc_g = Point 0x7b6aa5d85e572983e6fb32a7cdebc140
0x27b6916a894d3aee7106fe805fc34b44
, ecc_n = 0x3fffffff7fffffffbe0024720613b5a3
, ecc_h = 4
})
getCurveByName SEC_p160k1 = CurveFP $ CurvePrime
0x00fffffffffffffffffffffffffffffffeffffac73
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000
, ecc_b = 0x000000000000000000000000000000000000000007
, ecc_g = Point 0x003b4c382ce37aa192a4019e763036f4f5dd4d7ebb
0x00938cf935318fdced6bc28286531733c3f03c4fee
, ecc_n = 0x0100000000000000000001b8fa16dfab9aca16b6b3
, ecc_h = 1
})
getCurveByName SEC_p160r1 = CurveFP $ CurvePrime
0x00ffffffffffffffffffffffffffffffff7fffffff
(CurveCommon
{ ecc_a = 0x00ffffffffffffffffffffffffffffffff7ffffffc
, ecc_b = 0x001c97befc54bd7a8b65acf89f81d4d4adc565fa45
, ecc_g = Point 0x004a96b5688ef573284664698968c38bb913cbfc82
0x0023a628553168947d59dcc912042351377ac5fb32
, ecc_n = 0x0100000000000000000001f4c8f927aed3ca752257
, ecc_h = 1
})
getCurveByName SEC_p160r2 = CurveFP $ CurvePrime
0x00fffffffffffffffffffffffffffffffeffffac73
(CurveCommon
{ ecc_a = 0x00fffffffffffffffffffffffffffffffeffffac70
, ecc_b = 0x00b4e134d3fb59eb8bab57274904664d5af50388ba
, ecc_g = Point 0x0052dcb034293a117e1f4ff11b30f7199d3144ce6d
0x00feaffef2e331f296e071fa0df9982cfea7d43f2e
, ecc_n = 0x0100000000000000000000351ee786a818f3a1a16b
, ecc_h = 1
})
getCurveByName SEC_p192k1 = CurveFP $ CurvePrime
0xfffffffffffffffffffffffffffffffffffffffeffffee37
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000000000
, ecc_b = 0x000000000000000000000000000000000000000000000003
, ecc_g = Point 0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d
0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d
, ecc_n = 0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d
, ecc_h = 1
})
getCurveByName SEC_p192r1 = CurveFP $ CurvePrime
0xfffffffffffffffffffffffffffffffeffffffffffffffff
(CurveCommon
{ ecc_a = 0xfffffffffffffffffffffffffffffffefffffffffffffffc
, ecc_b = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1
, ecc_g = Point 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012
0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811
, ecc_n = 0xffffffffffffffffffffffff99def836146bc9b1b4d22831
, ecc_h = 1
})
getCurveByName SEC_p224k1 = CurveFP $ CurvePrime
0x00fffffffffffffffffffffffffffffffffffffffffffffffeffffe56d
(CurveCommon
{ ecc_a = 0x0000000000000000000000000000000000000000000000000000000000
, ecc_b = 0x0000000000000000000000000000000000000000000000000000000005
, ecc_g = Point 0x00a1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c
0x007e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5
, ecc_n = 0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7
, ecc_h = 1
})
getCurveByName SEC_p224r1 = CurveFP $ CurvePrime
0xffffffffffffffffffffffffffffffff000000000000000000000001
(CurveCommon
{ ecc_a = 0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe
, ecc_b = 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
, ecc_g = Point 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34
, ecc_n = 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
, ecc_h = 1
})
getCurveByName SEC_p256k1 = CurveFP $ CurvePrime
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
(CurveCommon
{ ecc_a = 0x0000000000000000000000000000000000000000000000000000000000000000
, ecc_b = 0x0000000000000000000000000000000000000000000000000000000000000007
, ecc_g = Point 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
, ecc_n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
, ecc_h = 1
})
getCurveByName SEC_p256r1 = CurveFP $ CurvePrime
0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
(CurveCommon
{ ecc_a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc
, ecc_b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
, ecc_g = Point 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
, ecc_n = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
, ecc_h = 1
})
getCurveByName SEC_p384r1 = CurveFP $ CurvePrime
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff
(CurveCommon
{ ecc_a = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc
, ecc_b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef
, ecc_g = Point 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7
0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f
, ecc_n = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973
, ecc_h = 1
})
getCurveByName SEC_p521r1 = CurveFP $ CurvePrime
0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
(CurveCommon
{ ecc_a = 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc
, ecc_b = 0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00
, ecc_g = Point 0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66
0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650
, ecc_n = 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409
, ecc_h = 1
})
getCurveByName SEC_t113r1 = CurveF2m $ CurveBinary
0x020000000000000000000000000201
(CurveCommon
{ ecc_a = 0x003088250ca6e7c7fe649ce85820f7
, ecc_b = 0x00e8bee4d3e2260744188be0e9c723
, ecc_g = Point 0x009d73616f35f4ab1407d73562c10f
0x00a52830277958ee84d1315ed31886
, ecc_n = 0x0100000000000000d9ccec8a39e56f
, ecc_h = 2
})
getCurveByName SEC_t113r2 = CurveF2m $ CurveBinary
0x020000000000000000000000000201
(CurveCommon
{ ecc_a = 0x00689918dbec7e5a0dd6dfc0aa55c7
, ecc_b = 0x0095e9a9ec9b297bd4bf36e059184f
, ecc_g = Point 0x01a57a6a7b26ca5ef52fcdb8164797
0x00b3adc94ed1fe674c06e695baba1d
, ecc_n = 0x010000000000000108789b2496af93
, ecc_h = 2
})
getCurveByName SEC_t131r1 = CurveF2m $ CurveBinary
0x080000000000000000000000000000010d
(CurveCommon
{ ecc_a = 0x07a11b09a76b562144418ff3ff8c2570b8
, ecc_b = 0x0217c05610884b63b9c6c7291678f9d341
, ecc_g = Point 0x0081baf91fdf9833c40f9c181343638399
0x078c6e7ea38c001f73c8134b1b4ef9e150
, ecc_n = 0x0400000000000000023123953a9464b54d
, ecc_h = 2
})
getCurveByName SEC_t131r2 = CurveF2m $ CurveBinary
0x080000000000000000000000000000010d
(CurveCommon
{ ecc_a = 0x03e5a88919d7cafcbf415f07c2176573b2
, ecc_b = 0x04b8266a46c55657ac734ce38f018f2192
, ecc_g = Point 0x0356dcd8f2f95031ad652d23951bb366a8
0x0648f06d867940a5366d9e265de9eb240f
, ecc_n = 0x0400000000000000016954a233049ba98f
, ecc_h = 2
})
getCurveByName SEC_t163k1 = CurveF2m $ CurveBinary
0x0800000000000000000000000000000000000000c9
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000001
, ecc_b = 0x000000000000000000000000000000000000000001
, ecc_g = Point 0x02fe13c0537bbc11acaa07d793de4e6d5e5c94eee8
0x0289070fb05d38ff58321f2e800536d538ccdaa3d9
, ecc_n = 0x04000000000000000000020108a2e0cc0d99f8a5ef
, ecc_h = 2
})
getCurveByName SEC_t163r1 = CurveF2m $ CurveBinary
0x0800000000000000000000000000000000000000c9
(CurveCommon
{ ecc_a = 0x07b6882caaefa84f9554ff8428bd88e246d2782ae2
, ecc_b = 0x0713612dcddcb40aab946bda29ca91f73af958afd9
, ecc_g = Point 0x0369979697ab43897789566789567f787a7876a654
0x00435edb42efafb2989d51fefce3c80988f41ff883
, ecc_n = 0x03ffffffffffffffffffff48aab689c29ca710279b
, ecc_h = 2
})
getCurveByName SEC_t163r2 = CurveF2m $ CurveBinary
0x0800000000000000000000000000000000000000c9
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000001
, ecc_b = 0x020a601907b8c953ca1481eb10512f78744a3205fd
, ecc_g = Point 0x03f0eba16286a2d57ea0991168d4994637e8343e36
0x00d51fbc6c71a0094fa2cdd545b11c5c0c797324f1
, ecc_n = 0x040000000000000000000292fe77e70c12a4234c33
, ecc_h = 2
})
getCurveByName SEC_t193r1 = CurveF2m $ CurveBinary
0x02000000000000000000000000000000000000000000008001
(CurveCommon
{ ecc_a = 0x0017858feb7a98975169e171f77b4087de098ac8a911df7b01
, ecc_b = 0x00fdfb49bfe6c3a89facadaa7a1e5bbc7cc1c2e5d831478814
, ecc_g = Point 0x01f481bc5f0ff84a74ad6cdf6fdef4bf6179625372d8c0c5e1
0x0025e399f2903712ccf3ea9e3a1ad17fb0b3201b6af7ce1b05
, ecc_n = 0x01000000000000000000000000c7f34a778f443acc920eba49
, ecc_h = 2
})
getCurveByName SEC_t193r2 = CurveF2m $ CurveBinary
0x02000000000000000000000000000000000000000000008001
(CurveCommon
{ ecc_a = 0x0163f35a5137c2ce3ea6ed8667190b0bc43ecd69977702709b
, ecc_b = 0x00c9bb9e8927d4d64c377e2ab2856a5b16e3efb7f61d4316ae
, ecc_g = Point 0x00d9b67d192e0367c803f39e1a7e82ca14a651350aae617e8f
0x01ce94335607c304ac29e7defbd9ca01f596f927224cdecf6c
, ecc_n = 0x010000000000000000000000015aab561b005413ccd4ee99d5
, ecc_h = 2
})
getCurveByName SEC_t233k1 = CurveF2m $ CurveBinary
0x020000000000000000000000000000000000000004000000000000000001
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000000000000000000000
, ecc_b = 0x000000000000000000000000000000000000000000000000000000000001
, ecc_g = Point 0x017232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126
0x01db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3
, ecc_n = 0x008000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf
, ecc_h = 4
})
getCurveByName SEC_t233r1 = CurveF2m $ CurveBinary
0x020000000000000000000000000000000000000004000000000000000001
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000000000000000000001
, ecc_b = 0x0066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad
, ecc_g = Point 0x00fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b
0x01006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052
, ecc_n = 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7
, ecc_h = 2
})
getCurveByName SEC_t239k1 = CurveF2m $ CurveBinary
0x800000000000000000004000000000000000000000000000000000000001
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000000000000000000000
, ecc_b = 0x000000000000000000000000000000000000000000000000000000000001
, ecc_g = Point 0x29a0b6a887a983e9730988a68727a8b2d126c44cc2cc7b2a6555193035dc
0x76310804f12e549bdb011c103089e73510acb275fc312a5dc6b76553f0ca
, ecc_n = 0x2000000000000000000000000000005a79fec67cb6e91f1c1da800e478a5
, ecc_h = 4
})
getCurveByName SEC_t283k1 = CurveF2m $ CurveBinary
0x0800000000000000000000000000000000000000000000000000000000000000000010a1
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000000000000000000000000000000000
, ecc_b = 0x000000000000000000000000000000000000000000000000000000000000000000000001
, ecc_g = Point 0x0503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836
0x01ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259
, ecc_n = 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61
, ecc_h = 4
})
getCurveByName SEC_t283r1 = CurveF2m $ CurveBinary
0x0800000000000000000000000000000000000000000000000000000000000000000010a1
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000000000000000000000000000000001
, ecc_b = 0x027b680ac8b8596da5a4af8a19a0303fca97fd7645309fa2a581485af6263e313b79a2f5
, ecc_g = Point 0x05f939258db7dd90e1934f8c70b0dfec2eed25b8557eac9c80e2e198f8cdbecd86b12053
0x03676854fe24141cb98fe6d4b20d02b4516ff702350eddb0826779c813f0df45be8112f4
, ecc_n = 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307
, ecc_h = 2
})
getCurveByName SEC_t409k1 = CurveF2m $ CurveBinary
0x02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
(CurveCommon
{ ecc_a = 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
, ecc_b = 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
, ecc_g = Point 0x0060f05f658f49c1ad3ab1890f7184210efd0987e307c84c27accfb8f9f67cc2c460189eb5aaaa62ee222eb1b35540cfe9023746
0x01e369050b7c4e42acba1dacbf04299c3460782f918ea427e6325165e9ea10e3da5f6c42e9c55215aa9ca27a5863ec48d8e0286b
, ecc_n = 0x007ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf
, ecc_h = 4
})
getCurveByName SEC_t409r1 = CurveF2m $ CurveBinary
0x02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001
(CurveCommon
{ ecc_a = 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
, ecc_b = 0x0021a5c2c8ee9feb5c4b9a753b7b476b7fd6422ef1f3dd674761fa99d6ac27c8a9a197b272822f6cd57a55aa4f50ae317b13545f
, ecc_g = Point 0x015d4860d088ddb3496b0c6064756260441cde4af1771d4db01ffe5b34e59703dc255a868a1180515603aeab60794e54bb7996a7
0x0061b1cfab6be5f32bbfa78324ed106a7636b9c5a7bd198d0158aa4f5488d08f38514f1fdf4b4f40d2181b3681c364ba0273c706
, ecc_n = 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173
, ecc_h = 2
})
getCurveByName SEC_t571k1 = CurveF2m $ CurveBinary
0x080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
, ecc_b = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
, ecc_g = Point 0x026eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972
0x0349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3
, ecc_n = 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001
, ecc_h = 4
})
getCurveByName SEC_t571r1 = CurveF2m $ CurveBinary
0x080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425
(CurveCommon
{ ecc_a = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
, ecc_b = 0x02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a
, ecc_g = Point 0x0303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19
0x037bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b
, ecc_n = 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47
, ecc_h = 2
})

143
Crypto/PubKey/ElGamal.hs Normal file
View File

@ -0,0 +1,143 @@
-- |
-- Module : Crypto.PubKey.ElGamal
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
-- This module is a work in progress. do not use:
-- it might eat your dog, your data or even both.
--
-- TODO: provide a mapping between integer and ciphertext
-- generate numbers correctly
--
module Crypto.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 Control.Applicative
import Data.Maybe (fromJust)
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.Random.Types
import Crypto.PubKey.HashDescr (HashFunction)
import Crypto.PubKey.DH (PrivateNumber(..), PublicNumber(..), Params(..), SharedKey(..))
-- | 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 :: MonadRandom m => Integer -> m PrivateNumber
generatePrivate q = PrivateNumber <$> generateMax 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 :: MonadRandom m => Integer -> m EphemeralKey
generateEphemeral q = toEphemeral <$> generatePrivate 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 :: MonadRandom m => Params -> PublicNumber -> Integer -> m (Integer,Integer)
encrypt params@(Params p _) public m = (\b -> encryptWith b params public m) <$> generateEphemeral 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 :: MonadRandom m
=> Params -- ^ DH params (p,g)
-> PrivateNumber -- ^ DH private key
-> HashFunction -- ^ collision resistant hash function
-> ByteString -- ^ message to sign
-> m Signature
sign params@(Params p _) priv hashF msg = do
k <- generateMax (p-1)
case signWith k params priv hashF msg of
Nothing -> sign params priv hashF msg
Just sig -> return sig
-- | 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

102
Crypto/PubKey/HashDescr.hs Normal file
View File

@ -0,0 +1,102 @@
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module : Crypto.PubKey.HashDescr
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- 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

24
Crypto/PubKey/Internal.hs Normal file
View File

@ -0,0 +1,24 @@
-- |
-- Module : Crypto.PubKey.Internal
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- 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

View File

@ -0,0 +1,31 @@
-- |
-- Module : Crypto.PubKey.MaskGenFunction
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- 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)

109
Crypto/PubKey/RSA.hs Normal file
View File

@ -0,0 +1,109 @@
-- |
-- Module : Crypto.PubKey.RSA
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
module Crypto.PubKey.RSA
( Error(..)
, PublicKey(..)
, PrivateKey(..)
, Blinder(..)
-- * generation function
, generateWith
, generate
, generateBlinder
) where
import Data.Bits
import Data.Word
import Control.Applicative
import Crypto.Random.Types
import Crypto.Number.ModArithmetic (inverse, inverseCoprimes)
import Crypto.Number.Generate (generateMax)
import Crypto.Number.Prime (generatePrime)
import Crypto.PubKey.RSA.Types
-- some bad implementation will not serialize ASN.1 integer properly, leading
-- to negative modulus.
-- TODO : Find a better place for this
toPositive :: Integer -> Integer
toPositive int
| int < 0 = uintOfBytes $ bytesOfInt int
| otherwise = int
where uintOfBytes = foldl (\acc n -> (acc `shiftL` 8) + fromIntegral n) 0
bytesOfInt :: Integer -> [Word8]
bytesOfInt n = if testBit (head nints) 7 then nints else 0xff : nints
where nints = reverse $ plusOne $ reverse $ map complement $ bytesOfUInt (abs n)
plusOne [] = [1]
plusOne (x:xs) = if x == 0xff then 0 : plusOne xs else (x+1) : xs
bytesOfUInt x = reverse (list x)
where list i = if i <= 0xff then [fromIntegral i] else (fromIntegral i .&. 0xff) : list (i `shiftR` 8)
-- | 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 :: MonadRandom m
=> Int -- ^ size in bytes
-> Integer -- ^ RSA public exponant 'e'
-> m (PublicKey, PrivateKey)
generate size e = loop
where
loop = do -- loop until we find a valid key pair given e
pq <- generatePQ
case generateWith pq size e of
Nothing -> loop
Just pp -> return pp
generatePQ = do
p <- generatePrime (8 * (size `div` 2))
q <- generateQ p
return (p,q)
generateQ p = do
q <- generatePrime (8 * (size - (size `div` 2)))
if p == q then generateQ p else return q
-- | 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 :: MonadRandom m
=> Integer -- ^ RSA public N parameter.
-> m Blinder
generateBlinder n =
(\r -> Blinder r (inverseCoprimes r n)) <$> generateMax n

151
Crypto/PubKey/RSA/OAEP.hs Normal file
View File

@ -0,0 +1,151 @@
-- |
-- Module : Crypto.PubKey.RSA.OAEP
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
-- RSA OAEP mode
-- <http://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding>
--
{-# LANGUAGE OverloadedStrings #-}
module Crypto.PubKey.RSA.OAEP
(
OAEPParams(..)
, defaultOAEPParams
-- * OAEP encryption
, encryptWithSeed
, encrypt
-- * OAEP decryption
, decrypt
, decryptSafer
) where
import Crypto.Random.Types
import Crypto.PubKey.RSA.Types
import Crypto.PubKey.HashDescr
import Crypto.PubKey.MaskGenFunction
import Crypto.PubKey.RSA.Prim
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 :: MonadRandom m
=> OAEPParams -- ^ OAEP params to use for encryption.
-> PublicKey -- ^ Public key.
-> ByteString -- ^ Message to encrypt
-> m (Either Error ByteString)
encrypt oaep pk msg = do
seed <- getRandomBytes hashLen
return (encryptWithSeed seed oaep pk msg)
where
hashF = oaepHash oaep
hashLen = B.length (hashF B.empty)
-- | 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 :: MonadRandom m
=> OAEPParams -- ^ OAEP params to use for decryption
-> PrivateKey -- ^ Private key
-> ByteString -- ^ Cipher text
-> m (Either Error ByteString)
decryptSafer oaep pk cipher = do
blinder <- generateBlinder (private_n pk)
return (decrypt (Just blinder) oaep pk cipher)

142
Crypto/PubKey/RSA/PKCS15.hs Normal file
View File

@ -0,0 +1,142 @@
-- |
-- Module : Crypto.PubKey.RSA.PKCS15
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- 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.Types
import Crypto.PubKey.Internal (and')
import Crypto.PubKey.RSA.Types
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Crypto.PubKey.RSA.Prim
import Crypto.PubKey.RSA (generateBlinder)
import Crypto.PubKey.HashDescr
-- | This produce a standard PKCS1.5 padding for encryption
pad :: MonadRandom m => Int -> ByteString -> m (Either Error ByteString)
pad len m
| B.length m > len - 11 = return (Left MessageTooLong)
| otherwise = do
padding <- getNonNullRandom (len - B.length m - 3)
return $ Right $ B.concat [ B.singleton 0, B.singleton 2, padding, B.singleton 0, m ]
where {- get random non-null bytes -}
getNonNullRandom :: MonadRandom m => Int -> m ByteString
getNonNullRandom n = do
bs0 <- getRandomBytes n
let bytes = B.pack $ filter (/= 0) $ B.unpack $ bs0
left = n - B.length bytes
if left == 0
then return bytes
else do bend <- getNonNullRandom left
return (bytes `B.append` bend)
-- | 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 :: MonadRandom m
=> PrivateKey -- ^ RSA private key
-> ByteString -- ^ cipher text
-> m (Either Error ByteString)
decryptSafer pk b = do
blinder <- generateBlinder (private_n pk)
return (decrypt (Just blinder) pk b)
-- | encrypt a bytestring using the public key and a CPRG random generator.
--
-- the message need to be smaller than the key size - 11
encrypt :: MonadRandom m => PublicKey -> ByteString -> m (Either Error ByteString)
encrypt pk m = do
r <- pad (public_size pk) m
case r of
Left err -> return $ Left err
Right em -> return $ Right (ep pk em)
-- | 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 :: MonadRandom m
=> HashDescr -- ^ Hash descriptor
-> PrivateKey -- ^ private key
-> ByteString -- ^ message to sign
-> m (Either Error ByteString)
signSafer hashDescr pk m = do
blinder <- generateBlinder (private_n pk)
return (sign (Just blinder) hashDescr pk m)
-- | 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

135
Crypto/PubKey/RSA/PSS.hs Normal file
View File

@ -0,0 +1,135 @@
-- |
-- Module : Crypto.PubKey.RSA.PSS
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
module Crypto.PubKey.RSA.PSS
( PSSParams(..)
, defaultPSSParams
, defaultPSSParamsSHA1
-- * Sign and verify functions
, signWithSalt
, sign
, signSafer
, verify
) where
import Crypto.Random.Types
import Crypto.PubKey.RSA.Types
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 :: MonadRandom m
=> Maybe Blinder -- ^ optional blinder to use
-> PSSParams -- ^ PSS Parameters to use
-> PrivateKey -- ^ RSA Private Key
-> ByteString -- ^ Message to sign
-> m (Either Error ByteString)
sign blinder params pk m = do
salt <- getRandomBytes (pssSaltLength params)
return (signWithSalt salt blinder params pk m)
-- | Sign using the PSS Parameters and an automatically generated blinder.
signSafer :: MonadRandom m
=> PSSParams -- ^ PSS Parameters to use
-> PrivateKey -- ^ private key
-> ByteString -- ^ message to sign
-> m (Either Error ByteString)
signSafer params pk m = do
blinder <- generateBlinder (private_n pk)
sign (Just blinder) params pk m
-- | 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)

60
Crypto/PubKey/RSA/Prim.hs Normal file
View File

@ -0,0 +1,60 @@
-- |
-- Module : Crypto.PubKey.RSA.Prim
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- 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
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

View File

@ -0,0 +1,86 @@
-- |
-- Module : Crypto.PubKey.RSA.Types
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
{-# LANGUAGE DeriveDataTypeable #-}
module Crypto.PubKey.RSA.Types
( Error(..)
, Blinder(..)
, PublicKey(..)
, PrivateKey(..)
, KeyPair(..)
, private_size
, private_n
, private_e
) where
import Data.Data
import Data.Typeable
-- | 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)
-- | Represent a RSA public key
data PublicKey = PublicKey
{ public_size :: Int -- ^ size of key in bytes
, public_n :: Integer -- ^ public p*q
, public_e :: Integer -- ^ public exponant e
} deriving (Show,Read,Eq,Data,Typeable)
-- | Represent a RSA private key.
--
-- Only the pub, d fields are mandatory to fill.
--
-- p, q, dP, dQ, qinv are by-product during RSA generation,
-- but are useful to record here to speed up massively
-- the decrypt and sign operation.
--
-- implementations can leave optional fields to 0.
--
data PrivateKey = PrivateKey
{ private_pub :: PublicKey -- ^ public part of a private key (size, n and e)
, private_d :: Integer -- ^ private exponant d
, private_p :: Integer -- ^ p prime number
, private_q :: Integer -- ^ q prime number
, private_dP :: Integer -- ^ d mod (p-1)
, private_dQ :: Integer -- ^ d mod (q-1)
, private_qinv :: Integer -- ^ q^(-1) mod p
} deriving (Show,Read,Eq,Data,Typeable)
-- | get the size in bytes from a private key
private_size = public_size . private_pub
-- | get n from a private key
private_n = public_n . private_pub
-- | get e from a private key
private_e = public_e . private_pub
-- | Represent RSA KeyPair
--
-- note the RSA private key contains already an instance of public key for efficiency
newtype KeyPair = KeyPair PrivateKey
deriving (Show,Read,Eq,Data,Typeable)
-- | Public key of a RSA KeyPair
toPublicKey :: KeyPair -> PublicKey
toPublicKey (KeyPair priv) = private_pub priv
-- | Private key of a RSA KeyPair
toPrivateKey :: KeyPair -> PrivateKey
toPrivateKey (KeyPair priv) = priv

View File

@ -59,6 +59,21 @@ Library
Crypto.Hash.Tiger
Crypto.Hash.Whirlpool
Crypto.PubKey.Curve25519
Crypto.PubKey.HashDescr
Crypto.PubKey.MaskGenFunction
Crypto.PubKey.DH
Crypto.PubKey.DSA
Crypto.PubKey.ECC.Generate
Crypto.PubKey.ECC.Prim
Crypto.PubKey.ECC.DH
Crypto.PubKey.ECC.ECDSA
Crypto.PubKey.ECC.Types
Crypto.PubKey.RSA
Crypto.PubKey.RSA.PKCS15
Crypto.PubKey.RSA.Prim
Crypto.PubKey.RSA.PSS
Crypto.PubKey.RSA.OAEP
Crypto.PubKey.RSA.Types
Crypto.Random
Crypto.Random.Types
Crypto.Random.Entropy
@ -86,6 +101,8 @@ Library
Crypto.Random.Entropy.Source
Crypto.Random.Entropy.Backend
Crypto.Random.ChaChaDRG
Crypto.PubKey.Internal
Crypto.PubKey.ElGamal
Crypto.Internal.Compat
Crypto.Internal.Bytes
Crypto.Internal.ByteArray
@ -151,6 +168,7 @@ Test-Suite test-cryptonite
, tasty
, tasty-quickcheck
, tasty-hunit
, tasty-kat
, cryptonite
ghc-options: -Wall -fno-warn-orphans -fno-warn-missing-signatures
default-language: Haskell2010

46
tests/KAT_PubKey.hs Normal file
View File

@ -0,0 +1,46 @@
{-# LANGUAGE OverloadedStrings #-}
module KAT_PubKey (tests) 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_PubKey.OAEP
import KAT_PubKey.PSS
import KAT_PubKey.DSA
import KAT_PubKey.ECC
import KAT_PubKey.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"
}
]
tests = testGroup "PubKey"
[ testGroup "MGF1" $ map doMGFTest (zip [0..] vectorsMGF)
, pssTests
, oaepTests
, dsaTests
, eccTests
, ecdsaTests
]
--newKats = [ eccKatTests ]

147
tests/KAT_PubKey/DSA.hs Normal file
View File

@ -0,0 +1,147 @@
{-# LANGUAGE OverloadedStrings #-}
module KAT_PubKey.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)
]
]

145
tests/KAT_PubKey/ECC.hs Normal file
View File

@ -0,0 +1,145 @@
{-# LANGUAGE OverloadedStrings #-}
module KAT_PubKey.ECC (eccTests, eccKatTests) where
import Control.Arrow (second)
import Control.Applicative
import Data.ByteString (ByteString)
import Crypto.Number.Serialize
import qualified Crypto.PubKey.ECC.Types 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

95
tests/KAT_PubKey/ECDSA.hs Normal file
View File

@ -0,0 +1,95 @@
-- Test vectors are taken from GEC2: www.secg.org/collateral/gec2.pdf
{-# LANGUAGE OverloadedStrings #-}
module KAT_PubKey.ECDSA (ecdsaTests) where
import Data.ByteString (ByteString)
import Crypto.Number.Serialize
import qualified Crypto.PubKey.ECC.ECDSA as ECDSA
import qualified Crypto.PubKey.ECC.Types 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)
]
]

104
tests/KAT_PubKey/OAEP.hs Normal file
View File

@ -0,0 +1,104 @@
{-# LANGUAGE OverloadedStrings #-}
module KAT_PubKey.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)
]

480
tests/KAT_PubKey/PSS.hs Normal file
View File

@ -0,0 +1,480 @@
{-# LANGUAGE OverloadedStrings #-}
module KAT_PubKey.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)
]

View File

@ -19,6 +19,7 @@ import qualified KATHash
import qualified KAT_HMAC
import qualified KAT_PBKDF2
import qualified KAT_Curve25519
import qualified KAT_PubKey
import qualified KAT_Scrypt
import qualified KAT_RC4
import qualified KAT_Blowfish
@ -78,6 +79,7 @@ tests = testGroup "cryptonite"
, KATHash.tests
, KAT_HMAC.tests
, KAT_Curve25519.tests
, KAT_PubKey.tests
, KAT_PBKDF2.tests
, KAT_Scrypt.tests
, KAT_RC4.tests