packages feed

cryptonite 0.20 → 0.21

raw patch · 24 files changed

+1563/−42 lines, 24 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Crypto.Cipher.Salsa: data State
+ Crypto.Cipher.Salsa: State :: ScrubbedBytes -> State
+ Crypto.Cipher.Salsa: newtype State
+ Crypto.Cipher.XSalsa: combine :: ByteArray ba => State -> ba -> (ba, State)
+ Crypto.Cipher.XSalsa: data State
+ Crypto.Cipher.XSalsa: generate :: ByteArray ba => State -> Int -> (ba, State)
+ Crypto.Cipher.XSalsa: initialize :: (ByteArrayAccess key, ByteArrayAccess nonce) => Int -> key -> nonce -> State
+ Crypto.ECC: Curve_P256R1 :: Curve_P256R1
+ Crypto.ECC: Curve_P384R1 :: Curve_P384R1
+ Crypto.ECC: Curve_P521R1 :: Curve_P521R1
+ Crypto.ECC: Curve_X25519 :: Curve_X25519
+ Crypto.ECC: Curve_X448 :: Curve_X448
+ Crypto.ECC: KeyPair :: !(Point curve) -> !(Scalar curve) -> KeyPair curve
+ Crypto.ECC: SharedSecret :: ScrubbedBytes -> SharedSecret
+ Crypto.ECC: [keypairGetPrivate] :: KeyPair curve -> !(Scalar curve)
+ Crypto.ECC: [keypairGetPublic] :: KeyPair curve -> !(Point curve)
+ Crypto.ECC: class EllipticCurve curve where type Point curve :: * type Scalar curve :: * where {
+ Crypto.ECC: class EllipticCurve curve => EllipticCurveArith curve
+ Crypto.ECC: class EllipticCurve curve => EllipticCurveDH curve
+ Crypto.ECC: curveGenerateKeyPair :: (EllipticCurve curve, MonadRandom randomly) => proxy curve -> randomly (KeyPair curve)
+ Crypto.ECC: curveGenerateScalar :: (EllipticCurve curve, MonadRandom randomly) => proxy curve -> randomly (Scalar curve)
+ Crypto.ECC: curveSizeBits :: EllipticCurve curve => proxy curve -> Int
+ Crypto.ECC: data Curve_P256R1
+ Crypto.ECC: data Curve_P384R1
+ Crypto.ECC: data Curve_P521R1
+ Crypto.ECC: data Curve_X25519
+ Crypto.ECC: data Curve_X448
+ Crypto.ECC: data KeyPair curve
+ Crypto.ECC: decodePoint :: (EllipticCurve curve, ByteArray bs) => proxy curve -> bs -> CryptoFailable (Point curve)
+ Crypto.ECC: ecdh :: EllipticCurveDH curve => proxy curve -> Scalar curve -> Point curve -> SharedSecret
+ Crypto.ECC: encodePoint :: (EllipticCurve curve, ByteArray bs) => proxy curve -> Point curve -> bs
+ Crypto.ECC: instance Crypto.ECC.EllipticCurve Crypto.ECC.Curve_P256R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurve Crypto.ECC.Curve_P384R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurve Crypto.ECC.Curve_P521R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurve Crypto.ECC.Curve_X25519
+ Crypto.ECC: instance Crypto.ECC.EllipticCurve Crypto.ECC.Curve_X448
+ Crypto.ECC: instance Crypto.ECC.EllipticCurveArith Crypto.ECC.Curve_P256R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurveArith Crypto.ECC.Curve_P384R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurveArith Crypto.ECC.Curve_P521R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurveDH Crypto.ECC.Curve_P256R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurveDH Crypto.ECC.Curve_P384R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurveDH Crypto.ECC.Curve_P521R1
+ Crypto.ECC: instance Crypto.ECC.EllipticCurveDH Crypto.ECC.Curve_X25519
+ Crypto.ECC: instance Crypto.ECC.EllipticCurveDH Crypto.ECC.Curve_X448
+ Crypto.ECC: instance Data.ByteArray.Types.ByteArrayAccess Crypto.ECC.SharedSecret
+ Crypto.ECC: instance GHC.Classes.Eq Crypto.ECC.SharedSecret
+ Crypto.ECC: newtype SharedSecret
+ Crypto.ECC: pointAdd :: EllipticCurveArith curve => proxy curve -> Point curve -> Point curve -> Point curve
+ Crypto.ECC: pointSmul :: EllipticCurveArith curve => proxy curve -> Scalar curve -> Point curve -> Point curve
+ Crypto.ECC: type family Scalar curve :: *;
+ Crypto.ECC: }
+ Crypto.Error: CryptoError_EcScalarOutOfBounds :: CryptoError
+ Crypto.Error: CryptoError_PointCoordinatesInvalid :: CryptoError
+ Crypto.Error: CryptoError_PointFormatInvalid :: CryptoError
+ Crypto.Error: CryptoError_PointFormatUnsupported :: CryptoError
+ Crypto.Error: CryptoError_PointSizeInvalid :: CryptoError
+ Crypto.KDF.HKDF: instance Data.ByteArray.Types.ByteArrayAccess (Crypto.KDF.HKDF.PRK a)
+ Crypto.PubKey.Curve25519: generateSecretKey :: MonadRandom m => m SecretKey
+ Crypto.PubKey.ECC.P256: instance GHC.Show.Show Crypto.PubKey.ECC.P256.Scalar
+ Crypto.PubKey.ECC.P256: pointDh :: ByteArray binary => Scalar -> Point -> binary
+ Crypto.PubKey.ECIES: deriveDecrypt :: EllipticCurveDH curve => proxy curve -> Point curve -> Scalar curve -> SharedSecret
+ Crypto.PubKey.ECIES: deriveEncrypt :: (MonadRandom randomly, EllipticCurveDH curve) => proxy curve -> Point curve -> randomly (Point curve, SharedSecret)
+ Crypto.PubKey.Ed448: generateSecretKey :: MonadRandom m => m SecretKey
- Crypto.KDF.HKDF: extractSkip :: (HashAlgorithm a, ByteArrayAccess ikm) => ikm -> PRK a
+ Crypto.KDF.HKDF: extractSkip :: ByteArrayAccess ikm => ikm -> PRK a

Files

Crypto/Cipher/AES.hs view
@@ -18,6 +18,8 @@ import Crypto.Cipher.AES.Primitive import Crypto.Internal.Imports +import Data.ByteArray as BA+ -- | AES with 128 bit key newtype AES128 = AES128 AES     deriving (NFData)@@ -33,17 +35,27 @@ instance Cipher AES128 where     cipherName    _ = "AES128"     cipherKeySize _ = KeySizeFixed 16-    cipherInit k    = AES128 `fmap` initAES k+    cipherInit k    = AES128 <$> (initAES =<< validateKeySize (undefined :: AES128) k)  instance Cipher AES192 where     cipherName    _ = "AES192"     cipherKeySize _ = KeySizeFixed 24-    cipherInit k    = AES192 `fmap` initAES k+    cipherInit k    = AES192 <$> (initAES =<< validateKeySize (undefined :: AES192) k)  instance Cipher AES256 where     cipherName    _ = "AES256"     cipherKeySize _ = KeySizeFixed 32-    cipherInit k    = AES256 `fmap` initAES k+    cipherInit k    = AES256 <$> (initAES =<< validateKeySize (undefined :: AES256) k)++validateKeySize :: (ByteArrayAccess key, Cipher cipher) => cipher -> key -> CryptoFailable key+validateKeySize c k = if validKeyLength+                      then CryptoPassed k+                      else CryptoFailed CryptoError_KeySizeInvalid+  where keyLength = BA.length k+        validKeyLength = case cipherKeySize c of+          KeySizeRange low high -> keyLength >= low && keyLength <= high+          KeySizeEnum lengths -> keyLength `elem` lengths+          KeySizeFixed s -> keyLength == s  #define INSTANCE_BLOCKCIPHER(CSTR) \ instance BlockCipher CSTR where \
Crypto/Cipher/Salsa.hs view
@@ -11,7 +11,7 @@     ( initialize     , combine     , generate-    , State+    , State(..)     ) where  import           Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, ScrubbedBytes)
+ Crypto/Cipher/XSalsa.hs view
@@ -0,0 +1,50 @@+-- |+-- Module      : Crypto.Cipher.XSalsa+-- License     : BSD-style+-- Maintainer  : Brandon Hamilton <brandon.hamilton@gmail.com>+-- Stability   : stable+-- Portability : good+--+-- Implementation of XSalsa20 algorithm+-- <https://cr.yp.to/snuffle/xsalsa-20081128.pdf>+-- Based on the Salsa20 algorithm with 256 bit key extended with 192 bit nonce++{-# LANGUAGE ForeignFunctionInterface #-}+module Crypto.Cipher.XSalsa+    ( initialize+    , combine+    , generate+    , State+    ) where++import           Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, ScrubbedBytes)+import qualified Crypto.Internal.ByteArray as B+import           Crypto.Internal.Compat+import           Crypto.Internal.Imports+import           Foreign.Ptr+import           Foreign.Storable+import           Foreign.C.Types+import           Crypto.Cipher.Salsa hiding (initialize)++-- | Initialize a new XSalsa context with the number of rounds,+-- the key and the nonce associated.+initialize :: (ByteArrayAccess key, ByteArrayAccess nonce)+           => Int    -- ^ number of rounds (8,12,20)+           -> key    -- ^ the key (256 bits)+           -> nonce  -- ^ the nonce (192 bits)+           -> State  -- ^ the initial XSalsa state+initialize nbRounds key nonce+    | kLen /= 32                      = error "XSalsa: key length should be 256 bits"+    | nonceLen /= 24                  = error "XSalsa: nonce length should be 192 bits"+    | not (nbRounds `elem` [8,12,20]) = error "XSalsa: rounds should be 8, 12 or 20"+    | otherwise = unsafeDoIO $ do+        stPtr <- B.alloc 132 $ \stPtr ->+            B.withByteArray nonce $ \noncePtr  ->+            B.withByteArray key   $ \keyPtr ->+                ccryptonite_xsalsa_init stPtr (fromIntegral nbRounds) kLen keyPtr nonceLen noncePtr+        return $ State stPtr+  where kLen     = B.length key+        nonceLen = B.length nonce++foreign import ccall "cryptonite_xsalsa_init"+    ccryptonite_xsalsa_init :: Ptr State -> Int -> Int -> Ptr Word8 -> Int -> Ptr Word8 -> IO ()
+ Crypto/ECC.hs view
@@ -0,0 +1,229 @@+-- |+-- Module      : Crypto.ECC+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : unknown+--+-- Elliptic Curve Cryptography+--+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Crypto.ECC+    ( Curve_P256R1(..)+    , Curve_P384R1(..)+    , Curve_P521R1(..)+    , Curve_X25519(..)+    , Curve_X448(..)+    , EllipticCurve(..)+    , EllipticCurveDH(..)+    , EllipticCurveArith(..)+    , KeyPair(..)+    , SharedSecret(..)+    ) where++import qualified Crypto.PubKey.ECC.P256 as P256+import qualified Crypto.ECC.Simple.Types as Simple+import qualified Crypto.ECC.Simple.Prim as Simple+import           Crypto.Random+import           Crypto.Error+import           Crypto.Internal.Proxy+import           Crypto.Internal.Imports+import           Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, ScrubbedBytes)+import qualified Crypto.Internal.ByteArray as B+import           Crypto.Number.Serialize (i2ospOf_, os2ip)+import qualified Crypto.PubKey.Curve25519 as X25519+import qualified Crypto.PubKey.Ed448 as X448+import           Data.Function (on)+import           Data.ByteArray (convert)++-- | An elliptic curve key pair composed of the private part (a scalar), and+-- the associated point.+data KeyPair curve = KeyPair+    { keypairGetPublic  :: !(Point curve)+    , keypairGetPrivate :: !(Scalar curve)+    }++newtype SharedSecret = SharedSecret ScrubbedBytes+    deriving (Eq, ByteArrayAccess)++class EllipticCurve curve where+    -- | Point on an Elliptic Curve+    type Point curve  :: *++    -- | Scalar in the Elliptic Curve domain+    type Scalar curve :: *++    -- | Generate a new random scalar on the curve.+    -- The scalar will represent a number between 1 and the order of the curve non included+    curveGenerateScalar :: MonadRandom randomly => proxy curve -> randomly (Scalar curve)++    -- | Generate a new random keypair+    curveGenerateKeyPair :: MonadRandom randomly => proxy curve -> randomly (KeyPair curve)++    -- | Get the curve size in bits+    curveSizeBits :: proxy curve -> Int++    -- | Encode a elliptic curve point into binary form+    encodePoint :: ByteArray bs => proxy curve -> Point curve -> bs++    -- | Try to decode the binary form of an elliptic curve point+    decodePoint :: ByteArray bs => proxy curve -> bs -> CryptoFailable (Point curve)++class EllipticCurve curve => EllipticCurveDH curve where+    -- | Generate a Diffie hellman secret value.+    --+    -- This is generally just the .x coordinate of the resulting point, that+    -- is not hashed.+    --+    -- use `pointSmul` to keep the result in Point format.+    ecdh :: proxy curve -> Scalar curve -> Point curve -> SharedSecret++class EllipticCurve curve => EllipticCurveArith curve where+    -- | Add points on a curve+    pointAdd :: proxy curve -> Point curve -> Point curve -> Point curve++    -- | Scalar Multiplication on a curve+    pointSmul :: proxy curve -> Scalar curve -> Point curve -> Point curve++--   -- | Scalar Inverse+--   scalarInverse :: Scalar curve -> Scalar curve++-- | P256 Curve+--+-- also known as P256+data Curve_P256R1 = Curve_P256R1++instance EllipticCurve Curve_P256R1 where+    type Point Curve_P256R1 = P256.Point+    type Scalar Curve_P256R1 = P256.Scalar+    curveSizeBits _ = 256+    curveGenerateScalar _ = P256.scalarGenerate+    curveGenerateKeyPair _ = toKeyPair <$> P256.scalarGenerate+      where toKeyPair scalar = KeyPair (P256.toPoint scalar) scalar+    encodePoint _ p = mxy+      where+        mxy :: forall bs. ByteArray bs => bs+        mxy = B.concat [uncompressed, xy]+          where+            uncompressed, xy :: bs+            uncompressed = B.singleton 4+            xy = P256.pointToBinary p+    decodePoint _ mxy = case B.uncons mxy of+        Nothing -> CryptoFailed $ CryptoError_PointSizeInvalid+        Just (m,xy)+            -- uncompressed+            | m == 4 -> P256.pointFromBinary xy+            | otherwise -> CryptoFailed $ CryptoError_PointFormatInvalid++instance EllipticCurveArith Curve_P256R1 where+    pointAdd  _ a b = P256.pointAdd a b+    pointSmul _ s p = P256.pointMul s p++instance EllipticCurveDH Curve_P256R1 where+    ecdh _ s p = SharedSecret $ P256.pointDh s p++data Curve_P384R1 = Curve_P384R1++instance EllipticCurve Curve_P384R1 where+    type Point Curve_P384R1 = Simple.Point Simple.SEC_p384r1+    type Scalar Curve_P384R1 = Simple.Scalar Simple.SEC_p384r1+    curveSizeBits _ = 384+    curveGenerateScalar _ = Simple.scalarGenerate+    curveGenerateKeyPair _ = toKeyPair <$> Simple.scalarGenerate+      where toKeyPair scalar = KeyPair (Simple.pointBaseMul scalar) scalar+    encodePoint _ point = encodeECPoint point+    decodePoint _ bs = decodeECPoint bs++instance EllipticCurveArith Curve_P384R1 where+    pointAdd _ a b = Simple.pointAdd a b+    pointSmul _ s p = Simple.pointMul s p++instance EllipticCurveDH Curve_P384R1 where+    ecdh _ s p = SharedSecret $ i2ospOf_ (curveSizeBytes prx) x+      where+        prx = Proxy :: Proxy Curve_P384R1+        Simple.Point x _ = pointSmul prx s p++data Curve_P521R1 = Curve_P521R1++instance EllipticCurve Curve_P521R1 where+    type Point Curve_P521R1 = Simple.Point Simple.SEC_p521r1+    type Scalar Curve_P521R1 = Simple.Scalar Simple.SEC_p521r1+    curveSizeBits _ = 521+    curveGenerateScalar _ = Simple.scalarGenerate+    curveGenerateKeyPair _ = toKeyPair <$> Simple.scalarGenerate+      where toKeyPair scalar = KeyPair (Simple.pointBaseMul scalar) scalar+    encodePoint _ point = encodeECPoint point+    decodePoint _ bs = decodeECPoint bs++instance EllipticCurveArith Curve_P521R1 where+    pointAdd _ a b = Simple.pointAdd a b+    pointSmul _ s p = Simple.pointMul s p++instance EllipticCurveDH Curve_P521R1 where+    ecdh _ s p = SharedSecret $ i2ospOf_ (curveSizeBytes prx) x+      where+        prx = Proxy :: Proxy Curve_P521R1+        Simple.Point x _ = pointSmul prx s p++data Curve_X25519 = Curve_X25519++instance EllipticCurve Curve_X25519 where+    type Point Curve_X25519 = X25519.PublicKey+    type Scalar Curve_X25519 = X25519.SecretKey+    curveSizeBits _ = 255+    curveGenerateScalar _ = X25519.generateSecretKey+    curveGenerateKeyPair _ = do+        s <- X25519.generateSecretKey+        return $ KeyPair (X25519.toPublic s) s+    encodePoint _ p = B.convert p+    decodePoint _ bs = X25519.publicKey bs++instance EllipticCurveDH Curve_X25519 where+    ecdh _ s p = SharedSecret $ convert secret+      where secret = X25519.dh p s++data Curve_X448 = Curve_X448++instance EllipticCurve Curve_X448 where+    type Point Curve_X448 = X448.PublicKey+    type Scalar Curve_X448 = X448.SecretKey+    curveSizeBits _ = 448+    curveGenerateScalar _ = X448.generateSecretKey+    curveGenerateKeyPair _ = do+        s <- X448.generateSecretKey+        return $ KeyPair (X448.toPublic s) s+    encodePoint _ p = B.convert p+    decodePoint _ bs = X448.publicKey bs++instance EllipticCurveDH Curve_X448 where+    ecdh _ s p = SharedSecret $ convert secret+      where secret = X448.dh p s++encodeECPoint :: forall curve bs . (Simple.Curve curve, ByteArray bs) => Simple.Point curve -> bs+encodeECPoint Simple.PointO      = error "encodeECPoint: cannot serialize point at infinity"+encodeECPoint (Simple.Point x y) = B.concat [uncompressed,xb,yb]+  where+    size = Simple.curveSizeBytes (Proxy :: Proxy curve)+    uncompressed, xb, yb :: bs+    uncompressed = B.singleton 4+    xb = i2ospOf_ size x+    yb = i2ospOf_ size y++decodeECPoint :: (Simple.Curve curve, ByteArray bs) => bs -> CryptoFailable (Simple.Point curve)+decodeECPoint mxy = case B.uncons mxy of+    Nothing     -> CryptoFailed $ CryptoError_PointSizeInvalid+    Just (m,xy)+        -- uncompressed+        | m == 4 ->+            let siz = B.length xy `div` 2+                (xb,yb) = B.splitAt siz xy+                x = os2ip xb+                y = os2ip yb+             in Simple.pointFromIntegers (x,y)+        | otherwise -> CryptoFailed $ CryptoError_PointFormatInvalid++curveSizeBytes :: EllipticCurve c => Proxy c -> Int+curveSizeBytes proxy = (curveSizeBits proxy + 7) `div` 8
+ Crypto/ECC/Simple/Prim.hs view
@@ -0,0 +1,207 @@+-- | Elliptic Curve Arithmetic.+--+-- /WARNING:/ These functions are vulnerable to timing attacks.+{-# LANGUAGE ScopedTypeVariables #-}+module Crypto.ECC.Simple.Prim+    ( scalarGenerate+    , scalarFromInteger+    , pointAdd+    , pointDouble+    , pointBaseMul+    , pointMul+    , pointAddTwoMuls+    , pointFromIntegers+    , isPointAtInfinity+    , isPointValid+    ) where++import Data.Maybe+import Crypto.Internal.Imports+import Crypto.Internal.Proxy+import Crypto.Number.ModArithmetic+import Crypto.Number.F2m+import Crypto.Number.Generate (generateBetween)+import Crypto.ECC.Simple.Types+import Crypto.Error+import Crypto.Random++-- | Generate a valid scalar for a specific Curve+scalarGenerate :: forall randomly curve . (MonadRandom randomly, Curve curve) => randomly (Scalar curve)+scalarGenerate =+    Scalar <$> generateBetween 1 (n - 1)+  where+    n = curveEccN $ curveParameters (Proxy :: Proxy curve)++scalarFromInteger :: forall curve . Curve curve => Integer -> CryptoFailable (Scalar curve)+scalarFromInteger n+    | n < 0  || n >= mx = CryptoFailed $ CryptoError_EcScalarOutOfBounds+    | otherwise         = CryptoPassed $ Scalar n+  where+    mx = case curveType (Proxy :: Proxy curve) of+            CurveBinary (CurveBinaryParam b) -> b+            CurvePrime (CurvePrimeParam p)   -> p++--TODO: Extract helper function for `fromMaybe PointO...`++-- | Elliptic Curve point negation:+-- @pointNegate p@ returns point @q@ such that @pointAdd p q == PointO@.+pointNegate :: Curve curve => Point curve -> Point curve+pointNegate        PointO     = PointO+pointNegate point@(Point x y) =+    case curveType point of+        CurvePrime {}  -> Point x (-y)+        CurveBinary {} -> Point x (x `addF2m` y)++-- | Elliptic Curve point addition.+--+-- /WARNING:/ Vulnerable to timing attacks.+pointAdd :: Curve curve => Point curve -> Point curve -> Point curve+pointAdd PointO PointO = PointO+pointAdd PointO q = q+pointAdd p PointO = p+pointAdd p q+  | p == q             = pointDouble p+  | p == pointNegate q = PointO+pointAdd point@(Point xp yp) (Point xq yq) =+    case ty of+        CurvePrime (CurvePrimeParam pr) -> 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+        CurveBinary (CurveBinaryParam fx) -> 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+    ty = curveType point+    cc = curveParameters point+    a  = curveEccA 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 curve => Point curve -> Point curve+pointDouble PointO = PointO+pointDouble point@(Point xp yp) =+    case ty of+        CurvePrime (CurvePrimeParam pr) -> 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+        CurveBinary (CurveBinaryParam fx)+            | 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+    ty = curveType point+    cc = curveParameters point+    a  = curveEccA cc++-- | Elliptic curve point multiplication using the base+--+-- /WARNING:/ Vulnerable to timing attacks.+pointBaseMul :: Curve curve => Scalar curve -> Point curve+pointBaseMul n = pointMul n (curveEccG $ curveParameters (Proxy :: Proxy curve))++-- | Elliptic curve point multiplication (double and add algorithm).+--+-- /WARNING:/ Vulnerable to timing attacks.+pointMul :: Curve curve => Scalar curve -> Point curve -> Point curve+pointMul _ PointO = PointO+pointMul (Scalar n) p+    | n == 0    = PointO+    | n == 1    = p+    | odd n     = pointAdd p (pointMul (Scalar (n - 1)) p)+    | otherwise = pointMul (Scalar (n `div` 2)) (pointDouble p)++-- | Elliptic curve double-scalar multiplication (uses Shamir's trick).+--+-- > pointAddTwoMuls n1 p1 n2 p2 == pointAdd (pointMul n1 p1)+-- >                                         (pointMul n2 p2)+--+-- /WARNING:/ Vulnerable to timing attacks.+pointAddTwoMuls :: Curve curve => Scalar curve -> Point curve -> Scalar curve -> Point curve -> Point curve+pointAddTwoMuls _  PointO _  PointO = PointO+pointAddTwoMuls _  PointO n2 p2     = pointMul n2 p2+pointAddTwoMuls n1 p1     _  PointO = pointMul n1 p1+pointAddTwoMuls (Scalar n1) p1 (Scalar n2) p2 = go (n1, n2)+  where+    p0 = pointAdd p1 p2++    go (0,  0 ) = PointO+    go (k1, k2) =+        let q = pointDouble $ go (k1 `div` 2, k2 `div` 2)+        in case (odd k1, odd k2) of+            (True  , True  ) -> pointAdd p0 q+            (True  , False ) -> pointAdd p1 q+            (False , True  ) -> pointAdd p2 q+            (False , False ) -> q++-- | Check if a point is the point at infinity.+isPointAtInfinity :: Point curve -> Bool+isPointAtInfinity PointO = True+isPointAtInfinity _      = False++-- | Make a point on a curve from integer (x,y) coordinate+--+-- if the point is not valid related to the curve then an error is+-- returned instead of a point+pointFromIntegers :: forall curve . Curve curve => (Integer, Integer) -> CryptoFailable (Point curve)+pointFromIntegers (x,y)+    | isPointValid (Proxy :: Proxy curve) x y = CryptoPassed $ Point x y+    | otherwise                               = CryptoFailed $ CryptoError_PointCoordinatesInvalid++-- | 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 curve => proxy curve -> Integer -> Integer -> Bool+isPointValid proxy x y =+    case ty of+        CurvePrime (CurvePrimeParam p) ->+            let a  = curveEccA cc+                b  = curveEccB cc+                eqModP z1 z2 = (z1 `mod` p) == (z2 `mod` p)+                isValid e = e >= 0 && e < p+             in isValid x && isValid y && (y ^ (2 :: Int)) `eqModP` (x ^ (3 :: Int) + a * x + b)+        CurveBinary (CurveBinaryParam fx) ->+            let a  = curveEccA cc+                b  = curveEccB cc+                add = addF2m+                mul = mulF2m fx+                isValid e = modF2m fx e == e+             in and [ isValid x+                    , isValid y+                    , ((((x `add` a) `mul` x `add` y) `mul` x) `add` b `add` (squareF2m fx y)) == 0+                    ]+  where+    ty = curveType proxy+    cc = curveParameters proxy++-- | div and mod+divmod :: Integer -> Integer -> Integer -> Maybe Integer+divmod y x m = do+    i <- inverse (x `mod` m) m+    return $ y * i `mod` m
+ Crypto/ECC/Simple/Types.hs view
@@ -0,0 +1,615 @@+{-# LANGUAGE DeriveDataTypeable #-}+-- |+-- Module      : Crypto.ECC.Simple.Types+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : Experimental+-- Portability : Excellent+--+-- references:+--   <https://tools.ietf.org/html/rfc5915>+--+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}+module Crypto.ECC.Simple.Types+    ( Curve(..)+    , Point(..)+    , Scalar(..)+    , CurveType(..)+    , CurveBinaryParam(..)+    , CurvePrimeParam(..)+    , curveSizeBits+    , curveSizeBytes+    , CurveParameters(..)+    -- * specific curves definition+    , 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(..)+    ) where++import           Data.Data+import           Crypto.Internal.Imports+import           Crypto.Number.Basic (numBits)++class Curve curve where+    curveParameters :: proxy curve -> CurveParameters curve+    curveType :: proxy curve -> CurveType++-- | get the size of the curve in bits+curveSizeBits :: Curve curve => proxy curve -> Int+curveSizeBits proxy =+    case curveType proxy of+        CurvePrime (CurvePrimeParam p)   -> numBits p+        CurveBinary (CurveBinaryParam c) -> numBits c - 1++-- | get the size of the curve in bytes+curveSizeBytes :: Curve curve => proxy curve -> Int+curveSizeBytes proxy = (curveSizeBits proxy + 7) `div` 8++-- | Define common parameters in a curve definition+-- of the form: y^2 = x^3 + ax + b.+data CurveParameters curve = CurveParameters+    { curveEccA :: Integer     -- ^ curve parameter a+    , curveEccB :: Integer     -- ^ curve parameter b+    , curveEccG :: Point curve -- ^ base point+    , curveEccN :: Integer     -- ^ order of G+    , curveEccH :: Integer     -- ^ cofactor+    } deriving (Show,Eq,Data,Typeable)++newtype CurveBinaryParam = CurveBinaryParam Integer+    deriving (Show,Read,Eq,Data,Typeable)++newtype CurvePrimeParam = CurvePrimeParam Integer+    deriving (Show,Read,Eq,Data,Typeable)++data CurveType =+      CurveBinary CurveBinaryParam+    | CurvePrime CurvePrimeParam+    deriving (Show,Read,Eq,Data,Typeable)++-- | ECC Private Number+newtype Scalar curve = Scalar Integer+    deriving (Show,Read,Eq,Data,Typeable)++-- | Define a point on a curve.+data Point curve =+      Point Integer Integer+    | PointO -- ^ Point at Infinity+    deriving (Show,Read,Eq,Data,Typeable)++instance NFData (Point curve) where+    rnf (Point x y) = x `seq` y `seq` ()+    rnf PointO = ()++data SEC_p112r1 = SEC_p112r1 deriving (Show,Read,Eq)+data SEC_p112r2 = SEC_p112r2 deriving (Show,Read,Eq)+data SEC_p128r1 = SEC_p128r1 deriving (Show,Read,Eq)+data SEC_p128r2 = SEC_p128r2 deriving (Show,Read,Eq)+data SEC_p160k1 = SEC_p160k1 deriving (Show,Read,Eq)+data SEC_p160r1 = SEC_p160r1 deriving (Show,Read,Eq)+data SEC_p160r2 = SEC_p160r2 deriving (Show,Read,Eq)+data SEC_p192k1 = SEC_p192k1 deriving (Show,Read,Eq)+data SEC_p192r1 = SEC_p192r1 deriving (Show,Read,Eq)+data SEC_p224k1 = SEC_p224k1 deriving (Show,Read,Eq)+data SEC_p224r1 = SEC_p224r1 deriving (Show,Read,Eq)+data SEC_p256k1 = SEC_p256k1 deriving (Show,Read,Eq)+data SEC_p256r1 = SEC_p256r1 deriving (Show,Read,Eq)+data SEC_p384r1 = SEC_p384r1 deriving (Show,Read,Eq)+data SEC_p521r1 = SEC_p521r1 deriving (Show,Read,Eq)+data SEC_t113r1 = SEC_t113r1 deriving (Show,Read,Eq)+data SEC_t113r2 = SEC_t113r2 deriving (Show,Read,Eq)+data SEC_t131r1 = SEC_t131r1 deriving (Show,Read,Eq)+data SEC_t131r2 = SEC_t131r2 deriving (Show,Read,Eq)+data SEC_t163k1 = SEC_t163k1 deriving (Show,Read,Eq)+data SEC_t163r1 = SEC_t163r1 deriving (Show,Read,Eq)+data SEC_t163r2 = SEC_t163r2 deriving (Show,Read,Eq)+data SEC_t193r1 = SEC_t193r1 deriving (Show,Read,Eq)+data SEC_t193r2 = SEC_t193r2 deriving (Show,Read,Eq)+data SEC_t233k1 = SEC_t233k1 deriving (Show,Read,Eq)+data SEC_t233r1 = SEC_t233r1 deriving (Show,Read,Eq)+data SEC_t239k1 = SEC_t239k1 deriving (Show,Read,Eq)+data SEC_t283k1 = SEC_t283k1 deriving (Show,Read,Eq)+data SEC_t283r1 = SEC_t283r1 deriving (Show,Read,Eq)+data SEC_t409k1 = SEC_t409k1 deriving (Show,Read,Eq)+data SEC_t409r1 = SEC_t409r1 deriving (Show,Read,Eq)+data SEC_t571k1 = SEC_t571k1 deriving (Show,Read,Eq)+data SEC_t571r1 = SEC_t571r1 deriving (Show,Read,Eq)++-- | Define names for known recommended curves.+instance Curve SEC_p112r1 where+    curveType _ = typeSEC_p112r1+    curveParameters _ = paramSEC_p112r1++instance Curve SEC_p112r2 where+    curveType _ = typeSEC_p112r2+    curveParameters _ = paramSEC_p112r2++instance Curve SEC_p128r1 where+    curveType _ = typeSEC_p128r1+    curveParameters _ = paramSEC_p128r1++instance Curve SEC_p128r2 where+    curveType _ = typeSEC_p128r2+    curveParameters _ = paramSEC_p128r2++instance Curve SEC_p160k1 where+    curveType _ = typeSEC_p160k1+    curveParameters _ = paramSEC_p160k1++instance Curve SEC_p160r1 where+    curveType _ = typeSEC_p160r1+    curveParameters _ = paramSEC_p160r1++instance Curve SEC_p160r2 where+    curveType _ = typeSEC_p160r2+    curveParameters _ = paramSEC_p160r2++instance Curve SEC_p192k1 where+    curveType _ = typeSEC_p192k1+    curveParameters _ = paramSEC_p192k1++instance Curve SEC_p192r1 where+    curveType _ = typeSEC_p192r1+    curveParameters _ = paramSEC_p192r1++instance Curve SEC_p224k1 where+    curveType _ = typeSEC_p224k1+    curveParameters _ = paramSEC_p224k1++instance Curve SEC_p224r1 where+    curveType _ = typeSEC_p224r1+    curveParameters _ = paramSEC_p224r1++instance Curve SEC_p256k1 where+    curveType _ = typeSEC_p256k1+    curveParameters _ = paramSEC_p256k1++instance Curve SEC_p256r1 where+    curveType _ = typeSEC_p256r1+    curveParameters _ = paramSEC_p256r1++instance Curve SEC_p384r1 where+    curveType _ = typeSEC_p384r1+    curveParameters _ = paramSEC_p384r1++instance Curve SEC_p521r1 where+    curveType _ = typeSEC_p521r1+    curveParameters _ = paramSEC_p521r1++instance Curve SEC_t113r1 where+    curveType _ = typeSEC_t113r1+    curveParameters _ = paramSEC_t113r1++instance Curve SEC_t113r2 where+    curveType _ = typeSEC_t113r2+    curveParameters _ = paramSEC_t113r2++instance Curve SEC_t131r1 where+    curveType _ = typeSEC_t131r1+    curveParameters _ = paramSEC_t131r1++instance Curve SEC_t131r2 where+    curveType _ = typeSEC_t131r2+    curveParameters _ = paramSEC_t131r2++instance Curve SEC_t163k1 where+    curveType _ = typeSEC_t163k1+    curveParameters _ = paramSEC_t163k1++instance Curve SEC_t163r1 where+    curveType _ = typeSEC_t163r1+    curveParameters _ = paramSEC_t163r1++instance Curve SEC_t163r2 where+    curveType _ = typeSEC_t163r2+    curveParameters _ = paramSEC_t163r2++instance Curve SEC_t193r1 where+    curveType _ = typeSEC_t193r1+    curveParameters _ = paramSEC_t193r1++instance Curve SEC_t193r2 where+    curveType _ = typeSEC_t193r2+    curveParameters _ = paramSEC_t193r2++instance Curve SEC_t233k1 where+    curveType _ = typeSEC_t233k1+    curveParameters _ = paramSEC_t233k1++instance Curve SEC_t233r1 where+    curveType _ = typeSEC_t233r1+    curveParameters _ = paramSEC_t233r1++instance Curve SEC_t239k1 where+    curveType _ = typeSEC_t239k1+    curveParameters _ = paramSEC_t239k1++instance Curve SEC_t283k1 where+    curveType _ = typeSEC_t283k1+    curveParameters _ = paramSEC_t283k1++instance Curve SEC_t283r1 where+    curveType _ = typeSEC_t283r1+    curveParameters _ = paramSEC_t283r1++instance Curve SEC_t409k1 where+    curveType _ = typeSEC_t409k1+    curveParameters _ = paramSEC_t409k1++instance Curve SEC_t409r1 where+    curveType _ = typeSEC_t409r1+    curveParameters _ = paramSEC_t409r1++instance Curve SEC_t571k1 where+    curveType _ = typeSEC_t571k1+    curveParameters _ = paramSEC_t571k1++instance Curve SEC_t571r1 where+    curveType _ = typeSEC_t571r1+    curveParameters _ = paramSEC_t571r1++{-+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])+    ]+-}++typeSEC_p112r1 = CurvePrime $ CurvePrimeParam 0xdb7c2abf62e35e668076bead208b+paramSEC_p112r1 = CurveParameters+    { curveEccA = 0xdb7c2abf62e35e668076bead2088+    , curveEccB = 0x659ef8ba043916eede8911702b22+    , curveEccG = Point 0x09487239995a5ee76b55f9c2f098+                    0xa89ce5af8724c0a23e0e0ff77500+    , curveEccN = 0xdb7c2abf62e35e7628dfac6561c5+    , curveEccH = 1+    }+typeSEC_p112r2 = CurvePrime $ CurvePrimeParam 0xdb7c2abf62e35e668076bead208b+paramSEC_p112r2 = CurveParameters+    { curveEccA = 0x6127c24c05f38a0aaaf65c0ef02c+    , curveEccB = 0x51def1815db5ed74fcc34c85d709+    , curveEccG = Point 0x4ba30ab5e892b4e1649dd0928643+                    0xadcd46f5882e3747def36e956e97+    , curveEccN = 0x36df0aafd8b8d7597ca10520d04b+    , curveEccH = 4+    }+typeSEC_p128r1 = CurvePrime $ CurvePrimeParam 0xfffffffdffffffffffffffffffffffff+paramSEC_p128r1 = CurveParameters+    { curveEccA = 0xfffffffdfffffffffffffffffffffffc+    , curveEccB = 0xe87579c11079f43dd824993c2cee5ed3+    , curveEccG = Point 0x161ff7528b899b2d0c28607ca52c5b86+                    0xcf5ac8395bafeb13c02da292dded7a83+    , curveEccN = 0xfffffffe0000000075a30d1b9038a115+    , curveEccH = 1+    }+typeSEC_p128r2 = CurvePrime $ CurvePrimeParam 0xfffffffdffffffffffffffffffffffff+paramSEC_p128r2 = CurveParameters+    { curveEccA = 0xd6031998d1b3bbfebf59cc9bbff9aee1+    , curveEccB = 0x5eeefca380d02919dc2c6558bb6d8a5d+    , curveEccG = Point 0x7b6aa5d85e572983e6fb32a7cdebc140+                    0x27b6916a894d3aee7106fe805fc34b44+    , curveEccN = 0x3fffffff7fffffffbe0024720613b5a3+    , curveEccH = 4+    }+typeSEC_p160k1 = CurvePrime $ CurvePrimeParam 0x00fffffffffffffffffffffffffffffffeffffac73+paramSEC_p160k1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000+    , curveEccB = 0x000000000000000000000000000000000000000007+    , curveEccG = Point 0x003b4c382ce37aa192a4019e763036f4f5dd4d7ebb+                    0x00938cf935318fdced6bc28286531733c3f03c4fee+    , curveEccN = 0x0100000000000000000001b8fa16dfab9aca16b6b3+    , curveEccH = 1+    }+typeSEC_p160r1 = CurvePrime $ CurvePrimeParam 0x00ffffffffffffffffffffffffffffffff7fffffff+paramSEC_p160r1 = CurveParameters+    { curveEccA = 0x00ffffffffffffffffffffffffffffffff7ffffffc+    , curveEccB = 0x001c97befc54bd7a8b65acf89f81d4d4adc565fa45+    , curveEccG = Point 0x004a96b5688ef573284664698968c38bb913cbfc82+                    0x0023a628553168947d59dcc912042351377ac5fb32+    , curveEccN = 0x0100000000000000000001f4c8f927aed3ca752257+    , curveEccH = 1+    }+typeSEC_p160r2 = CurvePrime $ CurvePrimeParam 0x00fffffffffffffffffffffffffffffffeffffac73+paramSEC_p160r2 = CurveParameters+    { curveEccA = 0x00fffffffffffffffffffffffffffffffeffffac70+    , curveEccB = 0x00b4e134d3fb59eb8bab57274904664d5af50388ba+    , curveEccG = Point 0x0052dcb034293a117e1f4ff11b30f7199d3144ce6d+                    0x00feaffef2e331f296e071fa0df9982cfea7d43f2e+    , curveEccN = 0x0100000000000000000000351ee786a818f3a1a16b+    , curveEccH = 1+    }+typeSEC_p192k1 = CurvePrime $ CurvePrimeParam 0xfffffffffffffffffffffffffffffffffffffffeffffee37+paramSEC_p192k1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000000000+    , curveEccB = 0x000000000000000000000000000000000000000000000003+    , curveEccG = Point 0xdb4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d+                    0x9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d+    , curveEccN = 0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d+    , curveEccH = 1+    }+typeSEC_p192r1 = CurvePrime $ CurvePrimeParam 0xfffffffffffffffffffffffffffffffeffffffffffffffff+paramSEC_p192r1 = CurveParameters+    { curveEccA = 0xfffffffffffffffffffffffffffffffefffffffffffffffc+    , curveEccB = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1+    , curveEccG = Point 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012+                    0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811+    , curveEccN = 0xffffffffffffffffffffffff99def836146bc9b1b4d22831+    , curveEccH = 1+    }+typeSEC_p224k1 = CurvePrime $ CurvePrimeParam 0x00fffffffffffffffffffffffffffffffffffffffffffffffeffffe56d+paramSEC_p224k1 = CurveParameters+    { curveEccA = 0x0000000000000000000000000000000000000000000000000000000000+    , curveEccB = 0x0000000000000000000000000000000000000000000000000000000005+    , curveEccG = Point 0x00a1455b334df099df30fc28a169a467e9e47075a90f7e650eb6b7a45c+                    0x007e089fed7fba344282cafbd6f7e319f7c0b0bd59e2ca4bdb556d61a5+    , curveEccN = 0x010000000000000000000000000001dce8d2ec6184caf0a971769fb1f7+    , curveEccH = 1+    }+typeSEC_p224r1 = CurvePrime $ CurvePrimeParam 0xffffffffffffffffffffffffffffffff000000000000000000000001+paramSEC_p224r1 = CurveParameters+    { curveEccA = 0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe+    , curveEccB = 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4+    , curveEccG = Point 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21+                    0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34+    , curveEccN = 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d+    , curveEccH = 1+    }+typeSEC_p256k1 = CurvePrime $ CurvePrimeParam 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f+paramSEC_p256k1 = CurveParameters+    { curveEccA = 0x0000000000000000000000000000000000000000000000000000000000000000+    , curveEccB = 0x0000000000000000000000000000000000000000000000000000000000000007+    , curveEccG = Point 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798+                    0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8+    , curveEccN = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141+    , curveEccH = 1+    }+typeSEC_p256r1 = CurvePrime $ CurvePrimeParam 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff+paramSEC_p256r1 = CurveParameters+    { curveEccA = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc+    , curveEccB = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b+    , curveEccG = Point 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296+                    0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5+    , curveEccN = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551+    , curveEccH = 1+    }+typeSEC_p384r1 = CurvePrime $ CurvePrimeParam 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff+paramSEC_p384r1 = CurveParameters+    { curveEccA = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc+    , curveEccB = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef+    , curveEccG = Point 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7+                    0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f+    , curveEccN = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973+    , curveEccH = 1+    }+typeSEC_p521r1 = CurvePrime $ CurvePrimeParam 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff+paramSEC_p521r1 = CurveParameters+    { curveEccA = 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc+    , curveEccB = 0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00+    , curveEccG = Point 0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66+                    0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650+    , curveEccN = 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409+    , curveEccH = 1+    }+typeSEC_t113r1 = CurveBinary $ CurveBinaryParam 0x020000000000000000000000000201+paramSEC_t113r1 = CurveParameters+    { curveEccA = 0x003088250ca6e7c7fe649ce85820f7+    , curveEccB = 0x00e8bee4d3e2260744188be0e9c723+    , curveEccG = Point 0x009d73616f35f4ab1407d73562c10f+                    0x00a52830277958ee84d1315ed31886+    , curveEccN = 0x0100000000000000d9ccec8a39e56f+    , curveEccH = 2+    }+typeSEC_t113r2 = CurveBinary $ CurveBinaryParam 0x020000000000000000000000000201+paramSEC_t113r2 = CurveParameters+    { curveEccA = 0x00689918dbec7e5a0dd6dfc0aa55c7+    , curveEccB = 0x0095e9a9ec9b297bd4bf36e059184f+    , curveEccG = Point 0x01a57a6a7b26ca5ef52fcdb8164797+                    0x00b3adc94ed1fe674c06e695baba1d+    , curveEccN = 0x010000000000000108789b2496af93+    , curveEccH = 2+    }+typeSEC_t131r1 = CurveBinary $ CurveBinaryParam 0x080000000000000000000000000000010d+paramSEC_t131r1 = CurveParameters+    { curveEccA = 0x07a11b09a76b562144418ff3ff8c2570b8+    , curveEccB = 0x0217c05610884b63b9c6c7291678f9d341+    , curveEccG = Point 0x0081baf91fdf9833c40f9c181343638399+                    0x078c6e7ea38c001f73c8134b1b4ef9e150+    , curveEccN = 0x0400000000000000023123953a9464b54d+    , curveEccH = 2+    }+typeSEC_t131r2 = CurveBinary $ CurveBinaryParam 0x080000000000000000000000000000010d+paramSEC_t131r2 = CurveParameters+    { curveEccA = 0x03e5a88919d7cafcbf415f07c2176573b2+    , curveEccB = 0x04b8266a46c55657ac734ce38f018f2192+    , curveEccG = Point 0x0356dcd8f2f95031ad652d23951bb366a8+                    0x0648f06d867940a5366d9e265de9eb240f+    , curveEccN = 0x0400000000000000016954a233049ba98f+    , curveEccH = 2+    }+typeSEC_t163k1 = CurveBinary $ CurveBinaryParam 0x0800000000000000000000000000000000000000c9+paramSEC_t163k1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000001+    , curveEccB = 0x000000000000000000000000000000000000000001+    , curveEccG = Point 0x02fe13c0537bbc11acaa07d793de4e6d5e5c94eee8+                    0x0289070fb05d38ff58321f2e800536d538ccdaa3d9+    , curveEccN = 0x04000000000000000000020108a2e0cc0d99f8a5ef+    , curveEccH = 2+    }+typeSEC_t163r1 = CurveBinary $ CurveBinaryParam 0x0800000000000000000000000000000000000000c9+paramSEC_t163r1 = CurveParameters+    { curveEccA = 0x07b6882caaefa84f9554ff8428bd88e246d2782ae2+    , curveEccB = 0x0713612dcddcb40aab946bda29ca91f73af958afd9+    , curveEccG = Point 0x0369979697ab43897789566789567f787a7876a654+                    0x00435edb42efafb2989d51fefce3c80988f41ff883+    , curveEccN = 0x03ffffffffffffffffffff48aab689c29ca710279b+    , curveEccH = 2+    }+typeSEC_t163r2 = CurveBinary $ CurveBinaryParam 0x0800000000000000000000000000000000000000c9+paramSEC_t163r2 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000001+    , curveEccB = 0x020a601907b8c953ca1481eb10512f78744a3205fd+    , curveEccG = Point 0x03f0eba16286a2d57ea0991168d4994637e8343e36+                    0x00d51fbc6c71a0094fa2cdd545b11c5c0c797324f1+    , curveEccN = 0x040000000000000000000292fe77e70c12a4234c33+    , curveEccH = 2+    }+typeSEC_t193r1 = CurveBinary $ CurveBinaryParam 0x02000000000000000000000000000000000000000000008001+paramSEC_t193r1 = CurveParameters+    { curveEccA = 0x0017858feb7a98975169e171f77b4087de098ac8a911df7b01+    , curveEccB = 0x00fdfb49bfe6c3a89facadaa7a1e5bbc7cc1c2e5d831478814+    , curveEccG = Point 0x01f481bc5f0ff84a74ad6cdf6fdef4bf6179625372d8c0c5e1+                    0x0025e399f2903712ccf3ea9e3a1ad17fb0b3201b6af7ce1b05+    , curveEccN = 0x01000000000000000000000000c7f34a778f443acc920eba49+    , curveEccH = 2+    }+typeSEC_t193r2 = CurveBinary $ CurveBinaryParam 0x02000000000000000000000000000000000000000000008001+paramSEC_t193r2 = CurveParameters+    { curveEccA = 0x0163f35a5137c2ce3ea6ed8667190b0bc43ecd69977702709b+    , curveEccB = 0x00c9bb9e8927d4d64c377e2ab2856a5b16e3efb7f61d4316ae+    , curveEccG = Point 0x00d9b67d192e0367c803f39e1a7e82ca14a651350aae617e8f+                    0x01ce94335607c304ac29e7defbd9ca01f596f927224cdecf6c+    , curveEccN = 0x010000000000000000000000015aab561b005413ccd4ee99d5+    , curveEccH = 2+    }+typeSEC_t233k1 = CurveBinary $ CurveBinaryParam 0x020000000000000000000000000000000000000004000000000000000001+paramSEC_t233k1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000000000000000000000+    , curveEccB = 0x000000000000000000000000000000000000000000000000000000000001+    , curveEccG = Point 0x017232ba853a7e731af129f22ff4149563a419c26bf50a4c9d6eefad6126+                    0x01db537dece819b7f70f555a67c427a8cd9bf18aeb9b56e0c11056fae6a3+    , curveEccN = 0x008000000000000000000000000000069d5bb915bcd46efb1ad5f173abdf+    , curveEccH = 4+    }+typeSEC_t233r1 = CurveBinary $ CurveBinaryParam 0x020000000000000000000000000000000000000004000000000000000001+paramSEC_t233r1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000000000000000000001+    , curveEccB = 0x0066647ede6c332c7f8c0923bb58213b333b20e9ce4281fe115f7d8f90ad+    , curveEccG = Point 0x00fac9dfcbac8313bb2139f1bb755fef65bc391f8b36f8f8eb7371fd558b+                    0x01006a08a41903350678e58528bebf8a0beff867a7ca36716f7e01f81052+    , curveEccN = 0x01000000000000000000000000000013e974e72f8a6922031d2603cfe0d7+    , curveEccH = 2+    }+typeSEC_t239k1 = CurveBinary $ CurveBinaryParam 0x800000000000000000004000000000000000000000000000000000000001+paramSEC_t239k1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000000000000000000000+    , curveEccB = 0x000000000000000000000000000000000000000000000000000000000001+    , curveEccG = Point 0x29a0b6a887a983e9730988a68727a8b2d126c44cc2cc7b2a6555193035dc+                    0x76310804f12e549bdb011c103089e73510acb275fc312a5dc6b76553f0ca+    , curveEccN = 0x2000000000000000000000000000005a79fec67cb6e91f1c1da800e478a5+    , curveEccH = 4+    }+typeSEC_t283k1 = CurveBinary $ CurveBinaryParam 0x0800000000000000000000000000000000000000000000000000000000000000000010a1+paramSEC_t283k1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000000000000000000000000000000000+    , curveEccB = 0x000000000000000000000000000000000000000000000000000000000000000000000001+    , curveEccG = Point 0x0503213f78ca44883f1a3b8162f188e553cd265f23c1567a16876913b0c2ac2458492836+                    0x01ccda380f1c9e318d90f95d07e5426fe87e45c0e8184698e45962364e34116177dd2259+    , curveEccN = 0x01ffffffffffffffffffffffffffffffffffe9ae2ed07577265dff7f94451e061e163c61+    , curveEccH = 4+    }+typeSEC_t283r1 = CurveBinary $ CurveBinaryParam 0x0800000000000000000000000000000000000000000000000000000000000000000010a1+paramSEC_t283r1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000000000000000000000000000000001+    , curveEccB = 0x027b680ac8b8596da5a4af8a19a0303fca97fd7645309fa2a581485af6263e313b79a2f5+    , curveEccG = Point 0x05f939258db7dd90e1934f8c70b0dfec2eed25b8557eac9c80e2e198f8cdbecd86b12053+                    0x03676854fe24141cb98fe6d4b20d02b4516ff702350eddb0826779c813f0df45be8112f4+    , curveEccN = 0x03ffffffffffffffffffffffffffffffffffef90399660fc938a90165b042a7cefadb307+    , curveEccH = 2+    }+typeSEC_t409k1 = CurveBinary $ CurveBinaryParam 0x02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001+paramSEC_t409k1 = CurveParameters+    { curveEccA = 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+    , curveEccB = 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+    , curveEccG = Point 0x0060f05f658f49c1ad3ab1890f7184210efd0987e307c84c27accfb8f9f67cc2c460189eb5aaaa62ee222eb1b35540cfe9023746+                    0x01e369050b7c4e42acba1dacbf04299c3460782f918ea427e6325165e9ea10e3da5f6c42e9c55215aa9ca27a5863ec48d8e0286b+    , curveEccN = 0x007ffffffffffffffffffffffffffffffffffffffffffffffffffe5f83b2d4ea20400ec4557d5ed3e3e7ca5b4b5c83b8e01e5fcf+    , curveEccH = 4+    }+typeSEC_t409r1 = CurveBinary $ CurveBinaryParam 0x02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001+paramSEC_t409r1 = CurveParameters+    { curveEccA = 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+    , curveEccB = 0x0021a5c2c8ee9feb5c4b9a753b7b476b7fd6422ef1f3dd674761fa99d6ac27c8a9a197b272822f6cd57a55aa4f50ae317b13545f+    , curveEccG = Point 0x015d4860d088ddb3496b0c6064756260441cde4af1771d4db01ffe5b34e59703dc255a868a1180515603aeab60794e54bb7996a7+                    0x0061b1cfab6be5f32bbfa78324ed106a7636b9c5a7bd198d0158aa4f5488d08f38514f1fdf4b4f40d2181b3681c364ba0273c706+    , curveEccN = 0x010000000000000000000000000000000000000000000000000001e2aad6a612f33307be5fa47c3c9e052f838164cd37d9a21173+    , curveEccH = 2+    }+typeSEC_t571k1 = CurveBinary $ CurveBinaryParam 0x080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425+paramSEC_t571k1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+    , curveEccB = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+    , curveEccG = Point 0x026eb7a859923fbc82189631f8103fe4ac9ca2970012d5d46024804801841ca44370958493b205e647da304db4ceb08cbbd1ba39494776fb988b47174dca88c7e2945283a01c8972+                    0x0349dc807f4fbf374f4aeade3bca95314dd58cec9f307a54ffc61efc006d8a2c9d4979c0ac44aea74fbebbb9f772aedcb620b01a7ba7af1b320430c8591984f601cd4c143ef1c7a3+    , curveEccN = 0x020000000000000000000000000000000000000000000000000000000000000000000000131850e1f19a63e4b391a8db917f4138b630d84be5d639381e91deb45cfe778f637c1001+    , curveEccH = 4+    }+typeSEC_t571r1 = CurveBinary $ CurveBinaryParam 0x080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425+paramSEC_t571r1 = CurveParameters+    { curveEccA = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001+    , curveEccB = 0x02f40e7e2221f295de297117b7f3d62f5c6a97ffcb8ceff1cd6ba8ce4a9a18ad84ffabbd8efa59332be7ad6756a66e294afd185a78ff12aa520e4de739baca0c7ffeff7f2955727a+    , curveEccG = Point 0x0303001d34b856296c16c0d40d3cd7750a93d1d2955fa80aa5f40fc8db7b2abdbde53950f4c0d293cdd711a35b67fb1499ae60038614f1394abfa3b4c850d927e1e7769c8eec2d19+                    0x037bf27342da639b6dccfffeb73d69d78c6c27a6009cbbca1980f8533921e8a684423e43bab08a576291af8f461bb2a8b3531d2f0485c19b16e2f1516e23dd3c1a4827af1b8ac15b+    , curveEccN = 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe661ce18ff55987308059b186823851ec7dd9ca1161de93d5174d66e8382e9bb2fe84e47+    , curveEccH = 2+    }
Crypto/Error/Types.hs view
@@ -34,6 +34,12 @@     | CryptoError_SecretKeyStructureInvalid     | CryptoError_PublicKeySizeInvalid     | CryptoError_SharedSecretSizeInvalid+    -- elliptic cryptography error+    | CryptoError_EcScalarOutOfBounds+    | CryptoError_PointSizeInvalid+    | CryptoError_PointFormatInvalid+    | CryptoError_PointFormatUnsupported+    | CryptoError_PointCoordinatesInvalid     -- Message authentification error     | CryptoError_MacKeyInvalid     | CryptoError_AuthenticationTagSizeInvalid
+ Crypto/Internal/Proxy.hs view
@@ -0,0 +1,13 @@+-- |+-- Module      : Crypto.Internal.Proxy+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : Good+--+module Crypto.Internal.Proxy+    ( Proxy(..)+    ) where++-- | A type witness for 'a' as phantom type+data Proxy a = Proxy
Crypto/KDF/HKDF.hs view
@@ -18,15 +18,21 @@     ) where  import           Data.Word-import           Crypto.Hash +import           Crypto.Hash import           Crypto.MAC.HMAC-import           Crypto.Internal.ByteArray (ScrubbedBytes, Bytes, ByteArray, ByteArrayAccess)+import           Crypto.Internal.ByteArray (ScrubbedBytes, ByteArray, ByteArrayAccess) import qualified Crypto.Internal.ByteArray as B  -- | Pseudo Random Key data PRK a = PRK (HMAC a) | PRK_NoExpand ScrubbedBytes     deriving (Eq) +instance ByteArrayAccess (PRK a) where+    length (PRK hm)          = B.length hm+    length (PRK_NoExpand sb) = B.length sb+    withByteArray (PRK hm)          = B.withByteArray hm+    withByteArray (PRK_NoExpand sb) = B.withByteArray sb+ -- | Extract a Pseudo Random Key using the parameter and the underlaying hash mechanism extract :: (HashAlgorithm a, ByteArrayAccess salt, ByteArrayAccess ikm)         => salt  -- ^ Salt@@ -38,7 +44,7 @@ -- -- Only use when guaranteed to have a good quality and random data to use directly as key. -- This effectively skip a HMAC with key=salt and data=key.-extractSkip :: (HashAlgorithm a, ByteArrayAccess ikm)+extractSkip :: ByteArrayAccess ikm             => ikm             -> PRK a extractSkip ikm = PRK_NoExpand $ B.convert ikm
Crypto/PubKey/Curve25519.hs view
@@ -9,6 +9,7 @@ -- {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-} module Crypto.PubKey.Curve25519     ( SecretKey     , PublicKey@@ -20,17 +21,22 @@     -- * methods     , dh     , toPublic+    , generateSecretKey     ) where +import           Data.Bits import           Data.Word import           Foreign.Ptr+import           Foreign.Storable import           GHC.Ptr  import           Crypto.Error import           Crypto.Internal.Compat import           Crypto.Internal.Imports-import           Crypto.Internal.ByteArray (ByteArrayAccess, ScrubbedBytes, Bytes, withByteArray)+import           Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, ScrubbedBytes, Bytes, withByteArray) import qualified Crypto.Internal.ByteArray as B+import           Crypto.Error (CryptoFailable(..))+import           Crypto.Random  -- | A Curve25519 Secret key newtype SecretKey = SecretKey ScrubbedBytes@@ -104,6 +110,18 @@   where         basePoint = Ptr "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# {-# NOINLINE toPublic #-}++-- | Generate a secret key.+generateSecretKey :: MonadRandom m => m SecretKey+generateSecretKey = tweakToSecretKey <$> getRandomBytes 32+  where+    tweakToSecretKey :: ScrubbedBytes -> SecretKey+    tweakToSecretKey bin = SecretKey $ B.copyAndFreeze bin $ \inp -> do+        modifyByte inp 0 (\e0 -> e0 .&. 0xf8)+        modifyByte inp 31 (\e31 -> (e31 .&. 0x7f) .|. 0x40)++    modifyByte :: Ptr Word8 -> Int -> (Word8 -> Word8) -> IO ()+    modifyByte p n f = peekByteOff p n >>= pokeByteOff p n . f  foreign import ccall "cryptonite_curve25519_donna"     ccryptonite_curve25519 :: Ptr Word8 -- ^ public
Crypto/PubKey/ECC/P256.hs view
@@ -18,6 +18,7 @@     , pointBase     , pointAdd     , pointMul+    , pointDh     , pointsMulVarTime     , pointIsValid     , toPoint@@ -56,7 +57,7 @@  -- | A P256 scalar newtype Scalar = Scalar ScrubbedBytes-    deriving (Eq,ByteArrayAccess)+    deriving (Show,Eq,ByteArrayAccess)  -- | A P256 point newtype Point = Point Bytes@@ -112,6 +113,14 @@     withScalar scalar $ \n -> withPoint p $ \px py -> withScalarZero $ \nzero ->         ccryptonite_p256_points_mul_vartime nzero n px py dx dy +-- | Similar to 'pointMul', serializing the x coordinate as binary+pointDh :: ByteArray binary => Scalar -> Point -> binary+pointDh scalar p =+    B.unsafeCreate scalarSize $ \dst -> withTempPoint $ \dx dy -> do+        withScalar scalar $ \n -> withPoint p $ \px py -> withScalarZero $ \nzero ->+            ccryptonite_p256_points_mul_vartime nzero n px py dx dy+        ccryptonite_p256_to_bin (castPtr dx) dst+ -- | multiply the point @p with @n2 and add a lifted to curve value @n1 -- -- > n1 * G + n2 * p@@ -281,6 +290,9 @@ withNewScalarFreeze :: (Ptr P256Scalar -> IO ()) -> Scalar withNewScalarFreeze f = Scalar $ B.allocAndFreeze scalarSize f {-# NOINLINE withNewScalarFreeze #-}++withTempPoint :: (Ptr P256X -> Ptr P256Y -> IO a) -> IO a+withTempPoint f = allocTempScrubbed scalarSize (\p -> let px = castPtr p in f px (pxToPy px))  withTempScalar :: (Ptr P256Scalar -> IO a) -> IO a withTempScalar f = allocTempScrubbed scalarSize (f . castPtr)
Crypto/PubKey/ECC/Types.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE DeriveDataTypeable #-} -- |--- Module      : Crypto.PubKey.ECC.types+-- Module      : Crypto.PubKey.ECC.Types -- License     : BSD-style -- Maintainer  : Vincent Hanquez <vincent@snarc.org> -- Stability   : Experimental
+ Crypto/PubKey/ECIES.hs view
@@ -0,0 +1,48 @@+-- |+-- Module      : Crypto.PubKey.ECIES+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : unknown+--+-- IES with Elliptic curve <https://en.wikipedia.org/wiki/Integrated_Encryption_Scheme>+--+-- This is a simple cryptographic system between 2 parties using Elliptic Curve.+--+-- The sending party create a shared secret using the receiver public key, and use the shared secret+-- to generate cryptographic material for an symmetric encryption scheme (preferably authenticated encryption).+--+-- The receiving party receive the temporary ephemeral public key which is combined to its secret key+-- to create the shared secret which just like on the sending is used to generate cryptographic material.+--+-- This module doesn't provide any symmetric data encryption capability or any mean to derive+-- cryptographic key material for a symmetric key from the shared secret.+-- this is left to the user for now.+--+module Crypto.PubKey.ECIES+    ( deriveEncrypt+    , deriveDecrypt+    ) where++import           Crypto.ECC+import           Crypto.Random+import           Crypto.Internal.Proxy++-- | Generate random a new Shared secret and the associated point+-- to do a ECIES style encryption+deriveEncrypt :: (MonadRandom randomly, EllipticCurveDH curve)+              => proxy curve -- ^ representation of the curve+              -> Point curve -- ^ the public key of the receiver+              -> randomly (Point curve, SharedSecret)+deriveEncrypt proxy pub = do+    (KeyPair rPoint rScalar) <- curveGenerateKeyPair proxy+    return (rPoint, ecdh proxy rScalar pub)++-- | Derive the shared secret with the receiver key+-- and the R point of the scheme.+deriveDecrypt :: EllipticCurveDH curve+              => proxy curve  -- ^ representation of the curve+              -> Point curve  -- ^ The received R (supposedly, randomly generated on the encrypt side)+              -> Scalar curve -- ^ The secret key of the receiver+              -> SharedSecret+deriveDecrypt proxy point secret = ecdh proxy secret point
Crypto/PubKey/Ed448.hs view
@@ -20,6 +20,7 @@     -- * methods     , dh     , toPublic+    , generateSecretKey     ) where  import           Data.Word@@ -27,6 +28,7 @@ import           GHC.Ptr  import           Crypto.Error+import           Crypto.Random import           Crypto.Internal.Compat import           Crypto.Internal.Imports import           Crypto.Internal.ByteArray (ByteArrayAccess, ScrubbedBytes, Bytes, withByteArray)@@ -91,6 +93,10 @@   where         basePoint = Ptr "\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"# {-# NOINLINE toPublic #-}++-- | Generate a secret key.+generateSecretKey :: MonadRandom m => m SecretKey+generateSecretKey = SecretKey <$> getRandomBytes x448_bytes  x448_bytes :: Int x448_bytes = 448 `quot` 8
README.md view
@@ -94,6 +94,7 @@ * [Salsa](http://cr.yp.to/snuffle.html) * [Salsa128-test-vectors](https://github.com/alexwebr/salsa20/blob/master/test_vectors.128) * [Salsa256-test-vectors](https://github.com/alexwebr/salsa20/blob/master/test_vectors.256)+* [XSalsa](https://cr.yp.to/snuffle/xsalsa-20081128.pdf) * [PBKDF2](http://tools.ietf.org/html/rfc2898) * [PBKDF2-test-vectors](http://www.ietf.org/rfc/rfc6070.txt) * [Scrypt](http://www.tarsnap.com/scrypt.html)@@ -101,7 +102,3 @@ * [Ed25519](http://ed25519.cr.yp.to/papers.html) * [AFIS](http://clemens.endorphin.org/cryptography) -TODO-------* add support for XSalsa
+ cbits/cryptonite_align.h view
@@ -0,0 +1,51 @@+#ifndef CRYPTONITE_ALIGN_H+#define CRYPTONITE_ALIGN_H++#include "cryptonite_bitfn.h"++#if (defined(__i386__))+# define UNALIGNED_ACCESS_OK+#elif defined(__x86_64__)+# define UNALIGNED_ACCESS_OK+#else+# define UNALIGNED_ACCESS_FAULT+#endif++/* n need to be power of 2.+ * IS_ALIGNED(p,8) */+#define IS_ALIGNED(p,alignment) (((uintptr_t) (p)) & ((alignment)-1))++#ifdef WITH_ASSERT_ALIGNMENT+#include <stdio.h>+#include <stdlib.h>+#include <inttypes.h>+# define ASSERT_ALIGNMENT(up, alignment) \+	do { if (IS_ALIGNED(up, alignment)) \+	{ printf("ALIGNMENT-ASSERT-FAILURE: %s:%d: ptr=%p alignment=%d\n", __FILE__, __LINE__, (void *) up, (alignment)); \+	  exit(99); \+	}; } while (0)+#else+# define ASSERT_ALIGNMENT(p, n) do {} while (0)+#endif++#ifdef UNALIGNED_ACCESS_OK+#define need_alignment(p,n) (0)+#else+#define need_alignment(p,n) IS_ALIGNED(p,n)+#endif++static inline uint32_t load_le32_aligned(const uint8_t *p)+{+	return le32_to_cpu(*((uint32_t *) p));		+}++#ifdef UNALIGNED_ACCESS_OK+#define load_le32(a) load_le32_aligned(a)+#else+static inline uint32_t load_le32(const uint8_t *p)+{+	return ((uint32_t)p[0]) | ((uint32_t)p[1] <<  8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);+}+#endif++#endif
cbits/cryptonite_chacha.c view
@@ -32,6 +32,7 @@ #include <string.h> #include "cryptonite_chacha.h" #include "cryptonite_bitfn.h"+#include "cryptonite_align.h" #include <stdio.h>  #define QR(a,b,c,d) \@@ -46,11 +47,6 @@ static const uint8_t sigma[16] = "expand 32-byte k"; static const uint8_t tau[16] = "expand 16-byte k"; -static inline uint32_t load32(const uint8_t *p)-{-	return le32_to_cpu(*((uint32_t *) p));-}- static void chacha_core(int rounds, block *out, const cryptonite_chacha_state *in) { 	uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;@@ -104,33 +100,35 @@ 	const uint8_t *constants = (keylen == 32) ? sigma : tau; 	int i; -	st->d[0] = load32(constants + 0);-	st->d[1] = load32(constants + 4);-	st->d[2] = load32(constants + 8);-	st->d[3] = load32(constants + 12);+	ASSERT_ALIGNMENT(constants, 4); -	st->d[4] = load32(key + 0);-	st->d[5] = load32(key + 4);-	st->d[6] = load32(key + 8);-	st->d[7] = load32(key + 12);+	st->d[0] = load_le32_aligned(constants + 0);+	st->d[1] = load_le32_aligned(constants + 4);+	st->d[2] = load_le32_aligned(constants + 8);+	st->d[3] = load_le32_aligned(constants + 12);++	st->d[4] = load_le32(key + 0);+	st->d[5] = load_le32(key + 4);+	st->d[6] = load_le32(key + 8);+	st->d[7] = load_le32(key + 12); 	/* we repeat the key on 128 bits */ 	if (keylen == 32) 		key += 16;-	st->d[8] = load32(key + 0);-	st->d[9] = load32(key + 4);-	st->d[10] = load32(key + 8);-	st->d[11] = load32(key + 12);+	st->d[8] = load_le32(key + 0);+	st->d[9] = load_le32(key + 4);+	st->d[10] = load_le32(key + 8);+	st->d[11] = load_le32(key + 12); 	st->d[12] = 0; 	switch (ivlen) { 	case 8: 		st->d[13] = 0;-		st->d[14] = load32(iv + 0);-		st->d[15] = load32(iv + 4);+		st->d[14] = load_le32(iv + 0);+		st->d[15] = load_le32(iv + 4); 		break; 	case 12:-		st->d[13] = load32(iv + 0);-		st->d[14] = load32(iv + 4);-		st->d[15] = load32(iv + 8);+		st->d[13] = load_le32(iv + 0);+		st->d[14] = load_le32(iv + 4);+		st->d[15] = load_le32(iv + 8); 	default: 		return; 	}
cbits/cryptonite_poly1305.c view
@@ -132,7 +132,7 @@ 	/* fill the remaining bytes in the partial buffer */ 	if (length) { 		memcpy(ctx->buf + ctx->index, data, length);-		ctx->index = length;+		ctx->index += length; 	} } 
cbits/cryptonite_sha3.c view
@@ -25,6 +25,7 @@ #include <stdint.h> #include <string.h> #include "cryptonite_bitfn.h"+#include "cryptonite_align.h" #include "cryptonite_sha3.h"  #define KECCAK_NB_ROUNDS 24@@ -124,9 +125,19 @@ 		ctx->bufindex = 0; 	} -	/* process as much ctx->bufsz-block */-	for (; len >= ctx->bufsz; len -= ctx->bufsz, data += ctx->bufsz)-		sha3_do_chunk(ctx->state, (uint64_t *) data, ctx->bufsz / 8);+	if (need_alignment(data, 8)) {+		uint64_t tramp[200 - 2 * (224 / 8)];+		ASSERT_ALIGNMENT(tramp, 8);+		for (; len >= ctx->bufsz; len -= ctx->bufsz, data += ctx->bufsz) {+			memcpy(tramp, data, ctx->bufsz / 8);+			sha3_do_chunk(ctx->state, (uint64_t *) data, ctx->bufsz / 8);+		}+	} else {+		/* process as much ctx->bufsz-block */+		for (; len >= ctx->bufsz; len -= ctx->bufsz, data += ctx->bufsz)+			sha3_do_chunk(ctx->state, (uint64_t *) data, ctx->bufsz / 8);+	}+  	/* append data into buf */ 	if (len) {
+ cbits/cryptonite_xsalsa.c view
@@ -0,0 +1,80 @@+/*+ * Copyright (c) 2016 Brandon Hamilton <brandon.hamilton@gmail.com>+ * + * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the author nor the names of his contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */+#include <stdint.h>+#include <string.h>+#include "cryptonite_xsalsa.h"+#include "cryptonite_bitfn.h"++static inline uint32_t load32(const uint8_t *p)+{+  return le32_to_cpu(*((uint32_t *) p));+}++/* XSalsa20 algorithm as described in https://cr.yp.to/snuffle/xsalsa-20081128.pdf */+void cryptonite_xsalsa_init(cryptonite_salsa_context *ctx, uint8_t nb_rounds,+                            uint32_t keylen, const uint8_t *key,+                            uint32_t ivlen, const uint8_t *iv)+{+  memset(ctx, 0, sizeof(*ctx));+  ctx->nb_rounds = nb_rounds;++  /* Create initial 512-bit input block:+       (x0, x5, x10, x15) is the Salsa20 constant+       (x1, x2, x3, x4, x11, x12, x13, x14) is a 256-bit key+       (x6, x7, x8, x9) is the first 128 bits of a 192-bit nonce+  */+  cryptonite_salsa_init_core(&ctx->st, keylen, key, 8, iv);+  ctx->st.d[ 8] = load32(iv + 8);+  ctx->st.d[ 9] = load32(iv + 12);++  /* Compute (z0, z1, . . . , z15) = doubleround ^(r/2) (x0, x1, . . . , x15) */+  block hSalsa;+  memset(&hSalsa, 0, sizeof(block));+  cryptonite_salsa_core_xor(nb_rounds, &hSalsa, &ctx->st);+ +  /* Build a new 512-bit input block (x′0, x′1, . . . , x′15):+       (x′0, x′5, x′10, x′15) is the Salsa20 constant+       (x′1,x′2,x′3,x′4,x′11,x′12,x′13,x′14) = (z0,z5,z10,z15,z6,z7,z8,z9)+       (x′6,x′7) is the last 64 bits of the 192-bit nonce+       (x′8, x′9) is a 64-bit block counter.+  */+  ctx->st.d[ 1] = hSalsa.d[ 0] - ctx->st.d[ 0];+  ctx->st.d[ 2] = hSalsa.d[ 5] - ctx->st.d[ 5];+  ctx->st.d[ 3] = hSalsa.d[10] - ctx->st.d[10];+  ctx->st.d[ 4] = hSalsa.d[15] - ctx->st.d[15];+  ctx->st.d[11] = hSalsa.d[ 6] - ctx->st.d[ 6];+  ctx->st.d[12] = hSalsa.d[ 7] - ctx->st.d[ 7];+  ctx->st.d[13] = hSalsa.d[ 8] - ctx->st.d[ 8];+  ctx->st.d[14] = hSalsa.d[ 9] - ctx->st.d[ 9];+  ctx->st.d[ 6] = load32(iv + 16);+  ctx->st.d[ 7] = load32(iv + 20);+  ctx->st.d[ 8] = 0;+  ctx->st.d[ 9] = 0;+}
+ cbits/cryptonite_xsalsa.h view
@@ -0,0 +1,37 @@+/*+ * Copyright (c) 2016 Brandon Hamilton <brandon.hamilton@gmail.com>+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the name of the author nor the names of his contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */+#ifndef CRYPTONITE_XSALSA+#define CRYPTONITE_XSALSA++#include "cryptonite_salsa.h"++void cryptonite_xsalsa_init(cryptonite_salsa_context *ctx, uint8_t nb_rounds, uint32_t keylen, const uint8_t *key, uint32_t ivlen, const uint8_t *iv);++#endif
cryptonite.cabal view
@@ -1,10 +1,10 @@ Name:                cryptonite-Version:             0.20+Version:             0.21 Synopsis:            Cryptography Primitives sink Description:     A repository of cryptographic primitives.     .-    * Symmetric ciphers: AES, DES, 3DES, Blowfish, Camellia, RC4, Salsa, ChaCha.+    * Symmetric ciphers: AES, DES, 3DES, Blowfish, Camellia, RC4, Salsa, XSalsa, ChaCha.     .     * Hash: SHA1, SHA2, SHA3, MD2, MD4, MD5, Keccak, Skein, Ripemd, Tiger, Whirlpool, Blake2     .@@ -86,6 +86,11 @@   Default:           False   Manual:            True +Flag check_alignment+  Description:       extra check on alignment in C layers, which cause lowlevel assert errors. for debugging only.+  Default:           False+  Manual:            True+ Library   Exposed-modules:   Crypto.Cipher.AES                      Crypto.Cipher.Blowfish@@ -97,9 +102,11 @@                      Crypto.Cipher.Salsa                      Crypto.Cipher.TripleDES                      Crypto.Cipher.Types+                     Crypto.Cipher.XSalsa                      Crypto.ConstructHash.MiyaguchiPreneel                      Crypto.Data.AFIS                      Crypto.Data.Padding+                     Crypto.ECC                      Crypto.Error                      Crypto.MAC.CMAC                      Crypto.MAC.Poly1305@@ -128,6 +135,7 @@                      Crypto.PubKey.ECC.ECDSA                      Crypto.PubKey.ECC.P256                      Crypto.PubKey.ECC.Types+                     Crypto.PubKey.ECIES                      Crypto.PubKey.Ed25519                      Crypto.PubKey.Ed448                      Crypto.PubKey.RSA@@ -183,6 +191,9 @@                      Crypto.Random.Probabilistic                      Crypto.PubKey.Internal                      Crypto.PubKey.ElGamal+                     Crypto.ECC.Simple.Types+                     Crypto.ECC.Simple.Prim+                     Crypto.Internal.Proxy                      Crypto.Internal.ByteArray                      Crypto.Internal.Compat                      Crypto.Internal.CompatPrim@@ -201,6 +212,7 @@     cc-options:      -fgnu89-inline   C-sources:         cbits/cryptonite_chacha.c                    , cbits/cryptonite_salsa.c+                   , cbits/cryptonite_xsalsa.c                    , cbits/cryptonite_rc4.c                    , cbits/cryptonite_cpu.c                    , cbits/ed25519/ed25519.c@@ -290,6 +302,8 @@   if flag(support_deepseq)     CPP-options:     -DWITH_DEEPSEQ_SUPPORT     Build-depends:   deepseq+  if flag(check_alignment)+    cc-options:     -DWITH_ASSERT_ALIGNMENT  Test-Suite test-cryptonite   type:              exitcode-stdio-1.0@@ -335,6 +349,7 @@                      Poly1305                      Salsa                      Utils+                     XSalsa   Build-Depends:     base >= 3 && < 5                    , bytestring                    , memory
tests/Tests.hs view
@@ -9,6 +9,7 @@ import qualified Hash import qualified Poly1305 import qualified Salsa+import qualified XSalsa import qualified ChaCha import qualified ChaChaPoly1305 import qualified KAT_MiyaguchiPreneel@@ -67,6 +68,7 @@         , ChaCha.tests         , ChaChaPoly1305.tests         , Salsa.tests+        , XSalsa.tests         ]     , KAT_AFIS.tests     ]
+ tests/XSalsa.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE OverloadedStrings #-}+module XSalsa (tests) where++import qualified Data.ByteString as B+import qualified Crypto.Cipher.XSalsa as XSalsa++import           Imports++type Vector = (Int, B.ByteString, B.ByteString, B.ByteString, B.ByteString)++-- Test vectors generated by naclcrypto library (https://nacl.cr.yp.to)+vectors :: [Vector]+vectors =+    [ ( 20+       , "\xA6\xA7\x25\x1C\x1E\x72\x91\x6D\x11\xC2\xCB\x21\x4D\x3C\x25\x25\x39\x12\x1D\x8E\x23\x4E\x65\x2D\x65\x1F\xA4\xC8\xCF\xF8\x80\x30"+       , "\x9E\x64\x5A\x74\xE9\xE0\xA6\x0D\x82\x43\xAC\xD9\x17\x7A\xB5\x1A\x1B\xEB\x8D\x5A\x2F\x5D\x70\x0C"+       , "\x09\x3C\x5E\x55\x85\x57\x96\x25\x33\x7B\xD3\xAB\x61\x9D\x61\x57\x60\xD8\xC5\xB2\x24\xA8\x5B\x1D\x0E\xFE\x0E\xB8\xA7\xEE\x16\x3A\xBB\x03\x76\x52\x9F\xCC\x09\xBA\xB5\x06\xC6\x18\xE1\x3C\xE7\x77\xD8\x2C\x3A\xE9\xD1\xA6\xF9\x72\xD4\x16\x02\x87\xCB\xFE\x60\xBF\x21\x30\xFC\x0A\x6F\xF6\x04\x9D\x0A\x5C\x8A\x82\xF4\x29\x23\x1F\x00\x80\x82\xE8\x45\xD7\xE1\x89\xD3\x7F\x9E\xD2\xB4\x64\xE6\xB9\x19\xE6\x52\x3A\x8C\x12\x10\xBD\x52\xA0\x2A\x4C\x3F\xE4\x06\xD3\x08\x5F\x50\x68\xD1\x90\x9E\xEE\xCA\x63\x69\xAB\xC9\x81\xA4\x2E\x87\xFE\x66\x55\x83\xF0\xAB\x85\xAE\x71\xF6\xF8\x4F\x52\x8E\x6B\x39\x7A\xF8\x6F\x69\x17\xD9\x75\x4B\x73\x20\xDB\xDC\x2F\xEA\x81\x49\x6F\x27\x32\xF5\x32\xAC\x78\xC4\xE9\xC6\xCF\xB1\x8F\x8E\x9B\xDF\x74\x62\x2E\xB1\x26\x14\x14\x16\x77\x69\x71\xA8\x4F\x94\xD1\x56\xBE\xAF\x67\xAE\xCB\xF2\xAD\x41\x2E\x76\xE6\x6E\x8F\xAD\x76\x33\xF5\xB6\xD7\xF3\xD6\x4B\x5C\x6C\x69\xCE\x29\x00\x3C\x60\x24\x46\x5A\xE3\xB8\x9B\xE7\x8E\x91\x5D\x88\xB4\xB5\x62\x1D"+       , "\xB2\xAF\x68\x8E\x7D\x8F\xC4\xB5\x08\xC0\x5C\xC3\x9D\xD5\x83\xD6\x71\x43\x22\xC6\x4D\x7F\x3E\x63\x14\x7A\xED\xE2\xD9\x53\x49\x34\xB0\x4F\xF6\xF3\x37\xB0\x31\x81\x5C\xD0\x94\xBD\xBC\x6D\x7A\x92\x07\x7D\xCE\x70\x94\x12\x28\x68\x22\xEF\x07\x37\xEE\x47\xF6\xB7\xFF\xA2\x2F\x9D\x53\xF1\x1D\xD2\xB0\xA3\xBB\x9F\xC0\x1D\x9A\x88\xF9\xD5\x3C\x26\xE9\x36\x5C\x2C\x3C\x06\x3B\xC4\x84\x0B\xFC\x81\x2E\x4B\x80\x46\x3E\x69\xD1\x79\x53\x0B\x25\xC1\x58\xF5\x43\x19\x1C\xFF\x99\x31\x06\x51\x1A\xA0\x36\x04\x3B\xBC\x75\x86\x6A\xB7\xE3\x4A\xFC\x57\xE2\xCC\xE4\x93\x4A\x5F\xAA\xE6\xEA\xBE\x4F\x22\x17\x70\x18\x3D\xD0\x60\x46\x78\x27\xC2\x7A\x35\x41\x59\xA0\x81\x27\x5A\x29\x1F\x69\xD9\x46\xD6\xFE\x28\xED\x0B\x9C\xE0\x82\x06\xCF\x48\x49\x25\xA5\x1B\x94\x98\xDB\xDE\x17\x8D\xDD\x3A\xE9\x1A\x85\x81\xB9\x16\x82\xD8\x60\xF8\x40\x78\x2F\x6E\xEA\x49\xDB\xB9\xBD\x72\x15\x01\xD2\xC6\x71\x22\xDE\xA3\xB7\x28\x38\x48\xC5\xF1\x3E\x0C\x0D\xE8\x76\xBD\x22\x7A\x85\x6E\x4D\xE5\x93\xA3")+    , ( 20+       , "\x9E\x1D\xA2\x39\xD1\x55\xF5\x2A\xD3\x7F\x75\xC7\x36\x8A\x53\x66\x68\xB0\x51\x95\x29\x23\xAD\x44\xF5\x7E\x75\xAB\x58\x8E\x47\x5A"+       , "\xAF\x06\xF1\x78\x59\xDF\xFA\x79\x98\x91\xC4\x28\x8F\x66\x35\xB5\xC5\xA4\x5E\xEE\x90\x17\xFD\x72"+       , "\xFE\xAC\x9D\x54\xFC\x8C\x11\x5A\xE2\x47\xD9\xA7\xE9\x19\xDD\x76\xCF\xCB\xC7\x2D\x32\xCA\xE4\x94\x48\x60\x81\x7C\xBD\xFB\x8C\x04\xE6\xB1\xDF\x76\xA1\x65\x17\xCD\x33\xCC\xF1\xAC\xDA\x92\x06\x38\x9E\x9E\x31\x8F\x59\x66\xC0\x93\xCF\xB3\xEC\x2D\x9E\xE2\xDE\x85\x64\x37\xED\x58\x1F\x55\x2F\x26\xAC\x29\x07\x60\x9D\xF8\xC6\x13\xB9\xE3\x3D\x44\xBF\xC2\x1F\xF7\x91\x53\xE9\xEF\x81\xA9\xD6\x6C\xC3\x17\x85\x7F\x75\x2C\xC1\x75\xFD\x88\x91\xFE\xFE\xBB\x7D\x04\x1E\x65\x17\xC3\x16\x2D\x19\x7E\x21\x12\x83\x7D\x3B\xC4\x10\x43\x12\xAD\x35\xB7\x5E\xA6\x86\xE7\xC7\x0D\x4E\xC0\x47\x46\xB5\x2F\xF0\x9C\x42\x14\x51\x45\x9F\xB5\x9F"+       , "\x2C\x26\x1A\x2F\x4E\x61\xA6\x2E\x1B\x27\x68\x99\x16\xBF\x03\x45\x3F\xCB\xC9\x7B\xB2\xAF\x6F\x32\x93\x91\xEF\x06\x3B\x5A\x21\x9B\xF9\x84\xD0\x7D\x70\xF6\x02\xD8\x5F\x6D\xB6\x14\x74\xE9\xD9\xF5\xA2\xDE\xEC\xB4\xFC\xD9\x01\x84\xD1\x6F\x3B\x5B\x5E\x16\x8E\xE0\x3E\xA8\xC9\x3F\x39\x33\xA2\x2B\xC3\xD1\xA5\xAE\x8C\x2D\x8B\x02\x75\x7C\x87\xC0\x73\x40\x90\x52\xA2\xA8\xA4\x1E\x7F\x48\x7E\x04\x1F\x9A\x49\xA0\x99\x7B\x54\x0E\x18\x62\x1C\xAD\x3A\x24\xF0\xA5\x6D\x9B\x19\x22\x79\x29\x05\x7A\xB3\xBA\x95\x0F\x62\x74\xB1\x21\xF1\x93\xE3\x2E\x06\xE5\x38\x87\x81\xA1\xCB\x57\x31\x7C\x0B\xA6\x30\x5E\x91\x09\x61\xD0\x10\x02\xF0")+    , ( 20+       , "\xD5\xC7\xF6\x79\x7B\x7E\x7E\x9C\x1D\x7F\xD2\x61\x0B\x2A\xBF\x2B\xC5\xA7\x88\x5F\xB3\xFF\x78\x09\x2F\xB3\xAB\xE8\x98\x6D\x35\xE2"+       , "\x74\x4E\x17\x31\x2B\x27\x96\x9D\x82\x64\x44\x64\x0E\x9C\x4A\x37\x8A\xE3\x34\xF1\x85\x36\x9C\x95"+       , "\x77\x58\x29\x8C\x62\x8E\xB3\xA4\xB6\x96\x3C\x54\x45\xEF\x66\x97\x12\x22\xBE\x5D\x1A\x4A\xD8\x39\x71\x5D\x11\x88\x07\x17\x39\xB7\x7C\xC6\xE0\x5D\x54\x10\xF9\x63\xA6\x41\x67\x62\x97\x57"+       , "\x27\xB8\xCF\xE8\x14\x16\xA7\x63\x01\xFD\x1E\xEC\x6A\x4D\x99\x67\x50\x69\xB2\xDA\x27\x76\xC3\x60\xDB\x1B\xDF\xEA\x7C\x0A\xA6\x13\x91\x3E\x10\xF7\xA6\x0F\xEC\x04\xD1\x1E\x65\xF2\xD6\x4E")+    , ( 20+       , "\x73\x7D\x78\x11\xCE\x96\x47\x2E\xFE\xD1\x22\x58\xB7\x81\x22\xF1\x1D\xEA\xEC\x87\x59\xCC\xBD\x71\xEA\xC6\xBB\xEF\xA6\x27\x78\x5C"+       , "\x6F\xB2\xEE\x3D\xDA\x6D\xBD\x12\xF1\x27\x4F\x12\x67\x01\xEC\x75\xC3\x5C\x86\x60\x7A\xDB\x3E\xDD"+       , "\x50\x13\x25\xFB\x26\x45\x26\x48\x64\xDF\x11\xFA\xA1\x7B\xBD\x58\x31\x2B\x77\xCA\xD3\xD9\x4A\xC8\xFB\x85\x42\xF0\xEB\x65\x3A\xD7\x3D\x7F\xCE\x93\x2B\xB8\x74\xCB\x89\xAC\x39\xFC\x47\xF8\x26\x7C\xF0\xF0\xC2\x09\xF2\x04\xB2\xD8\x57\x8A\x3B\xDF\x46\x1C\xB6\xA2\x71\xA4\x68\xBE\xBA\xCC\xD9\x68\x50\x14\xCC\xBC\x9A\x73\x61\x8C\x6A\x5E\x77\x8A\x21\xCC\x84\x16\xC6\x0A\xD2\x4D\xDC\x41\x7A\x13\x0D\x53\xED\xA6\xDF\xBF\xE4\x7D\x09\x17\x0A\x7B\xE1\xA7\x08\xB7\xB5\xF3\xAD\x46\x43\x10\xBE\x36\xD9\xA2\xA9\x5D\xC3\x9E\x83\xD3\x86\x67\xE8\x42\xEB\x64\x11\xE8\xA2\x37\x12\x29\x7B\x16\x5F\x69\x0C\x2D\x7C\xA1\xB1\x34\x6E\x3C\x1F\xCC\xF5\xCA\xFD\x4F\x8B\xE0"+       , "\x67\x24\xC3\x72\xD2\xE9\x07\x4D\xA5\xE2\x7A\x6C\x54\xB2\xD7\x03\xDC\x1D\x4C\x9B\x1F\x8D\x90\xF0\x0C\x12\x2E\x69\x2A\xCE\x77\x00\xEA\xDC\xA9\x42\x54\x45\x07\xF1\x37\x5B\x65\x81\xD5\xA8\xFB\x39\x98\x1C\x1C\x0E\x6E\x1F\xF2\x14\x0B\x08\x2E\x9E\xC0\x16\xFC\xE1\x41\xD5\x19\x96\x47\xD4\x3B\x0B\x68\xBF\xD0\xFE\xA5\xE0\x0F\x46\x89\x62\xC7\x38\x4D\xD6\x12\x9A\xEA\x6A\x3F\xDF\xE7\x5A\xBB\x21\x0E\xD5\x60\x7C\xEF\x8F\xA0\xE1\x52\x83\x3D\x5A\xC3\x7D\x52\xE5\x57\xB9\x10\x98\xA3\x22\xE7\x6A\x45\xBB\xBC\xF4\x89\x9E\x79\x06\x18\xAA\x3F\x4C\x2E\x5E\x0F\xC3\xDE\x93\x26\x9A\x57\x7D\x77\xA5\x50\x2E\x8E\xA0\x2F\x71\x7B\x1D\xD2\xDF\x1E\xC6\x9D\x8B\x61\xCA")+    , ( 20+       , "\x76\x01\x58\xDA\x09\xF8\x9B\xBA\xB2\xC9\x9E\x69\x97\xF9\x52\x3A\x95\xFC\xEF\x10\x23\x9B\xCC\xA2\x57\x3B\x71\x05\xF6\x89\x8D\x34"+       , "\x43\x63\x6B\x2C\xC3\x46\xFC\x8B\x7C\x85\xA1\x9B\xF5\x07\xBD\xC3\xDA\xFE\x95\x3B\x88\xC6\x9D\xBA"+       , "\xD3\x0A\x6D\x42\xDF\xF4\x9F\x0E\xD0\x39\xA3\x06\xBA\xE9\xDE\xC8\xD9\xE8\x83\x66\xCC\x19\xE8\xC3\x64\x2F\xD5\x8F\xA0\x79\x4E\xBF\x80\x29\xD9\x49\x73\x03\x39\xB0\x82\x3A\x51\xF0\xF4\x9F\x0D\x2C\x71\xF1\x05\x1C\x1E\x0E\x2C\x86\x94\x1F\x17\x27\x89\xCD\xB1\xB0\x10\x74\x13\xE7\x0F\x98\x2F\xF9\x76\x18\x77\xBB\x52\x6E\xF1\xC3\xEB\x11\x06\xA9\x48\xD6\x0E\xF2\x1B\xD3\x5D\x32\xCF\xD6\x4F\x89\xB7\x9E\xD6\x3E\xCC\x5C\xCA\x56\x24\x6A\xF7\x36\x76\x6F\x28\x5D\x8E\x6B\x0D\xA9\xCB\x1C\xD2\x10\x20\x22\x3F\xFA\xCC\x5A\x32"+       , "\xC8\x15\xB6\xB7\x9B\x64\xF9\x36\x9A\xEC\x8D\xCE\x8C\x75\x3D\xF8\xA5\x0F\x2B\xC9\x7C\x70\xCE\x2F\x01\x4D\xB3\x3A\x65\xAC\x58\x16\xBA\xC9\xE3\x0A\xC0\x8B\xDD\xED\x30\x8C\x65\xCB\x87\xE2\x8E\x2E\x71\xB6\x77\xDC\x25\xC5\xA6\x49\x9C\x15\x53\x55\x5D\xAF\x1F\x55\x27\x0A\x56\x95\x9D\xFF\xA0\xC6\x6F\x24\xE0\xAF\x00\x95\x1E\xC4\xBB\x59\xCC\xC3\xA6\xC5\xF5\x2E\x09\x81\x64\x7E\x53\xE4\x39\x31\x3A\x52\xC4\x0F\xA7\x00\x4C\x85\x5B\x6E\x6E\xB2\x5B\x21\x2A\x13\x8E\x84\x3A\x9B\xA4\x6E\xDB\x2A\x03\x9E\xE8\x2A\x26\x3A\xBE")+    , ( 20+       , "\x27\xBA\x7E\x81\xE7\xED\xD4\xE7\x1B\xE5\x3C\x07\xCE\x8E\x63\x31\x38\xF2\x87\xE1\x55\xC7\xFA\x9E\x84\xC4\xAD\x80\x4B\x7F\xA1\xB9"+       , "\xEA\x05\xF4\xEB\xCD\x2F\xB6\xB0\x00\xDA\x06\x12\x86\x1B\xA5\x4F\xF5\xC1\x76\xFB\x60\x13\x91\xAA"+       , "\xE0\x9F\xF5\xD2\xCB\x05\x0D\x69\xB2\xD4\x24\x94\xBD\xE5\x82\x52\x38\xC7\x56\xD6\x99\x1D\x99\xD7\xA2\x0D\x1E\xF0\xB8\x3C\x37\x1C\x89\x87\x26\x90\xB2\xFC\x11\xD5\x36\x9F\x4F\xC4\x97\x1B\x6D\x3D\x6C\x07\x8A\xEF\x9B\x0F\x05\xC0\xE6\x1A\xB8\x9C\x02\x51\x68\x05\x4D\xEF\xEB\x03\xFE\xF6\x33\x85\x87\x00\xC5\x8B\x12\x62\xCE\x01\x13\x00\x01\x26\x73\xE8\x93\xE4\x49\x01\xDC\x18\xEE\xE3\x10\x56\x99\xC4\x4C\x80\x58\x97\xBD\xAF\x77\x6A\xF1\x83\x31\x62\xA2\x1A"+       , "\xA2\x3E\x7E\xF9\x3C\x5D\x06\x67\xC9\x6D\x9E\x40\x4D\xCB\xE6\xBE\x62\x02\x6F\xA9\x8F\x7A\x3F\xF9\xBA\x5D\x45\x86\x43\xA1\x6A\x1C\xEF\x72\x72\xDC\x60\x97\xA9\xB5\x2F\x35\x98\x35\x57\xC7\x7A\x11\xB3\x14\xB4\xF7\xD5\xDC\x2C\xCA\x15\xEE\x47\x61\x6F\x86\x18\x73\xCB\xFE\xD1\xD3\x23\x72\x17\x1A\x61\xE3\x8E\x44\x7F\x3C\xF3\x62\xB3\xAB\xBB\x2E\xD4\x17\x0D\x89\xDC\xB2\x81\x87\xB7\xBF\xD2\x06\xA3\xE0\x26\xF0\x84\xA7\xE0\xED\x63\xD3\x19\xDE\x6B\xC9\xAF\xC0")+    , ( 20+       , "\x67\x99\xD7\x6E\x5F\xFB\x5B\x49\x20\xBC\x27\x68\xBA\xFD\x3F\x8C\x16\x55\x4E\x65\xEF\xCF\x9A\x16\xF4\x68\x3A\x7A\x06\x92\x7C\x11"+       , "\x61\xAB\x95\x19\x21\xE5\x4F\xF0\x6D\x9B\x77\xF3\x13\xA4\xE4\x9D\xF7\xA0\x57\xD5\xFD\x62\x79\x89"+       , "\x47\x27\x66"+       , "\x8F\xD7\xDF")+    , ( 20+        , "\xF6\x82\x38\xC0\x83\x65\xBB\x29\x3D\x26\x98\x0A\x60\x64\x88\xD0\x9C\x2F\x10\x9E\xDA\xFA\x0B\xBA\xE9\x93\x7B\x5C\xC2\x19\xA4\x9C"+        , "\x51\x90\xB5\x1E\x9B\x70\x86\x24\x82\x0B\x5A\xBD\xF4\xE4\x0F\xAD\x1F\xB9\x50\xAD\x1A\xDC\x2D\x26"+        , "\x47\xEC\x6B\x1F\x73\xC4\xB7\xFF\x52\x74\xA0\xBF\xD7\xF4\x5F\x86\x48\x12\xC8\x5A\x12\xFB\xCB\x3C\x2C\xF8\xA3\xE9\x0C\xF6\x6C\xCF\x2E\xAC\xB5\x21\xE7\x48\x36\x3C\x77\xF5\x2E\xB4\x26\xAE\x57\xA0\xC6\xC7\x8F\x75\xAF\x71\x28\x45\x69\xE7\x9D\x1A\x92\xF9\x49\xA9\xD6\x9C\x4E\xFC\x0B\x69\x90\x2F\x1E\x36\xD7\x56\x27\x65\x54\x3E\x2D\x39\x42\xD9\xF6\xFF\x59\x48\xD8\xA3\x12\xCF\xF7\x2C\x1A\xFD\x9E\xA3\x08\x8A\xFF\x76\x40\xBF\xD2\x65\xF7\xA9\x94\x6E\x60\x6A\xBC\x77\xBC\xED\xAE\x6B\xDD\xC7\x5A\x0D\xBA\x0B\xD9\x17\xD7\x3E\x3B\xD1\x26\x8F\x72\x7E\x00\x96\x34\x5D\xA1\xED\x25\xCF\x55\x3E\xA7\xA9\x8F\xEA\x6B\x6F\x28\x57\x32\xDE\x37\x43\x15\x61\xEE\x1B\x30\x64\x88\x7F\xBC\xBD\x71\x93\x5E\x02"+        , "\x36\x16\x0E\x88\xD3\x50\x05\x29\xBA\x4E\xDB\xA1\x7B\xC2\x4D\x8C\xFA\xCA\x9A\x06\x80\xB3\xB1\xFC\x97\xCF\x03\xF3\x67\x5B\x7A\xC3\x01\xC8\x83\xA6\x8C\x07\x1B\xC5\x4A\xCD\xD3\xB6\x3A\xF4\xA2\xD7\x2F\x98\x5E\x51\xF9\xD6\x0A\x4C\x7F\xD4\x81\xAF\x10\xB2\xFC\x75\xE2\x52\xFD\xEE\x7E\xA6\xB6\x45\x31\x90\x61\x7D\xCC\x6E\x2F\xE1\xCD\x56\x58\x5F\xC2\xF0\xB0\xE9\x7C\x5C\x3F\x8A\xD7\xEB\x4F\x31\xBC\x48\x90\xC0\x38\x82\xAA\xC2\x4C\xC5\x3A\xCC\x19\x82\x29\x65\x26\x69\x0A\x22\x02\x71\xC2\xF6\xE3\x26\x75\x0D\x3F\xBD\xA5\xD5\xB6\x35\x12\xC8\x31\xF6\x78\x30\xF5\x9A\xC4\x9A\xAE\x33\x0B\x3E\x0E\x02\xC9\xEA\x00\x91\xD1\x98\x41\xF1\xB0\xE1\x3D\x69\xC9\xFB\xFE\x8A\x12\xD6\xF3\x0B\xB7\x34\xD9\xD2")+    , ( 20+       , "\x45\xB2\xBD\x0D\xE4\xED\x92\x93\xEC\x3E\x26\xC4\x84\x0F\xAA\xF6\x4B\x7D\x61\x9D\x51\xE9\xD7\xA2\xC7\xE3\x6C\x83\xD5\x84\xC3\xDF"+       , "\x54\x6C\x8C\x5D\x6B\xE8\xF9\x09\x52\xCA\xB3\xF3\x6D\x7C\x19\x57\xBA\xAA\x7A\x59\xAB\xE3\xD7\xE5"+       , "\x50\x07\xC8\xCD\x5B\x3C\x40\xE1\x7D\x7F\xE4\x23\xA8\x7A\xE0\xCE\xD8\x6B\xEC\x1C\x39\xDC\x07\xA2\x57\x72\xF3\xE9\x6D\xAB\xD5\x6C\xD3\xFD\x73\x19\xF6\xC9\x65\x49\x25\xF2\xD8\x70\x87\xA7\x00\xE1\xB1\x30\xDA\x79\x68\x95\xD1\xC9\xB9\xAC\xD6\x2B\x26\x61\x44\x06\x7D\x37\x3E\xD5\x1E\x78\x74\x98\xB0\x3C\x52\xFA\xAD\x16\xBB\x38\x26\xFA\x51\x1B\x0E\xD2\xA1\x9A\x86\x63\xF5\xBA\x2D\x6E\xA7\xC3\x8E\x72\x12\xE9\x69\x7D\x91\x48\x6C\x49\xD8\xA0\x00\xB9\xA1\x93\x5D\x6A\x7F\xF7\xEF\x23\xE7\x20\xA4\x58\x55\x48\x14\x40\x46\x3B\x4A\xC8\xC4\xF6\xE7\x06\x2A\xDC\x1F\x1E\x1E\x25\xD3\xD6\x5A\x31\x81\x2F\x58\xA7\x11\x60"+       , "\x8E\xAC\xFB\xA5\x68\x89\x8B\x10\xC0\x95\x7A\x7D\x44\x10\x06\x85\xE8\x76\x3A\x71\xA6\x9A\x8D\x16\xBC\x7B\x3F\x88\x08\x5B\xB9\xA2\xF0\x96\x42\xE4\xD0\x9A\x9F\x0A\xD0\x9D\x0A\xAD\x66\xB2\x26\x10\xC8\xBD\x02\xFF\x66\x79\xBB\x92\xC2\xC0\x26\xA2\x16\xBF\x42\x5C\x6B\xE3\x5F\xB8\xDA\xE7\xFF\x0C\x72\xB0\xEF\xD6\xA1\x80\x37\xC7\x0E\xED\x0C\xA9\x00\x62\xA4\x9A\x3C\x97\xFD\xC9\x0A\x8F\x9C\x2E\xA5\x36\xBF\xDC\x41\x91\x8A\x75\x82\xC9\x92\x7F\xAE\x47\xEF\xAA\x3D\xC8\x79\x67\xB7\x88\x7D\xEE\x1B\xF0\x71\x73\x4C\x76\x65\x90\x1D\x91\x05\xDA\xE2\xFD\xF6\x6B\x49\x18\xE5\x1D\x8F\x4A\x48\xC6\x0D\x19\xFB\xFB\xBC\xBA")+    , ( 20+       , "\xFE\x55\x9C\x9A\x28\x2B\xEB\x40\x81\x4D\x01\x6D\x6B\xFC\xB2\xC0\xC0\xD8\xBF\x07\x7B\x11\x10\xB8\x70\x3A\x3C\xE3\x9D\x70\xE0\xE1"+       , "\xB0\x76\x20\x0C\xC7\x01\x12\x59\x80\x5E\x18\xB3\x04\x09\x27\x54\x00\x27\x23\xEB\xEC\x5D\x62\x00"+       , "\x6D\xB6\x5B\x9E\xC8\xB1\x14\xA9\x44\x13\x7C\x82\x1F\xD6\x06\xBE\x75\x47\x8D\x92\x83\x66\xD5\x28\x40\x96\xCD\xEF\x78\x2F\xCF\xF7\xE8\xF5\x9C\xB8\xFF\xCD\xA9\x79\x75\x79\x02\xC5\xFF\xA6\xBC\x47\x7C\xEA\xA4\xCB\x5D\x5E\xA7\x6F\x94\xD9\x1E\x83\x3F\x82\x3A\x6B\xC7\x8F\x10\x55\xDF\xA6\xA9\x7B\xEA\x89\x65\xC1\xCD\xE6\x7A\x66\x8E\x00\x12\x57\x33\x4A\x58\x57\x27\xD9\xE0\xF7\xC1\xA0\x6E\x88\xD3\xD2\x5A\x4E\x6D\x90\x96\xC9\x68\xBF\x13\x8E\x11\x6A\x3E\xBE\xFF\xD4\xBB\x48\x08\xAD\xB1\xFD\x69\x81\x64\xBA\x0A\x35\xC7\x09\xA4\x7F\x16\xF1\xF4\x43\x5A\x23\x45\xA9\x19\x4A\x00\xB9\x5A\xBD\x51\x85\x1D\x50\x58\x09\xA6\x07\x7D\xA9\xBA\xCA\x58\x31\xAF\xFF\x31\x57\x8C\x48\x7E\xE6\x8F\x27\x67\x97\x4A\x98\xA7\xE8\x03\xAA\xC7\x88\xDA\x98\x31\x9C\x4E\xA8\xEA\xA3\xD3\x94\x85\x56\x51\xF4\x84\xCE\xF5\x43\xF5\x37\xE3\x51\x58\xEE\x29"+       , "\x4D\xCE\x9C\x8F\x97\xA0\x28\x05\x1B\x07\x27\xF3\x4E\x1B\x9E\xF2\x1F\x06\xF0\x76\x0F\x36\xE7\x17\x13\x20\x40\x27\x90\x20\x90\xBA\x2B\xB6\xB1\x34\x36\xEE\x77\x8D\x9F\x50\x53\x0E\xFB\xD7\xA3\x2B\x0D\x41\x44\x3F\x58\xCC\xAE\xE7\x81\xC7\xB7\x16\xD3\xA9\x6F\xDE\xC0\xE3\x76\x4E\xD7\x95\x9F\x34\xC3\x94\x12\x78\x59\x1E\xA0\x33\xB5\xCB\xAD\xC0\xF1\x91\x60\x32\xE9\xBE\xBB\xD1\xA8\x39\x5B\x83\xFB\x63\xB1\x45\x4B\xD7\x75\xBD\x20\xB3\xA2\xA9\x6F\x95\x12\x46\xAC\x14\xDA\xF6\x81\x66\xBA\x62\xF6\xCB\xFF\x8B\xD1\x21\xAC\x94\x98\xFF\x88\x52\xFD\x2B\xE9\x75\xDF\x52\xB5\xDA\xEF\x38\x29\xD1\x8E\xDA\x42\xE7\x15\x02\x2D\xCB\xF9\x30\xD0\xA7\x89\xEE\x6A\x14\x6C\x2C\x70\x88\xC3\x57\x73\xC6\x3C\x06\xB4\xAF\x45\x59\x85\x6A\xC1\x99\xCE\xD8\x68\x63\xE4\x29\x47\x07\x82\x53\x37\xC5\x85\x79\x70\xEB\x7F\xDD\xEB\x26\x37\x81\x30\x90\x11")+    , ( 20+       , "\x0A\xE1\x00\x12\xD7\xE5\x66\x14\xB0\x3D\xCC\x89\xB1\x4B\xAE\x92\x42\xFF\xE6\x30\xF3\xD7\xE3\x5C\xE8\xBB\xB9\x7B\xBC\x2C\x92\xC3"+       , "\xF9\x6B\x02\x5D\x6C\xF4\x6A\x8A\x12\xAC\x2A\xF1\xE2\xAE\xF1\xFB\x83\x59\x0A\xDA\xDA\xA5\xC5\xEA"+       , "\xEA\x0F\x35\x4E\x96\xF1\x2B\xC7\x2B\xBA\xA3\xD1\x2B\x4A\x8E\xD8\x79\xB0\x42\xF0\x68\x98\x78\xF4\x6B\x65\x1C\xC4\x11\x6D\x6F\x78\x40\x9B\x11\x43\x0B\x3A\xAA\x30\xB2\x07\x68\x91\xE8\xE1\xFA\x52\x8F\x2F\xD1\x69\xED\x93\xDC\x9F\x84\xE2\x44\x09\xEE\xC2\x10\x1D\xAF\x4D\x05\x7B\xE2\x49\x2D\x11\xDE\x64\x0C\xBD\x7B\x35\x5A\xD2\x9F\xB7\x04\x00\xFF\xFD\x7C\xD6\xD4\x25\xAB\xEE\xB7\x32\xA0\xEA\xA4\x33\x0A\xF4\xC6\x56\x25\x2C\x41\x73\xDE\xAB\x65\x3E\xB8\x5C\x58\x46\x2D\x7A\xB0\xF3\x5F\xD1\x2B\x61\x3D\x29\xD4\x73\xD3\x30\x31\x0D\xC3\x23\xD3\xC6\x63\x48\xBB\xDB\xB6\x8A\x32\x63\x24\x65\x7C\xAE\x7B\x77\xA9\xE3\x43\x58\xF2\xCE\xC5\x0C\x85\x60\x9E\x73\x05\x68\x56\x79\x6E\x3B\xE8\xD6\x2B\x6E\x2F\xE9\xF9\x53"+       , "\xE8\xAB\xD4\x89\x24\xB5\x4E\x5B\x80\x86\x6B\xE7\xD4\xEB\xE5\xCF\x42\x74\xCA\xFF\xF0\x8B\x39\xCB\x2D\x40\xA8\xF0\xB4\x72\x39\x8A\xED\xC7\x76\xE0\x79\x38\x12\xFB\xF1\xF6\x00\x78\x63\x5D\x2E\xD8\x6B\x15\xEF\xCD\xBA\x60\x41\x1E\xE2\x3B\x07\x23\x35\x92\xA4\x4E\xC3\x1B\x10\x13\xCE\x89\x64\x23\x66\x75\xF8\xF1\x83\xAE\xF8\x85\xE8\x64\xF2\xA7\x2E\xDF\x42\x15\xB5\x33\x8F\xA2\xB5\x46\x53\xDF\xA1\xA8\xC5\x5C\xE5\xD9\x5C\xC6\x05\xB9\xB3\x11\x52\x7F\x2E\x34\x63\xFF\xBE\xC7\x8A\x9D\x1D\x65\xDA\xBA\xD2\xF3\x38\x76\x9C\x9F\x43\xF1\x33\xA7\x91\xA1\x1C\x7E\xCA\x9A\xF0\xB7\x71\xA4\xAC\x32\x96\x3D\xC8\xF6\x31\xA2\xC1\x12\x17\xAC\x6E\x1B\x94\x30\xC1\xAA\xE1\xCE\xEB\xE2\x27\x03\xF4\x29\x99\x8A\x8F\xB8\xC6\x41")+    , ( 20+       , "\x08\x2C\x53\x9B\xC5\xB2\x0F\x97\xD7\x67\xCD\x3F\x22\x9E\xDA\x80\xB2\xAD\xC4\xFE\x49\xC8\x63\x29\xB5\xCD\x62\x50\xA9\x87\x74\x50"+       , "\x84\x55\x43\x50\x2E\x8B\x64\x91\x2D\x8F\x2C\x8D\x9F\xFF\xB3\xC6\x93\x65\x68\x65\x87\xC0\x8D\x0C"+       , "\xA9\x6B\xB7\xE9\x10\x28\x1A\x6D\xFA\xD7\xC8\xA9\xC3\x70\x67\x4F\x0C\xEE\xC1\xAD\x8D\x4F\x0D\xE3\x2F\x9A\xE4\xA2\x3E\xD3\x29\xE3\xD6\xBC\x70\x8F\x87\x66\x40\xA2\x29\x15\x3A\xC0\xE7\x28\x1A\x81\x88\xDD\x77\x69\x51\x38\xF0\x1C\xDA\x5F\x41\xD5\x21\x5F\xD5\xC6\xBD\xD4\x6D\x98\x2C\xB7\x3B\x1E\xFE\x29\x97\x97\x0A\x9F\xDB\xDB\x1E\x76\x8D\x7E\x5D\xB7\x12\x06\x8D\x8B\xA1\xAF\x60\x67\xB5\x75\x34\x95\xE2\x3E\x6E\x19\x63\xAF\x01\x2F\x9C\x7C\xE4\x50\xBF\x2D\xE6\x19\xD3\xD5\x95\x42\xFB\x55\xF3"+       , "\x83\x5D\xA7\x4F\xC6\xDE\x08\xCB\xDA\x27\x7A\x79\x66\xA0\x7C\x8D\xCD\x62\x7E\x7B\x17\xAD\xDE\x6D\x93\x0B\x65\x81\xE3\x12\x4B\x8B\xAA\xD0\x96\xF6\x93\x99\x1F\xED\xB1\x57\x29\x30\x60\x1F\xC7\x70\x95\x41\x83\x9B\x8E\x3F\xFD\x5F\x03\x3D\x20\x60\xD9\x99\xC6\xC6\xE3\x04\x82\x76\x61\x3E\x64\x80\x00\xAC\xB5\x21\x2C\xC6\x32\xA9\x16\xAF\xCE\x29\x0E\x20\xEB\xDF\x61\x2D\x08\xA6\xAA\x4C\x79\xA7\x4B\x07\x0D\x3F\x87\x2A\x86\x1F\x8D\xC6\xBB\x07\x61\x4D\xB5\x15\xD3\x63\x34\x9D\x3A\x8E\x33\x36\xA3")+    , ( 20+       , "\x3D\x02\xBF\xF3\x37\x5D\x40\x30\x27\x35\x6B\x94\xF5\x14\x20\x37\x37\xEE\x9A\x85\xD2\x05\x2D\xB3\xE4\xE5\xA2\x17\xC2\x59\xD1\x8A"+       , "\x74\x21\x6C\x95\x03\x18\x95\xF4\x8C\x1D\xBA\x65\x15\x55\xEB\xFA\x3C\xA3\x26\xA7\x55\x23\x70\x25"+       , "\x0D\x4B\x0F\x54\xFD\x09\xAE\x39\xBA\xA5\xFA\x4B\xAC\xCF\x2E\x66\x82\xE6\x1B\x25\x7E\x01\xF4\x2B\x8F"+       , "\x16\xC4\x00\x6C\x28\x36\x51\x90\x41\x1E\xB1\x59\x38\x14\xCF\x15\xE7\x4C\x22\x23\x8F\x21\x0A\xFC\x3D")+    , ( 20+       , "\xAD\x1A\x5C\x47\x68\x88\x74\xE6\x66\x3A\x0F\x3F\xA1\x6F\xA7\xEF\xB7\xEC\xAD\xC1\x75\xC4\x68\xE5\x43\x29\x14\xBD\xB4\x80\xFF\xC6"+       , "\xE4\x89\xEE\xD4\x40\xF1\xAA\xE1\xFA\xC8\xFB\x7A\x98\x25\x63\x54\x54\xF8\xF8\xF1\xF5\x2E\x2F\xCC"+       , "\xAA\x6C\x1E\x53\x58\x0F\x03\xA9\xAB\xB7\x3B\xFD\xAD\xED\xFE\xCA\xDA\x4C\x6B\x0E\xBE\x02\x0E\xF1\x0D\xB7\x45\xE5\x4B\xA8\x61\xCA\xF6\x5F\x0E\x40\xDF\xC5\x20\x20\x3B\xB5\x4D\x29\xE0\xA8\xF7\x8F\x16\xB3\xF1\xAA\x52\x5D\x6B\xFA\x33\xC5\x47\x26\xE5\x99\x88\xCF\xBE\xC7\x80\x56"+       , "\x02\xFE\x84\xCE\x81\xE1\x78\xE7\xAA\xBD\xD3\xBA\x92\x5A\x76\x6C\x3C\x24\x75\x6E\xEF\xAE\x33\x94\x2A\xF7\x5E\x8B\x46\x45\x56\xB5\x99\x7E\x61\x6F\x3F\x2D\xFC\x7F\xCE\x91\x84\x8A\xFD\x79\x91\x2D\x9F\xB5\x52\x01\xB5\x81\x3A\x5A\x07\x4D\x2C\x0D\x42\x92\xC1\xFD\x44\x18\x07\xC5")+    , ( 20+       , "\x05\x3A\x02\xBE\xDD\x63\x68\xC1\xFB\x8A\xFC\x7A\x1B\x19\x9F\x7F\x7E\xA2\x22\x0C\x9A\x4B\x64\x2A\x68\x50\x09\x1C\x9D\x20\xAB\x9C"+       , "\xC7\x13\xEE\xA5\xC2\x6D\xAD\x75\xAD\x3F\x52\x45\x1E\x00\x3A\x9C\xB0\xD6\x49\xF9\x17\xC8\x9D\xDE"+       , "\x8F\x0A\x8A\x16\x47\x60\x42\x65\x67\xE3\x88\x84\x02\x76\xDE\x3F\x95\xCB\x5E\x3F\xAD\xC6\xED\x3F\x3E\x4F\xE8\xBC\x16\x9D\x93\x88\x80\x4D\xCB\x94\xB6\x58\x7D\xBB\x66\xCB\x0B\xD5\xF8\x7B\x8E\x98\xB5\x2A\xF3\x7B\xA2\x90\x62\x9B\x85\x8E\x0E\x2A\xA7\x37\x80\x47\xA2\x66\x02"+       , "\x51\x67\x10\xE5\x98\x43\xE6\xFB\xD4\xF2\x5D\x0D\x8C\xA0\xEC\x0D\x47\xD3\x9D\x12\x5E\x9D\xAD\x98\x7E\x05\x18\xD4\x91\x07\x01\x4C\xB0\xAE\x40\x5E\x30\xC2\xEB\x37\x94\x75\x0B\xCA\x14\x2C\xE9\x5E\x29\x0C\xF9\x5A\xBE\x15\xE8\x22\x82\x3E\x2E\x7D\x3A\xB2\x1B\xC8\xFB\xD4\x45")+    , ( 20+       ,"\x5B\x14\xAB\x0F\xBE\xD4\xC5\x89\x52\x54\x8A\x6C\xB1\xE0\x00\x0C\xF4\x48\x14\x21\xF4\x12\x88\xEA\x0A\xA8\x4A\xDD\x9F\x7D\xEB\x96"+       , "\x54\xBF\x52\xB9\x11\x23\x1B\x95\x2B\xA1\xA6\xAF\x8E\x45\xB1\xC5\xA2\x9D\x97\xE2\xAB\xAD\x7C\x83"+       , "\x37\xFB\x44\xA6\x75\x97\x8B\x56\x0F\xF9\xA4\xA8\x70\x11\xD6\xF3\xAD\x2D\x37\xA2\xC3\x81\x5B\x45\xA3\xC0\xE6\xD1\xB1\xD8\xB1\x78\x4C\xD4\x68\x92\x7C\x2E\xE3\x9E\x1D\xCC\xD4\x76\x5E\x1C\x3D\x67\x6A\x33\x5B\xE1\xCC\xD6\x90\x0A\x45\xF5\xD4\x1A\x31\x76\x48\x31\x5D\x8A\x8C\x24\xAD\xC6\x4E\xB2\x85\xF6\xAE\xBA\x05\xB9\x02\x95\x86\x35\x3D\x30\x3F\x17\xA8\x07\x65\x8B\x9F\xF7\x90\x47\x4E\x17\x37\xBD\x5F\xDC\x60\x4A\xEF\xF8\xDF\xCA\xF1\x42\x7D\xCC\x3A\xAC\xBB\x02\x56\xBA\xDC\xD1\x83\xED\x75\xA2\xDC\x52\x45\x2F\x87\xD3\xC1\xED\x2A\xA5\x83\x47\x2B\x0A\xB9\x1C\xDA\x20\x61\x4E\x9B\x6F\xDB\xDA\x3B\x49\xB0\x98\xC9\x58\x23\xCC\x72\xD8\xE5\xB7\x17\xF2\x31\x4B\x03\x24\xE9\xCE"+       , "\xAE\x6D\xEB\x5D\x6C\xE4\x3D\x4B\x09\xD0\xE6\xB1\xC0\xE9\xF4\x61\x57\xBC\xD8\xAB\x50\xEA\xA3\x19\x7F\xF9\xFA\x2B\xF7\xAF\x64\x9E\xB5\x2C\x68\x54\x4F\xD3\xAD\xFE\x6B\x1E\xB3\x16\xF1\xF2\x35\x38\xD4\x70\xC3\x0D\xBF\xEC\x7E\x57\xB6\x0C\xBC\xD0\x96\xC7\x82\xE7\x73\x6B\x66\x91\x99\xC8\x25\x3E\x70\x21\x4C\xF2\xA0\x98\xFD\xA8\xEA\xC5\xDA\x79\xA9\x49\x6A\x3A\xAE\x75\x4D\x03\xB1\x7C\x6D\x70\xD1\x02\x7F\x42\xBF\x7F\x95\xCE\x3D\x1D\x9C\x33\x88\x54\xE1\x58\xFC\xC8\x03\xE4\xD6\x26\x2F\xB6\x39\x52\x1E\x47\x11\x6E\xF7\x8A\x7A\x43\x7C\xA9\x42\x7B\xA6\x45\xCD\x64\x68\x32\xFE\xAB\x82\x2A\x20\x82\x78\xE4\x5E\x93\xE1\x18\xD7\x80\xB9\x88\xD6\x53\x97\xED\xDF\xD7\xA8\x19\x52\x6E")+    , ( 20+       , "\xD7\x46\x36\xE3\x41\x3A\x88\xD8\x5F\x32\x2C\xA8\x0F\xB0\xBD\x65\x0B\xD0\xBF\x01\x34\xE2\x32\x91\x60\xB6\x96\x09\xCD\x58\xA4\xB0"+       , "\xEF\xB6\x06\xAA\x1D\x9D\x9F\x0F\x46\x5E\xAA\x7F\x81\x65\xF1\xAC\x09\xF5\xCB\x46\xFE\xCF\x2A\x57"+       , "\xF8\x54\x71\xB7\x5F\x6E\xC8\x1A\xBA\xC2\x79\x9E\xC0\x9E\x98\xE2\x80\xB2\xFF\xD6\x4C\xA2\x85\xE5\xA0\x10\x9C\xFB\x31\xFF\xAB\x2D\x61\x7B\x2C\x29\x52\xA2\xA8\xA7\x88\xFC\x0D\xA2\xAF\x7F\x53\x07\x58\xF7\x4F\x1A\xB5\x63\x91\xAB\x5F\xF2\xAD\xBC\xC5\xBE\x2D\x6C\x7F\x49\xFB\xE8\x11\x81\x04\xC6\xFF\x9A\x23\xC6\xDF\xE5\x2F\x57\x95\x4E\x6A\x69\xDC\xEE\x5D\xB0\x6F\x51\x4F\x4A\x0A\x57\x2A\x9A\x85\x25\xD9\x61\xDA\xE7\x22\x69\xB9\x87\x18\x9D\x46\x5D\xF6\x10\x71\x19\xC7\xFA\x79\x08\x53\xE0\x63\xCB\xA0\xFA\xB7\x80\x0C\xA9\x32\xE2\x58\x88\x0F\xD7\x4C\x33\xC7\x84\x67\x5B\xED\xAD\x0E\x7C\x09\xE9\xCC\x4D\x63\xDD\x5E\x97\x13\xD5\xD4\xA0\x19\x6E\x6B\x56\x22\x26\xAC\x31\xB4\xF5\x7C\x04\xF9\x0A\x18\x19\x73\x73\x7D\xDC\x7E\x80\xF3\x64\x11\x2A\x9F\xBB\x43\x5E\xBD\xBC\xAB\xF7\xD4\x90\xCE\x52"+       , "\xB2\xB7\x95\xFE\x6C\x1D\x4C\x83\xC1\x32\x7E\x01\x5A\x67\xD4\x46\x5F\xD8\xE3\x28\x13\x57\x5C\xBA\xB2\x63\xE2\x0E\xF0\x58\x64\xD2\xDC\x17\xE0\xE4\xEB\x81\x43\x6A\xDF\xE9\xF6\x38\xDC\xC1\xC8\xD7\x8F\x6B\x03\x06\xBA\xF9\x38\xE5\xD2\xAB\x0B\x3E\x05\xE7\x35\xCC\x6F\xFF\x2D\x6E\x02\xE3\xD6\x04\x84\xBE\xA7\xC7\xA8\xE1\x3E\x23\x19\x7F\xEA\x7B\x04\xD4\x7D\x48\xF4\xA4\xE5\x94\x41\x74\x53\x94\x92\x80\x0D\x3E\xF5\x1E\x2E\xE5\xE4\xC8\xA0\xBD\xF0\x50\xC2\xDD\x3D\xD7\x4F\xCE\x5E\x7E\x5C\x37\x36\x4F\x75\x47\xA1\x14\x80\xA3\x06\x3B\x9A\x0A\x15\x7B\x15\xB1\x0A\x5A\x95\x4D\xE2\x73\x1C\xED\x05\x5A\xA2\xE2\x76\x7F\x08\x91\xD4\x32\x9C\x42\x6F\x38\x08\xEE\x86\x7B\xED\x0D\xC7\x5B\x59\x22\xB7\xCF\xB8\x95\x70\x0F\xDA\x01\x61\x05\xA4\xC7\xB7\xF0\xBB\x90\xF0\x29\xF6\xBB\xCB\x04\xAC\x36\xAC\x16") +    ]++tests = testGroup "XSalsa"+    [ testGroup "KAT" $+        map (\(i,f) -> testCase (show (i :: Int)) f) $ zip [1..] $ map (\(r, k, i, p, e) -> salsaRunSimple r k i p e) vectors+    ]+  where+      salsaRunSimple rounds key nonce plain expected =+          let salsa = XSalsa.initialize rounds key nonce+          in fst (XSalsa.combine salsa plain) @?= expected