packages feed

NTRU 0.1.0.0 → 1.0.0.0

raw patch · 19 files changed

+939/−555 lines, 19 filesnew-uploaderPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- NTRU: decrypt112 :: (Num a, Eq a, Integral a) => [a] -> [a] -> [a] -> [a]
- NTRU: decrypt128 :: (Num a, Eq a, Integral a) => [a] -> [a] -> [a] -> [a]
- NTRU: decrypt192 :: (Num a, Eq a, Integral a) => [a] -> [a] -> [a] -> [a]
- NTRU: decrypt256 :: (Num a, Eq a, Integral a) => [a] -> [a] -> [a] -> [a]
- NTRU: encrypt112 :: (Num a, Eq a, Integral a) => [a] -> [a] -> IO [a]
- NTRU: encrypt128 :: (Num a, Eq a, Integral a) => [a] -> [a] -> IO [a]
- NTRU: encrypt192 :: (Num a, Eq a, Integral a) => [a] -> [a] -> IO [a]
- NTRU: encrypt256 :: (Num a, Eq a, Integral a) => [a] -> [a] -> IO [a]
- NTRU: instance (Num a, Eq a) => Num (Poly a)
- NTRU: keyGen112 :: (Num a, Eq a, Integral a) => IO ([a], [a])
- NTRU: keyGen128 :: (Num a, Eq a, Integral a) => IO ([a], [a])
- NTRU: keyGen192 :: (Num a, Eq a, Integral a) => IO ([a], [a])
- NTRU: keyGen256 :: (Num a, Eq a, Integral a) => IO ([a], [a])
+ Math.NTRU: ParamSet :: Int -> Integer -> Integer -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Integer -> Int -> [Int] -> Int -> Int -> ParamSet
+ Math.NTRU: data ParamSet
+ Math.NTRU: decrypt :: ParamSet -> [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU: encrypt :: ParamSet -> [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU: genParams :: String -> ParamSet
+ Math.NTRU: getBitLvl :: ParamSet -> Int
+ Math.NTRU: getBufferLenBits :: ParamSet -> Int
+ Math.NTRU: getBufferLenTrits :: ParamSet -> Int
+ Math.NTRU: getC :: ParamSet -> Int
+ Math.NTRU: getDb :: ParamSet -> Int
+ Math.NTRU: getDf :: ParamSet -> Int
+ Math.NTRU: getDg :: ParamSet -> Int
+ Math.NTRU: getDm0 :: ParamSet -> Int
+ Math.NTRU: getDr :: ParamSet -> Int
+ Math.NTRU: getLLen :: ParamSet -> Int
+ Math.NTRU: getMaxMsgLenBytes :: ParamSet -> Int
+ Math.NTRU: getMinCallsMask :: ParamSet -> Int
+ Math.NTRU: getMinCallsR :: ParamSet -> Integer
+ Math.NTRU: getN :: ParamSet -> Int
+ Math.NTRU: getOID :: ParamSet -> [Int]
+ Math.NTRU: getP :: ParamSet -> Integer
+ Math.NTRU: getPkLen :: ParamSet -> Int
+ Math.NTRU: getQ :: ParamSet -> Integer
+ Math.NTRU: getShaLvl :: ParamSet -> Int
+ Math.NTRU: instance (Num a, Eq a) => Num (Poly a)
+ Math.NTRU: instance Show ParamSet
+ Math.NTRU: keyGen :: ParamSet -> IO ([Integer], [Integer])
+ Math.NTRU.EES1087EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES1087EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES1087EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES1087EP2: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES1087EP2: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES1087EP2: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES1171EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES1171EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES1171EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES1499EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES1499EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES1499EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES401EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES401EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES401EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES449EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES449EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES449EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES541EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES541EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES541EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES613EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES613EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES613EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES659EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES659EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES659EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES677EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES677EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES677EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES761EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES761EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES761EP1: keyGen :: IO ([Integer], [Integer])
+ Math.NTRU.EES887EP1: decrypt :: [Integer] -> [Integer] -> [Integer] -> Maybe [Integer]
+ Math.NTRU.EES887EP1: encrypt :: [Integer] -> [Integer] -> IO [Integer]
+ Math.NTRU.EES887EP1: keyGen :: IO ([Integer], [Integer])

Files

LICENSE view
@@ -1,2 +1,25 @@-Do not steal+This software is provided free of use in accordance with the new BSD license:+Copyright (c) 2014, CyberPoint International, LLC+All rights reserved. +Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:+    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.+    * 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.+    * Neither the name of the CyberPoint International, LLC nor the+      names of its contributors may be used to endorse or promote products+      derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 CYBERPOINT INTERNATIONAL, LLC 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.
NTRU.cabal view
@@ -10,42 +10,61 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.1.0.0+version:             1.0.0.0  -- A short (one-line) description of the package.-synopsis: NTRU Cryptographic Library            +synopsis: NTRU Cryptography           -- A longer description of the package.-description: A Haskell implementation of the NTRU cryptographic system, following the IEEE Standard Specification for Public Key Crpytographic Techniques Based on Hard Problems over Lattices +description: A Haskell implementation of the NTRU cryptographic system, following the IEEE Standard Specification for Public Key Crpytographic Techniques Based on Hard Problems over Lattices (IEEE Std 1363.1-2008)  -- The license under which the package is released.-license:             MIT +license:             BSD3  -- The file containing the license text. license-file:        LICENSE  -- The package author(s).-author:              Theo Levine+author:              Theo Levine, Tom Cornelius, Elizabeth Hughes, CyberPoint International LLC.   -- An email address to which users can send suggestions, bug reports, and  -- patches.-maintainer:          tlevine@cyberpointllc.com+maintainer:          opensource@cyberpointllc.com  -- A copyright notice.--- copyright:           +copyright:           2014, CyberPoint International, LLC        -category:            Cryptography+category:            Cryptography, Math  build-type:          Simple +extra-source-files: README.md, examples/sampleGeneralNTRU.hs, examples/sampleSpecificNTRU.hs+ -- Constraint on the version of Cabal needed to build this package. cabal-version:       >=1.8   library++  hs-source-dirs:       src++  ghc-options:          -Wall+   -- Modules exported by the library.-  exposed-modules:     NTRU-  +  exposed-modules:     Math.NTRU+                       Math.NTRU.EES401EP1+                       Math.NTRU.EES449EP1+                       Math.NTRU.EES677EP1+                       Math.NTRU.EES1087EP2+                       Math.NTRU.EES541EP1+                       Math.NTRU.EES613EP1+                       Math.NTRU.EES887EP1+                       Math.NTRU.EES1171EP1+                       Math.NTRU.EES659EP1+                       Math.NTRU.EES761EP1+                       Math.NTRU.EES1087EP1+                       Math.NTRU.EES1499EP1                       +   -- Modules included in this library but not exported.   -- other-modules:          
− NTRU.hs
@@ -1,544 +0,0 @@-{- |  -Module      : NTRU-Description : NTRU cryptographic system implementation-Maintainer  : tlevine@cyberpointllc.com-Stability   : Experimental-License     : MIT-This is an implementation of the NTRU cryptographic system, following the standard set forth -by the IEEE in the document entitled IEEE Standard Specification for Public Key Cryptographic -Techniques Based on Hard Problems over Lattices. It is designed to be compatible with the implmentation-of SecurityInnovations, available <https://www.securityinnovation.com/products/encryption-libraries/ntru-crypto/ here>. --}----module NTRU (keyGen112, keyGen128, keyGen192, keyGen256, encrypt112, encrypt128, encrypt192, encrypt256, decrypt112, decrypt128, decrypt192, decrypt256) where--import Data.Digest.Pure.SHA-import Data.List.Split-import Data.Sequence as Seq (index, update, empty, fromList, Seq)-import Data.Foldable as L (toList)-import Crypto.Random-import System.Random-import Math.Polynomial-import Math.NumberTheory.Moduli -import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as BC-import qualified Data.ByteString.Lazy as BL--{- Polynomial Operations -} ---- | Poly to List-fromPoly :: (Num a, Eq a, Integral a) => Poly a -> [a]-fromPoly = polyCoeffs LE ---- | List to Poly-toPoly :: (Num a, Eq a, Integral a) => [a] -> Poly a  -toPoly = poly LE ---- | Retrive the coefficient of p corresponding to the (x^i) term -polyCoef :: (Num a, Eq a, Integral a) => Poly a -> Int -> a-polyCoef p i = fromPoly p !! i ---- | Useful for syntax. Allows for poly + poly or poly * poly. --- | Note that for ring multiplication, reduceDegree must be called-instance (Num a, Eq a) => Num (Poly a) where-  f + g = addPoly f g-  f * g = multPoly f g-  negate = negatePoly-  abs = undefined-  signum = undefined-  fromInteger = undefined---- | Allows for polynomial multiplaction in the ring of size n: reduceDegree (getDegree a) (a * b) = a * b in the ring-reduceDegree :: (Num a, Eq a, Integral a) => Int -> Poly a -> Poly a -reduceDegree n f =-  let (f1,f2) = splitAt n (fromPoly f) -  in toPoly f1 + toPoly f2 ---- | Reduces all of the polynomial's coefficents mod q-polyMod :: (Num a, Eq a, Integral a) => a -> Poly a -> Poly a-polyMod q f = toPoly $ map (`mod` q) (fromPoly f)---- | Same as polyMod, but chooses representative group values in Z/nZ to be in [-q/2, q/2] instead of [0,q-1]-polyModInterval :: (Num a, Eq a, Integral a) => a -> Poly a -> Poly a-polyModInterval q f = toPoly $ map (\x -> intervalReduce $ x `mod` q) (fromPoly f)  -  where intervalReduce x = if x <= (q `div` 2) then x else x - q---- | PolyMod when q is big -polyBigMod :: (Num a, Eq a, Integral a) => Int -> Poly a -> Poly a-polyBigMod q p = toPoly $ map fromIntegral $ fromPoly $ polyMod q $ toPoly $ map fromIntegral $ fromPoly p ---- | Creates the polynomial x^n-xPow :: (Num a, Eq a, Integral a) => Int -> Poly a -xPow = powPoly x---{- Key Generation -}---- | 6.3.3.1 Divides one polynomial by another mod p: let (q,r) = divPolyMod p a b; ((b * q) + r) `mod` p = a   -divPolyMod :: (Num a, Eq a, Integral a) => a -> Poly a -> Poly a -> (Poly a, Poly a)-divPolyMod p a b = -  let n = polyDegree b in -  let u = inverseMod (polyCoef b n) p in -  divLoop p b n u zero a-  where -    divLoop p b n u q r =-      let d = polyDegree r in -      if d < n then (polyMod p q, polyMod p r)-      else-        let v = scalePoly (u * polyCoef r d) (xPow (d - n)) in -        let r' = polyMod p $ r - (v * b) in -        let q' = polyMod p $ q + v in -      divLoop p b n u q' r'---- | 6.3.3.2 Finds the extended GCD mod p: let (d,u) = extendedEuclidean p a b; if d == 1, then (u * a) `mod` p = 1 -extendedEuclidean :: (Num a, Eq a, Integral a) => a -> Poly a -> Poly a -> (Poly a, Poly a)-extendedEuclidean p a b = extendedEuclideanLoop p one a zero b-  where -    extendedEuclideanLoop p u d v1 v3-      | polyIsZero v3 = (d,u)-      | otherwise = -        let (q,t3) = divPolyMod p d v3 in -        let t1 = polyMod p $ u - q * v1 in -        extendedEuclideanLoop p v1 v3 t1 t3 ---- | Generates Polynomials and Attempts to Find Inverses Until Success: let (a,u) = findInversable params; (a * u) `mod` 2 = 1  -findInversable :: (Num a, Eq a, Integral a) => [Int] -> IO (Poly a, Poly a)-findInversable params = do -    let n = getN params -    let df = getDf params -    a' <- genRandPoly n df df  -    let a = scalePoly (getP params) a' + one-    let b = xPow n - one-    let (d, u) = extendedEuclidean 2 a b -    if d == one then return (a, u) else findInversable params  ---- | 6.3.3.4 Raises Polynomial Inverse mod 2 to mod 2^11; let (a, u) = findInversable; (a * (inverseLift a b (degree a))) `mod` 2048 = 1 -inverseLift :: (Num a, Eq a, Integral a) => Poly a -> Poly a -> Int -> a -> Poly a-inverseLift a b deg = inverseLift' a b deg 2 11 where -  inverseLift' a b deg n e q -    | e == 0 = polyMod (2 ^ 11) b-    | otherwise = -        let b' = polyBigMod (2 ^ n) $ scalePoly 2 b - (reduceDegree deg $! a * (reduceDegree deg $! (b * b))) -        in inverseLift' a b' deg (2 * n) (e `div` 2) q ---- | 9.2.1 Generates a key pair. (publicKey, privateKey). The private key will be 1 + pF, per enhancement 2 at --- | https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf-generateKeyPair :: (Num a, Eq a, Integral a) => [Int] -> IO ([a], [a])-generateKeyPair params = do -  let n = getN params -      dg = getDg params-      q = getQ params  -  (f, u) <- findInversable params -  let fq = inverseLift f u n (fromIntegral q) -  g <- genRandPoly n dg (dg - 1) -  let pk = polyMod q $! reduceDegree n $! scalePoly (getP params) $! fq * g-  return (fromPoly pk, fromPoly f)---{- Blinding Polynomial Generation -}---- | Creates seed for bpgm -genSData :: (Num a, Eq a, Integral a) => [a] -> [a] -> [a] -> [Int] -> [a]-genSData h msg b params = -  let bh = concatMap bigIntToBits h in -  let pkLen = getPkLen params in -  let bhTrunc = take (pkLen - (pkLen `mod` 8)) bh in -  let hTrunc = map (fromIntegral . bitsToInt) (chunksOf 8 bhTrunc) in -  let sData = map fromIntegral (getOID params) ++ msg ++ b ++ hTrunc in -  sData---- | 8.3.2.2 Generates the blinding polynomial using the given seed-bpgm :: (Num a, Eq a, Integral a) => [a] -> [Int] -> [a]-bpgm seed params =-  let (i, s) = igf ([], [], 0) seed params in-  let r = Seq.update i 1 $ Seq.fromList $ replicate (getN params) 0 in-  let t = getDr params in-  let r' = rlooper s 1 r (t - 1) params in-  L.toList $ rlooper s (-1) r' t params---- | Creates the sequence with the proper -1's and 1's-rlooper :: (Num a, Eq a, Integral a) => ([a], [a], a) -> a -> Seq.Seq a -> Int -> [Int] -> Seq.Seq a-rlooper s val r 0 params = r-rlooper s val r t params =-  let (i, s') = igf s [] params in-  if Seq.index r i == 0-    then (let r' = Seq.update i val r in rlooper s' val r' (t-1) params)-    else rlooper s' val r t params---- | 8.4.2.1 Given a state or a seed, generates the next index to be used-igf :: (Num a, Eq a, Integral a) => ([a], [a], a) -> [a] -> [Int] -> (Int, ([a], [a], a))-igf state seed params =-  let (z, buf, counter) = extractVariables state seed params -      (i, buf', counter') = genIndex counter buf z params-      s = (z, buf', counter')-      n = getN params -  in (i `mod` n, s)---- | Either initializes the state, or uses the already created one -extractVariables :: (Num a, Eq a, Integral a) => ([a], [a], a) -> [a] -> [Int] -> ([a], [a], a) -extractVariables state [] _ = state-extractVariables _ seed params = igfinit seed params ---- | Initialization of state-igfinit :: (Num a, Eq a, Integral a) => [a] -> [Int] -> ([a], [a], a)-igfinit seed params = -  let minCallsR = getMinCallsR params  -      shaFn = getSHA params -      z = shaFn seed  -      buf = buildM 0 minCallsR z shaFn []-  in (z, buf, minCallsR)---- | Returns an index and pieces of the state-genIndex :: (Num a, Eq a, Integral a) => a -> [a] -> [a] -> [Int] -> (Int, [a], a)-genIndex counter buf z params =-  let remLen = length buf-      c = getC params -      n = getN params -      shaFn = getSHA params-      hLen = getHLen params  -      tmpLen = (c - remLen)-      cThreshold = counter + fromIntegral (ceiling (fromIntegral tmpLen / fromIntegral hLen))-      (m, counter') = if remLen >= c -                      then (buf, counter)-                      else (buildM counter cThreshold z shaFn buf, cThreshold)-      (b, buf') = splitAt c (buf ++ m)-      i = fromIntegral $ bitsToInt b -  in if i >= (2^c - (2^c `mod` n))-     then genIndex counter' buf' z params -     else (i, buf', counter')---- | Builds out the buffer -buildM :: (Num a, Eq a, Integral a) => a -> a -> [a] -> ([a]->[a]) -> [a] -> [a]-buildM count cThreshold z shaFn buf-  | count >= cThreshold = buf -  | otherwise = -    let c = i2osp count 3 -        h =  shaFn (z ++ c) -        m = buf ++ intsToBits h-    in buildM (count + 1) cThreshold z shaFn m ---- | Converts counter to 4 bytes... Not exactly the same as documentation but in practice counter does not exceed the bounds-i2osp :: (Num a, Eq a, Integral a) => a -> a -> [a]-i2osp i n -  | n == 0 = [i] -  | otherwise = 0:i2osp i (n-1)---{- SHA Functionality -}---- | Needed to pass sha() output to unpack()-bToStrict :: BL.ByteString -> B.ByteString-bToStrict = B.concat . BL.toChunks---- | sha1 output: 20 octets (1 octet = 8 bits)-sha1Octets :: (Num a, Eq a, Integral a) => [a] -> [a]-sha1Octets input = map fromIntegral $ B.unpack $ bToStrict $ bytestringDigest $ sha1 $ BL.pack $ map fromIntegral input---- | sha256 output: 32 octets-sha256Octets :: (Num a, Eq a, Integral a) => [a] -> [a]-sha256Octets input = map fromIntegral $ B.unpack $ bToStrict $ bytestringDigest $ sha256 $ BL.pack $ map fromIntegral input---{- Mask Generation -} -- Much of this code is similar to blinding polynomial generation, but we implemented separately ---- | 8.4.1.1 Generates the mask based on the given seed -mgf :: (Num a, Eq a, Integral a) => [a] -> [Int] -> [a]-mgf seed params =-  let n = getN params in-  let shaFn = getSHA params in -  let z = shaFn seed in -  let buf = buildBuffer 0 (getMinCallsR params) z shaFn [] in -  let i = formatI buf in-  take n $ finishI i n (getMinCallsR params) z shaFn---- | Builds out the buffer -buildBuffer :: (Num a, Eq a, Integral a) => a -> a -> [a] -> ([a]->[a]) -> [a] -> [a]-buildBuffer counter minCallsR z shaFn buffer-  | counter >= minCallsR = buffer-  | otherwise = let octet_c = i2osp counter 3 in  -                let h = shaFn (z ++ octet_c) in -                buildBuffer (counter + 1) minCallsR z shaFn (buffer ++ h)---- | Step I Converts octets to trits-toTrits :: (Num a, Eq a, Integral a) => a -> a -> [a]-toTrits n o-  | n == 0 = []-  | otherwise = (o `mod` 3):toTrits (n - 1) ((o - (o `mod` 3)) `div` 3)---- | Builds out buffer when needed-finishI :: (Num a, Eq a, Integral a) => [a] -> Int -> a -> [a] -> ([a] -> [a]) -> [a]-finishI i n counter z shaFn-  | fromIntegral (length i) >= n = i -  | otherwise = let buf = buildBuffer counter (counter + 1) z shaFn [] in -                let i' = formatI buf in -                finishI i' n (counter + 1) z shaFn ---- | Formats buffer-formatI :: (Num a, Eq a, Integral a) => [a] -> [a]-formatI buf = concatMap (toTrits 5) $ filter (< 243) buf--{- Encrypt -}---- | 9.2.2 Encrypts msg using the public key h and parameter set -encrypt :: (Num a, Eq a, Integral a) => [Int] -> [a] -> [a] -> IO [a]-encrypt params msg h =  -  let l = fromIntegral $ length msg-      maxLength = getMaxMsgLenBytes params in-  if l > maxLength then error "message too long"-  else do -    let bLen = getDb params `div` 8 -        dr = getDr params -        n = getN params-        q = getQ params-        p = getP params -    b <- randByteString bLen-    let p0 = replicate (fromIntegral $ maxLength - l) 0-        m = b ++ [fromIntegral l] ++ msg ++ p0 -        mBin = addPadding $ intsToBits m -        mTrin = concatMap binToTern $ chunksOf 3 mBin-        sData = genSData h msg b params-        r = bpgm sData params-        r' = polyMod q $ reduceDegree n $ toPoly r * toPoly h-        r4 = polyMod 4 r'-        or4 = toOctets $ fromPoly r4-        mask = mgf or4 params -        m' = polyModInterval p $ toPoly mask + toPoly mTrin-        e = polyMod q $ r' + m' -    return $ fromPoly e---{- Decrypt -}---- | 9.3.3 Decrypts e using the private key f and verifies it using the public key h. -decrypt :: (Num a, Eq a, Integral a) => [Int] -> [a] -> [a] -> [a] -> [a]-decrypt params f h e =-  let n = getN params-      p = getP params-      q = getQ params -      bLen = getDb params `div` 8-      ci = polyMod p $ polyModInterval q $ reduceDegree n $ toPoly f * toPoly e-      cR = polyMod q $ toPoly e - polyModInterval p ci-      cR4 = polyMod 4 cR-      coR4 = toOctets $ fromPoly cR4-      cMask = polyMod p $ toPoly $ mgf coR4 params-      cMTrin = polyModInterval p $ ci - cMask -      cMTrin' = improperPolynomial n $ fromPoly cMTrin-      cMBin = concatMap ternToBin $ chunksOf 2 $ take (length cMTrin' - (length cMTrin' `mod` 2)) cMTrin'-      cM = map bitsToInt $ chunksOf 8 $ take (length cMBin - (length cMBin `mod` 8)) cMBin-      (cb, rest) = splitAt bLen cM-      ([cl], rest') = splitAt (getLLen params) rest-      (cm, rest'') = splitAt (fromIntegral cl) rest'-      sData = genSData h cm cb params -      cr = bpgm sData params-      cR' = polyMod q $ reduceDegree n $ toPoly cr * toPoly h-      validR = cR' == cR-      validRemainder = all (==0) rest''-  in checkValid cm validR validRemainder ---- | Checks results of verification steps-checkValid :: (Num a, Eq a, Integral a) => [a] -> Bool -> Bool -> [a]-checkValid _ _ False = error "Failure Checking Remainder of Message"-checkValid _ False _ = error "Failure Verifying Blinding Polynomial"-checkValid m _ _ = m ---{- Other Operations -}---- | Calculate the modular inverse of x and y: ((inverseMod x y) * x) `mod` y = 1 -inverseMod :: (Num a, Eq a, Integral a) => a -> a -> a-inverseMod x y = case invertMod (fromIntegral x) (fromIntegral y) of-  Just n -> fromIntegral n -  _ -> error "Coukd not calculate inverseMod"---- | Generate a random ByteString-randByteString :: (Num a, Eq a, Integral a) => Int -> IO [a]-randByteString size = do-  g <- newGenIO :: IO SystemRandom-  case genBytes size g of -    Left err -> error $ show err-    Right (result, g2) -> return (unpackByteString result)---- | Converts a bytestring to a list of ascii values -unpackByteString :: (Num a, Eq a, Integral a) => BC.ByteString -> [a]-unpackByteString str = map fromIntegral (B.unpack str) ---- | Used to encode bits of a message from binary to trinary representation -binToTern :: (Num a, Eq a, Integral a) => [a] -> [a]-binToTern [0,0,0] = [0,0]-binToTern [0,0,1] = [0,1]-binToTern [0,1,0] = [0,-1]-binToTern [0,1,1] = [1,0]-binToTern [1,0,0] = [1,1]-binToTern [1,0,1] = [1,-1]-binToTern [1,1,0] = [-1,0]-binToTern [1,1,1] = [-1,1]-binToTern _ = error "Problem converting binary to trinary"---- | Inverse of binToTern-ternToBin :: (Num a, Eq a, Integral a) => [a] -> [a]-ternToBin [0,0] = [0,0,0]-ternToBin [0,1] = [0,0,1]-ternToBin [0,-1] = [0,1,0]-ternToBin [1,0] = [0,1,1]-ternToBin [1,1] = [1,0,0]-ternToBin [1,-1] = [1,0,1]-ternToBin [-1,0] = [1,1,0]-ternToBin [-1,1] = [1,1,1]-ternToBin _ = error " Problem converting trinary to binary"----- | Makes message length a multiple of 3 by padding with 0s-addPadding :: (Num a, Eq a, Integral a) => [a] -> [a]-addPadding m = case length m `mod` 3 of-  0 -> m-  1 -> m ++ [0,0]-  2 -> m ++ [0]----- | Converts a single byte to a list of (n+1) bits: unpackByte 7 3 = [0,0,0,0,0,0,1,1]-unpackByte :: (Num a, Eq a, Integral a) => a -> a -> [a]-unpackByte n b -  | n < 0 = []-  | otherwise = (b `div` (2 ^ n)):unpackByte (n-1) (b `mod` 2 ^ n)---- | Converts a byte to a list of 8 bits-intToBits :: (Num a, Eq a, Integral a) => a -> [a]-intToBits = unpackByte 7---- | Converts a byte to a list of 11 bits. Needed for blinding polynomial seed -bigIntToBits :: (Num a, Eq a, Integral a) => a -> [a]-bigIntToBits = unpackByte 10---- | Turns a list of integers into bits -intsToBits :: (Num a, Eq a, Integral a) => [a] -> [a]-intsToBits = concatMap intToBits---- | Converts a list of bits to a single byte: bitsToInt [0,0,0,0,0,0,1,1] = 3  -bitsToInt :: (Num a, Eq a, Integral a) => [a] -> a-bitsToInt b = packByte 1 (reverse b) -  where-    packByte n b-      | null b = 0-      | otherwise = n * head b + packByte (n * 2) (tail b)---- | Generates a random polynomial of degree n with pos 1's and neg -1's-genRandPoly :: (Num a, Eq a, Integral a) => Int -> Int -> Int -> IO (Poly a)-genRandPoly n pos neg = do -  poly <- setRandValues [] n pos neg-  return $ toPoly poly  -  where-    setRandValues lst n pos neg = -      if n == 0 then return lst -      else do-        randVal <- randomIO :: IO Int-        let randInRange = randVal `mod` n -        if randInRange <= pos then setRandValues ((-1):lst) (n - 1) (neg - 1) pos else if randInRange <= (pos + neg) then setRandValues (1:lst) (n - 1) neg (pos - 1) else setRandValues (0:lst) (n - 1) neg pos---- | Creates an improper polynomial of length n from poly-improperPolynomial :: (Num a, Eq a, Integral a) => Int -> [a] -> [a]-improperPolynomial n poly = poly ++ replicate (fromIntegral n - length poly) 0---- | Pads the given list with the requisite zeros to have a multiple of 8 length -padInt8 :: (Num a, Eq a, Integral a) => [a] -> [a]-padInt8 lst = lst ++ replicate ((8 - (length lst `mod` 8)) `mod` 8) 0 ---- | Converts to octets-toOctets :: (Num a, Eq a, Integral a) => [a] -> [a]-toOctets lst = -  let int2s = concatMap (reverse . take 2 . reverse . unpackByte 7) lst -  in map (bitsToInt . padInt8) $ chunksOf 8 int2s---{- Paramter Sets -}---- | Generates the proper parameter set based on the given bit level-genParams :: (Num a, Eq a, Integral a) => a -> [Int]-genParams bit_level -  | bit_level == 112 = [401,3,2048,113,133,1,112,60,600,400,113,1,113,11,32,0,0,2,4,114,112] -  | bit_level == 128 = [449,3,2048,134,149,1,128,67,672,448,134,1,134,9,31,9,0,3,3,128,128]-  | bit_level == 192 = [677,3,2048,157,225,1,192,101,1008,676,157,256,157,11,27,9,0,5,3,192,192]-  | bit_level == 256 = [1087,3,2048,120,362,1,256,170,1624,1086,120,256,120,13,25,14,0,6,3,256,256]-  | otherwise = error "BitLevel must be 112, 128, 192, 256"---- | Parsing functions for paramter set   -getN = head-getP lst = fromIntegral $ lst!!1-getQ lst = fromIntegral $ lst!!2-getDf lst = lst!!3-getDg lst = lst!!4-getLLen lst = lst!!5-getDb lst = lst!!6-getMaxMsgLenBytes lst = lst!!7-getBufferLenBits lst = lst!!8-getBufferLenTrits lst = lst!!9-getDm0 lst = lst!!10-getSHA lst -  | lst!!11 == 1 = sha1Octets-  | otherwise = sha256Octets -getHLen lst -  | lst!!11 == 1 = 20 -  | otherwise = 32 -getDr lst = lst!!12-getC lst = lst!!13-getMinCallsR lst = fromIntegral $ lst!!14-getMinCallsMask lst = fromIntegral $ lst!!15-getOID lst = [lst!!16,lst!!17,lst!!18]-getPkLen lst = lst!!19-getLvl lst = lst!!20-  -{- External Functions -}---- | Generates a key-pair with the EES401EP1 Parameter Set-keyGen112 :: (Num a, Eq a, Integral a) => IO ([a], [a]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per Enhancement #2 at https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf-keyGen112 = generateKeyPair (genParams 112)---- | Generates a key-pair with the EES449EP1 Parameter Set-keyGen128 :: (Num a, Eq a, Integral a) => IO ([a], [a])-keyGen128 = generateKeyPair (genParams 128)---- | Generates a key-pair with the EES677EP1 Parameter Set-keyGen192 :: (Num a, Eq a, Integral a) => IO ([a], [a])-keyGen192 = generateKeyPair (genParams 192)---- | Generates a key-pair with the EES1087EP2 Parameter Set-keyGen256 :: (Num a, Eq a, Integral a) => IO ([a], [a])-keyGen256 = generateKeyPair (genParams 256)---- | Encrypts a message with the EES401EP1 Parameter Set -encrypt112 :: (Num a, Eq a, Integral a) => [a] -- ^ A list of ASCII values representing the message-                                        -> [a] -- ^ A list of numbers representing the public key-                                        -> IO [a] -- ^ A list of numbers representing the ciphertext-encrypt112 = encrypt (genParams 112)---- | Encrypts a message with the EES449EP1 Parameter Set -encrypt128 :: (Num a, Eq a, Integral a) => [a] -> [a] -> IO [a]-encrypt128 = encrypt (genParams 128)---- | Encrypts a message with the EES677EP1 Parameter Set -encrypt192 :: (Num a, Eq a, Integral a) => [a] -> [a] -> IO [a]-encrypt192 = encrypt (genParams 192)---- | Encrypts a message with the EES1087EP2 Parameter Set-encrypt256 :: (Num a, Eq a, Integral a) => [a] -> [a] -> IO [a]-encrypt256 = encrypt (genParams 256)---- | Decrypts and verifies a cyphertext with the EES401EP1 Parameter Set-decrypt112 :: (Num a, Eq a, Integral a) => [a] -- ^ A list of numbers representing the private key-                                        -> [a] -- ^ A list of numbers representing the public key-                                        -> [a] -- ^ A list of numbers representing the ciphertext-                                        -> [a] -- ^ A list of numbers representing the original message-decrypt112 = decrypt (genParams 112)---- | Decrypts and verifies a cyphertext with the EES449EP1 Parameter Set-decrypt128 :: (Num a, Eq a, Integral a) => [a] -> [a] -> [a] -> [a]-decrypt128 = decrypt (genParams 128)---- | Decrypts and verifies a cyphertext with the EES677EP1 Parameter Set-decrypt192 :: (Num a, Eq a, Integral a) => [a] -> [a] -> [a] -> [a]-decrypt192 = decrypt (genParams 192)---- | Decrypts and verifies a cyphertext with the EES1087EP2 Parameter Set-decrypt256 :: (Num a, Eq a, Integral a) => [a] -> [a] -> [a] -> [a]-decrypt256 = decrypt (genParams 256)
+ README.md view
@@ -0,0 +1,19 @@+# This is a Haskell Implementation of the NTRU Cryptographic library, following the IEEE Standard Specification (IEEE Std 1363.1-2008). ++### You can build it by running:+```+cabal install NTRU+```++### or by downloading it, and then running: +```+cabal configure+cabal build+cabal install +```++##### You can ignore the warnings from the build. ++##### You may need to install some dependencies, such as llvm. ++##Please contact julrich@cyberpointllc.com with any questions. 
+ examples/sampleGeneralNTRU.hs view
@@ -0,0 +1,26 @@+{-+To compile: ghc sampleGeneralNTRU.hs+To run: ./sampleGeneralNTRU+-}++import Math.NTRU+import Data.Char+import Data.Maybe++main = do +	+--  let params = genParams "EES401EP1" +	let params = ParamSet {getN =  401, getP = 3, getQ = 2048, getDf = 113, getDg = 133, getLLen = 1, getDb = 112, getMaxMsgLenBytes = 60, getBufferLenBits = 600, getBufferLenTrits = 400, getDm0 = 113, getShaLvl = 1, getDr = 113, getC = 11, getMinCallsR = 32, getMinCallsMask = 9, getOID = [0,2,4], getPkLen = 114, getBitLvl = 112}++	(publicKey, privateKey) <- keyGen params+	+	let msg = map (fromIntegral . ord) "Hello, World" :: [Integer]++	ct <- encrypt params msg publicKey++	let unencrypted = decrypt params privateKey publicKey ct ++	if (isNothing unencrypted)+	then print "Encryption Failed"+	else print $ map (chr . fromIntegral) (fromJust unencrypted)+
+ examples/sampleSpecificNTRU.hs view
@@ -0,0 +1,24 @@+{-+To compile: ghc sampleSpecificNTRU.hs+To run: ./sampleSpecificNTRU+-}++-- Paramter Set EES401EP1+import Math.NTRU.EES401EP1 +import Data.Char+import Data.Maybe++main = do +	+	(publicKey, privateKey) <- keyGen+	+	let msg = map (fromIntegral . ord) "Hello, World" :: [Integer]++	ct <- encrypt msg publicKey++	let unencrypted = decrypt privateKey publicKey ct ++	if (isNothing unencrypted)+	then print "Encryption Failed"+	else print $ map (chr . fromIntegral) (fromJust unencrypted)+
+ src/Math/NTRU.hs view
@@ -0,0 +1,517 @@+{- |  +Module      : NTRU+Description : NTRU cryptographic system implementation+Maintainer  : julrich@cyberpointllc.com+Stability   : Experimental+License     : New BSD++This is an implementation of the NTRU cryptographic system, following the standard set forth +by the IEEE in the document entitled IEEE Standard Specification for Public Key Cryptographic +Techniques Based on Hard Problems over Lattices (IEEE Std 1363.1-2008). It is designed to be compatible with the implementation+of SecurityInnovations, available <https://www.securityinnovation.com/products/encryption-libraries/ntru-crypto/ here>. +-}++++module Math.NTRU (keyGen, encrypt, decrypt, genParams, ParamSet(..)) where++import Data.Digest.Pure.SHA+import Data.List.Split+import Data.Sequence as Seq (index, update, fromList, Seq)+import Data.Foldable as L (toList)+import Crypto.Random+import System.Random+import Math.Polynomial+import Math.NumberTheory.Moduli +import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import qualified Data.ByteString.Lazy as BL+++{- Polynomial Operations -} ++-- | Poly to List+fromPoly :: Poly Integer -> [Integer]+fromPoly = polyCoeffs LE ++-- | List to Poly+toPoly :: [Integer] -> Poly Integer  +toPoly = poly LE ++-- | Retrive the coefficient of p corresponding to the (x^i) term +polyCoef :: Poly Integer -> Int -> Integer+polyCoef p i = fromPoly p !! i ++-- | Useful for syntax. Allows for poly + poly or poly * poly. +-- | Note that for ring multiplication, reduceDegree must be called+instance (Num a, Eq a) => Num (Poly a) where+  f + g = addPoly f g+  f * g = multPoly f g+  negate = negatePoly+  abs = undefined+  signum = undefined+  fromInteger = undefined++-- | Allows for polynomial multipliction in the ring of size n: reduceDegree n (a * b) = a * b in the ring. Assumes: (degree f) <= 2n+reduceDegree :: Int -> Poly Integer -> Poly Integer +reduceDegree n f =+  let (f1,f2) = splitAt n (fromPoly f) +  in toPoly f1 + toPoly f2 ++-- | Reduces all of the polynomial's coefficents mod q+polyMod :: Integer -> Poly Integer -> Poly Integer+polyMod q f = toPoly $ map (`mod` q) (fromPoly f)++-- | Same as polyMod, but chooses representative group values in Z/nZ to be in (-q/2, q/2] instead of [0,q-1]+polyModInterval :: Integer -> Poly Integer -> Poly Integer+polyModInterval q f = toPoly $ map (\x' -> intervalReduce $ x' `mod` q) (fromPoly f)  +  where intervalReduce x' = if x' <= (q `div` 2) then x' else x' - q++-- | PolyMod when q is big +polyBigMod :: Integer -> Poly Integer -> Poly Integer+polyBigMod q p = toPoly $ map fromIntegral $ fromPoly $ polyMod q $ toPoly $ map fromIntegral $ fromPoly p ++-- | Creates the polynomial x^n+xPow :: Int -> Poly Integer +xPow = powPoly x+++{- Key Generation -}++-- | 6.3.3.1 Divides one polynomial by another mod p: let (q,r) = divPolyMod p a b; ((b * q) + r) `mod` p = a; (degree r) < (degree b)+divPolyMod :: Integer -> Poly Integer -> Poly Integer -> (Poly Integer, Poly Integer)+divPolyMod p a b = +  let n = polyDegree b in +  let u = inverseMod (polyCoef b n) p in +  divLoop p b n u zero a+  where +    divLoop p' b' n' u' q r =+      let d = polyDegree r in +      if d < n' then (polyMod p' q, polyMod p r)+      else+        let v = scalePoly (u' * polyCoef r d) (xPow (d - n')) in +        let r' = polyMod p' $ r - (v * b') in +        let q' = polyMod p' $ q + v in +      divLoop p' b' n' u' q' r'++-- | 6.3.3.2 Finds the extended GCD mod p: let (d,u) = extendedEuclidean p a b; if d == 1, then (u * a) `mod` p = 1 +extendedEuclidean :: Integer -> Poly Integer -> Poly Integer -> (Poly Integer, Poly Integer)+extendedEuclidean p a b = extendedEuclideanLoop p one a zero b+  where +    extendedEuclideanLoop p' u d v1 v3+      | polyIsZero v3 = (d,u)+      | otherwise = +        let (q,t3) = divPolyMod p' d v3 in +        let t1 = polyMod p' $ u - q * v1 in +        extendedEuclideanLoop p' v1 v3 t1 t3 ++-- | Generates Polynomials and Attempts to Find Inverses Until Success: let (a,u) = findInvertible params; (a * u) `mod` 2 = 1  +findInvertible :: ParamSet -> IO (Poly Integer, Poly Integer)+findInvertible params = do +    let n =  getN params +    let df = getDf params +    a' <- genRandPoly n df df  +    let a = scalePoly (getP params) a' + one+    let b = xPow n - one+    let (d, u) = extendedEuclidean 2 a b +    if d == one then return (a, u) else findInvertible params  ++-- | 6.3.3.4 Raises Polynomial Inverse mod 2 to mod 2^11; let (a, b) = findInvertible; (a * (inverseLift a b (degree a))) `mod` 2048 = 1 +inverseLift :: Poly Integer -> Poly Integer -> Int -> Integer -> Poly Integer+inverseLift a b deg = inverseLift' a b deg (2 :: Integer) (11 :: Integer) where +  inverseLift' a b deg n e q +    | e == 0 = polyMod (2 ^ q) b+    | otherwise = +        let b' = polyBigMod (2 ^ n) $ scalePoly 2 b - (reduceDegree deg $! a * (reduceDegree deg $! (b * b))) +        in inverseLift' a b' deg (2 * n) (e `div` 2) q ++-- | Generates a random PublicKey-PrivateKey Pair +keyGen :: ParamSet -- ^ Parameter set, most likely the output of 'genParams'+          -> IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enhancement #2>.+keyGen params = do +  let n =  getN params +      dg = getDg params+      q = getQ params  +  (f, u) <- findInvertible params +  let fq = inverseLift f u n (fromIntegral q) +  g <- genRandPoly n dg (dg - 1) +  let pk = polyMod q $! reduceDegree n $! scalePoly (getP params) $! fq * g+  return (fromPoly pk, fromPoly f)+++{- Blinding Polynomial Generation -}++-- | Creates seed for bpgm. h is the public key, b is the random string of bits prefixed to the message+genSData :: [Integer] -> [Integer] -> [Integer] -> ParamSet -> [Integer]+genSData h msg b params = +  let bh = concatMap bigIntToBits h in +  let pkLen = getPkLen params in +  let bhTrunc = take (pkLen - (pkLen `mod` 8)) bh in +  let hTrunc = map (fromIntegral . bitsToInt) (chunksOf 8 bhTrunc) in +  let sData = map fromIntegral (getOID params) ++ msg ++ b ++ hTrunc in +  sData++-- | 8.3.2.2 Generates the blinding polynomial using the given seed+bpgm :: [Integer] -> ParamSet -> [Integer]+bpgm seed params =+  let (i, s) = igf ([], [], 0) seed params in+  let r = Seq.update i 1 $ Seq.fromList $ replicate (getN params) 0 in+  let t = getDr params in+  let r' = rlooper s 1 r (t - 1) params in+  L.toList $ rlooper s (-1) r' t params++-- | Creates the sequence with the proper -1's and 1's+rlooper :: ([Integer], [Integer], Integer) -> Integer -> Seq.Seq Integer -> Int -> ParamSet -> Seq.Seq Integer+rlooper s val r 0 params = r+rlooper s val r t params =+  let (i, s') = igf s [] params in+  if Seq.index r i == 0+    then (let r' = Seq.update i val r in rlooper s' val r' (t-1) params)+    else rlooper s' val r t params++-- | 8.4.2.1 Given a state or a seed, generates the next index to be used+igf :: ([Integer], [Integer], Integer) -> [Integer] -> ParamSet -> (Int, ([Integer], [Integer], Integer))+igf state seed params =+  let (z, buf, counter) = extractVariables state seed params +      (i, buf', counter') = genIndex counter buf z params+      s = (z, buf', counter')+      n =  getN params +  in (i `mod` n, s)++-- | Either initializes the state, or uses the already created one +extractVariables :: ([Integer], [Integer], Integer) -> [Integer] -> ParamSet -> ([Integer], [Integer], Integer) +extractVariables state [] _ = state+extractVariables _ seed params = igfinit seed params ++-- | Initialization of state+igfinit :: [Integer] -> ParamSet -> ([Integer], [Integer], Integer)+igfinit seed params = +  let minCallsR = getMinCallsR params  +      shaFn =  getSHA params +      z = shaFn seed  +      buf = buildM 0 minCallsR z shaFn []+  in (z, buf, minCallsR)++-- | Returns an index and pieces of the state+genIndex :: Integer -> [Integer] -> [Integer] -> ParamSet -> (Int, [Integer], Integer)+genIndex counter buf z params =+  let remLen =  length buf+      c = getC params +      n =  getN params +      shaFn =  getSHA params+      hLen =  getHLen params  +      tmpLen =  (c - remLen)+      cThreshold = counter + fromIntegral (ceiling (fromIntegral tmpLen / fromIntegral hLen))+      (m, counter') = if remLen >= c +                      then (buf, counter)+                      else (buildM counter cThreshold z shaFn buf, cThreshold)+      (b, buf') = splitAt c (buf ++ m)+      i = fromIntegral $ bitsToInt b +  in if i >= (2^c - (2^c `mod` n))+     then genIndex counter' buf' z params +     else (i, buf', counter')++-- | Builds out the buffer +buildM :: Integer -> Integer -> [Integer] -> ([Integer]->[Integer]) -> [Integer] -> [Integer]+buildM count cThreshold z shaFn buf+  | count >= cThreshold = buf +  | otherwise = +    let c = i2osp count 3 +        h =  shaFn (z ++ c) +        m = buf ++ intsToBits h+    in buildM (count + 1) cThreshold z shaFn m ++-- | Converts counter to 4 bytes... Not exactly the same as documentation but in practice counter does not exceed the bounds+i2osp :: Integer -> Integer -> [Integer]+i2osp i n +  | n == 0 = [i] +  | otherwise = 0:i2osp i (n-1)+++{- SHA Functionality -}++-- | Needed to pass sha() output to unpack()+bToStrict :: BL.ByteString -> B.ByteString+bToStrict = B.concat . BL.toChunks++-- | sha1 output: 20 octets (1 octet = 8 bits)+sha1Octets :: [Integer] -> [Integer]+sha1Octets input = map fromIntegral $ B.unpack $ bToStrict $ bytestringDigest $ sha1 $ BL.pack $ map fromIntegral input++-- | sha256 output: 32 octets+sha256Octets :: [Integer] -> [Integer]+sha256Octets input = map fromIntegral $ B.unpack $ bToStrict $ bytestringDigest $ sha256 $ BL.pack $ map fromIntegral input+++{- Mask Generation -} -- Much of this code is similar to blinding polynomial generation, but we implemented separately ++-- | 8.4.1.1 Generates the mask based on the given seed +mgf :: [Integer] -> ParamSet -> [Integer]+mgf seed params =+  let n =  getN params in+  let shaFn =  getSHA params in +  let z = shaFn seed in +  let buf = buildBuffer 0 (getMinCallsR params) z shaFn [] in +  let i = formatI buf in+  take n $ finishI i n (getMinCallsR params) z shaFn++-- | Builds out the buffer +buildBuffer :: Integer -> Integer -> [Integer] -> ([Integer]->[Integer]) -> [Integer] -> [Integer]+buildBuffer counter minCallsR z shaFn buffer+  | counter >= minCallsR = buffer+  | otherwise = let octet_c = i2osp counter 3 in  +                let h = shaFn (z ++ octet_c) in +                buildBuffer (counter + 1) minCallsR z shaFn (buffer ++ h)++-- | Step I Converts octets to trits+toTrits :: Integer -> Integer -> [Integer]+toTrits n o+  | n == 0 = []+  | otherwise = (o `mod` 3):toTrits (n - 1) ((o - (o `mod` 3)) `div` 3)++-- | Builds out buffer when needed+finishI :: [Integer] -> Int -> Integer -> [Integer] -> ([Integer] -> [Integer]) -> [Integer]+finishI i n counter z shaFn+  | fromIntegral (length i) >= n = i +  | otherwise = let buf = buildBuffer counter (counter + 1) z shaFn [] in +                let i' = formatI buf in +                finishI i' n (counter + 1) z shaFn ++-- | Formats buffer+formatI :: [Integer] -> [Integer]+formatI buf = concatMap (toTrits 5) $ filter (< 243) buf++{- Encrypt -}++-- | Encrypts a message using the given parameter set+encrypt :: ParamSet -- ^ Parameter set, most likely the output of 'genParams' +           -> [Integer] -- ^ A list of ASCII values representing the message+           -> [Integer] -- ^ A list of numbers representing the public key+           -> IO [Integer] -- ^ A list of numbers representing the ciphertext+encrypt params msg h =  +  let l = fromIntegral $ length msg+      maxLength = getMaxMsgLenBytes params in+  if l > maxLength then error "message too long"+  else do +    let bLen =  getDb params `div` 8 +        dr = getDr params +        n =  getN params+        q = getQ params+        p = getP params +    b <- randByteString bLen+    let p0 = replicate (fromIntegral $ maxLength - l) 0+        m = b ++ [fromIntegral l] ++ msg ++ p0 +        mBin =  addPadding $ intsToBits m +        mTrin =  concatMap binToTern $ chunksOf 3 mBin+        sData = genSData h msg b params+        r = bpgm sData params+        r' = polyMod q $ reduceDegree n $ toPoly r * toPoly h+        r4 = polyMod 4 r'+        or4 = toOctets $ fromPoly r4+        mask = mgf or4 params +        m' = polyModInterval p $ toPoly mask + toPoly mTrin+        e = polyMod q $ r' + m' +    return $ fromPoly e+++{- Decrypt -}++-- | 9.3.3 Decrypts e using the private key f and verifies it using the public key h. +decrypt :: ParamSet -- ^ Parameter set, most likely the output of 'genParams' +           -> [Integer] -- ^ A list of numbers representing the private key+           -> [Integer] -- ^ A list of numbers representing the public key+           -> [Integer] -- ^ A list of numbers representing the ciphertext+           -> Maybe [Integer] -- ^ A list of numbers representing the original message+decrypt params f h e =+  let n =  getN params+      p = getP params+      q = getQ params +      bLen =  getDb params `div` 8+      ci = polyMod p $ polyModInterval q $ reduceDegree n $ toPoly f * toPoly e+      cR = polyMod q $ toPoly e - polyModInterval p ci+      cR4 = polyMod 4 cR+      coR4 = toOctets $ fromPoly cR4+      cMask = polyMod p $ toPoly $ mgf coR4 params+      cMTrin =  polyModInterval p $ ci - cMask +      cMTrin' = improperPolynomial n $ fromPoly cMTrin+      cMBin =  concatMap ternToBin $ chunksOf 2 $ take (length cMTrin' - (length cMTrin' `mod` 2)) cMTrin'+      cM = map bitsToInt $ chunksOf 8 $ take (length cMBin - (length cMBin `mod` 8)) cMBin+      (cb, rest) = splitAt bLen cM+      ([cl], rest') = splitAt (getLLen params) rest+      (cm, rest'') = splitAt (fromIntegral cl) rest'+      sData = genSData h cm cb params +      cr = bpgm sData params+      cR' = polyMod q $ reduceDegree n $ toPoly cr * toPoly h+      validR = cR' == cR+      validRemainder = all (==0) rest''+  in checkValid cm validR validRemainder ++-- | Checks results of verification steps+checkValid :: [Integer] -> Bool -> Bool -> Maybe [Integer]+checkValid _ _ False = Nothing+checkValid _ False _ = Nothing+checkValid m _ _ = Just m +++{- Other Operations -}++-- | Calculate the modular inverse of x and y: ((inverseMod x y) * x) `mod` y = 1 +inverseMod :: Integer -> Integer -> Integer+inverseMod x y = case invertMod (fromIntegral x) (fromIntegral y) of+  Just n -> fromIntegral n +  _ -> error "Could not calculate inverseMod"++-- | Generate a random ByteString+randByteString :: Int -> IO [Integer]+randByteString size = do+  g <- newGenIO :: IO SystemRandom+  case genBytes size g of +    Left err -> error $ show err+    Right (result, g2) -> return (unpackByteString result)++-- | Converts a bytestring to a list of ascii values +unpackByteString :: BC.ByteString -> [Integer]+unpackByteString str = map fromIntegral (B.unpack str) ++-- | Used to encode bits of a message from binary to trinary representation +binToTern :: [Integer] -> [Integer]+binToTern [0,0,0] = [0,0]+binToTern [0,0,1] = [0,1]+binToTern [0,1,0] = [0,-1]+binToTern [0,1,1] = [1,0]+binToTern [1,0,0] = [1,1]+binToTern [1,0,1] = [1,-1]+binToTern [1,1,0] = [-1,0]+binToTern [1,1,1] = [-1,1]+binToTern _ = error "Problem converting binary to trinary"++-- | Inverse of binToTern+ternToBin :: [Integer] -> [Integer]+ternToBin [0,0] = [0,0,0]+ternToBin [0,1] = [0,0,1]+ternToBin [0,-1] = [0,1,0]+ternToBin [1,0] = [0,1,1]+ternToBin [1,1] = [1,0,0]+ternToBin [1,-1] = [1,0,1]+ternToBin [-1,0] = [1,1,0]+ternToBin [-1,1] = [1,1,1]+ternToBin _ = error " Problem converting trinary to binary"+++-- | Makes message length a multiple of 3 by padding with 0s+addPadding :: [Integer] -> [Integer]+addPadding m = case length m `mod` 3 of+  0 -> m+  1 -> m ++ [0,0]+  2 -> m ++ [0]+++-- | Converts a single byte to a list of (n+1) bits: unpackByte 7 3 = [0,0,0,0,0,0,1,1]+unpackByte :: Integer -> Integer -> [Integer]+unpackByte n b +  | n < 0 = []+  | otherwise = (b `div` (2 ^ n)):unpackByte (n-1) (b `mod` 2 ^ n)++-- | Converts a byte to a list of 8 bits+intToBits :: Integer -> [Integer]+intToBits = unpackByte 7++-- | Converts a byte to a list of 11 bits. Needed for blinding polynomial seed +bigIntToBits :: Integer -> [Integer]+bigIntToBits = unpackByte 10++-- | Turns a list of integers into bits +intsToBits :: [Integer] -> [Integer]+intsToBits = concatMap intToBits++-- | Converts a list of bits to a single byte: bitsToInt [0,0,0,0,0,0,1,1] = 3  +bitsToInt :: [Integer] -> Integer+bitsToInt b = packByte 1 (reverse b) +  where+    packByte n b+      | null b = 0+      | otherwise = n * head b + packByte (n * 2) (tail b)++-- | Generates a random polynomial of degree < n with pos 1's and neg -1's. Assumes pos + neg <= n+genRandPoly :: Int -> Int -> Int -> IO (Poly Integer)+genRandPoly n pos neg = do +  poly <- setRandValues [] n pos neg+  return $ toPoly poly  +  where+    setRandValues lst n pos neg = +      if n == 0 then return lst +      else do+        randVal <- randomIO :: IO Int+        let randInRange = randVal `mod` n +        if randInRange < pos +          then setRandValues ((1):lst) (n - 1) (pos - 1) neg else if randInRange < (pos + neg) then setRandValues ((-1):lst) (n - 1) pos (neg - 1) else setRandValues (0:lst) (n - 1) pos neg++-- | Creates an improper polynomial of length n from poly+improperPolynomial :: Int -> [Integer] -> [Integer]+improperPolynomial n poly = poly ++ replicate (fromIntegral n - length poly) 0++-- | Pads the given list with the requisite zeros to have a multiple of 8 length +padInt8 :: [Integer] -> [Integer]+padInt8 lst = lst ++ replicate ((8 - (length lst `mod` 8)) `mod` 8) 0 ++-- | Converts to octets+toOctets :: [Integer] -> [Integer]+toOctets lst = +  let int2s = concatMap (reverse . take 2 . reverse . unpackByte 7) lst +  in map (bitsToInt . padInt8) $ chunksOf 8 int2s+++{- Paramter Sets -}++-- | Generates the proper parameter set based on the given bit level+genParams :: String -- ^ Desired parameter set: This should be either one of the 12 listed in the IEEE Standard (1363.1-2008) Annex A+             -> ParamSet -- ^ Parameter set to be used by 'keyGen', 'encrypt', or 'decrypt'+genParams bit_level +  | bit_level == "EES401EP1" = ParamSet {getN =  401, getP = 3, getQ = 2048, getDf = 113, getDg = 133, getLLen = 1, getDb = 112, getMaxMsgLenBytes = 60, getBufferLenBits = 600, getBufferLenTrits = 400, getDm0 = 113, getShaLvl = 1, getDr = 113, getC = 11, getMinCallsR = 32, getMinCallsMask = 9, getOID = [0,2,4], getPkLen = 114, getBitLvl = 112} +  | bit_level == "EES449EP1" = ParamSet {getN =  449, getP = 3, getQ = 2048, getDf = 134, getDg = 149, getLLen = 1, getDb = 128, getMaxMsgLenBytes = 67, getBufferLenBits = 672, getBufferLenTrits = 448, getDm0 = 134, getShaLvl = 1, getDr = 134, getC = 9, getMinCallsR = 31, getMinCallsMask = 9, getOID = [0,3,3], getPkLen = 128, getBitLvl = 128} +  | bit_level == "EES677EP1" = ParamSet {getN =  677, getP = 3, getQ = 2048, getDf = 157, getDg = 225, getLLen = 1, getDb = 192, getMaxMsgLenBytes = 101, getBufferLenBits = 1008, getBufferLenTrits = 676, getDm0 = 157, getShaLvl = 256, getDr = 157, getC = 11, getMinCallsR = 27, getMinCallsMask = 9, getOID = [0,5,3], getPkLen = 192, getBitLvl = 192} +  | bit_level == "EES1087EP2" = ParamSet {getN =  1087, getP = 3, getQ = 2048, getDf = 120, getDg = 362, getLLen = 1, getDb = 256, getMaxMsgLenBytes = 170, getBufferLenBits = 1624, getBufferLenTrits = 1086, getDm0 = 120, getShaLvl = 256, getDr = 120, getC = 13, getMinCallsR = 25, getMinCallsMask = 14, getOID = [0,6,3], getPkLen = 256, getBitLvl = 256} +  | bit_level == "EES541EP1" = ParamSet {getN =  541, getP = 3, getQ = 2048, getDf = 49, getDg = 180, getLLen = 1, getDb = 112, getMaxMsgLenBytes = 86, getBufferLenBits = 808, getBufferLenTrits = 540, getDm0 = 49, getShaLvl = 1, getDr = 49, getC = 12, getMinCallsR = 15, getMinCallsMask = 11, getOID = [0,2,5], getPkLen = 112, getBitLvl = 112} +  | bit_level == "EES613EP1" = ParamSet {getN =  613, getP = 3, getQ = 2048, getDf = 55, getDg = 204, getLLen = 1, getDb = 128, getMaxMsgLenBytes = 97, getBufferLenBits = 912, getBufferLenTrits = 612, getDm0 = 55, getShaLvl = 1, getDr = 55, getC = 11, getMinCallsR = 16, getMinCallsMask = 13, getOID = [0,3,4], getPkLen = 128, getBitLvl = 128} +  | bit_level == "EES887EP1" = ParamSet {getN =  887, getP = 3, getQ = 2048, getDf = 81, getDg = 295, getLLen = 1, getDb = 192, getMaxMsgLenBytes = 141, getBufferLenBits = 1328, getBufferLenTrits = 886, getDm0 = 81, getShaLvl = 256, getDr = 81, getC = 10, getMinCallsR = 13, getMinCallsMask = 12, getOID = [0,5,4], getPkLen = 192, getBitLvl = 192} +  | bit_level == "EES1171EP1" = ParamSet {getN =  1171, getP = 3, getQ = 2048, getDf = 106, getDg = 390, getLLen = 1, getDb = 256, getMaxMsgLenBytes = 186, getBufferLenBits = 1752, getBufferLenTrits = 1170, getDm0 = 106, getShaLvl = 256, getDr = 106, getC = 10, getMinCallsR = 20, getMinCallsMask = 15, getOID = [0,6,4], getPkLen = 256, getBitLvl = 256} +  | bit_level == "EES659EP1" = ParamSet {getN =  659, getP = 3, getQ = 2048, getDf = 38, getDg = 219, getLLen = 1, getDb = 112, getMaxMsgLenBytes = 108, getBufferLenBits = 984, getBufferLenTrits = 658, getDm0 = 38, getShaLvl = 1, getDr = 38, getC = 11, getMinCallsR = 11, getMinCallsMask = 14, getOID = [0,2,6], getPkLen = 112, getBitLvl = 112} +  | bit_level == "EES761EP2" = ParamSet {getN =  761, getP = 3, getQ = 2048, getDf = 42, getDg = 253, getLLen = 1, getDb = 128, getMaxMsgLenBytes = 125, getBufferLenBits = 1136, getBufferLenTrits = 760, getDm0 = 42, getShaLvl = 1, getDr = 42, getC = 12, getMinCallsR = 13, getMinCallsMask = 16, getOID = [0,3,5], getPkLen = 128, getBitLvl = 128} +  | bit_level == "EES1087EP1" = ParamSet {getN =  1087, getP = 3, getQ = 2048, getDf = 63, getDg = 362, getLLen = 1, getDb = 192, getMaxMsgLenBytes = 178, getBufferLenBits = 1624, getBufferLenTrits = 1086, getDm0 = 63, getShaLvl = 256, getDr = 63, getC = 13, getMinCallsR = 13, getMinCallsMask = 14, getOID = [0,5,5], getPkLen = 192, getBitLvl = 192} +  | bit_level == "EES1499EP1" = ParamSet {getN =  1499, getP = 3, getQ = 2048, getDf = 79, getDg = 499, getLLen = 1, getDb = 256, getMaxMsgLenBytes = 247, getBufferLenBits = 2240, getBufferLenTrits = 1498, getDm0 = 79, getShaLvl = 256, getDr = 79, getC = 13, getMinCallsR = 17, getMinCallsMask = 19, getOID = [0,6,5], getPkLen = 256, getBitLvl = 256} +  | otherwise = error "Unsupported Parameter Set"++-- | The Parameter Set Record+data ParamSet = ParamSet {+  getN :: Int, -- ^ The size of the polynomials+  getP  :: Integer, -- ^ The small modulus p +  getQ :: Integer, -- ^ The large modulus q+  getDf :: Int, -- ^ The number of 1's in f+  getDg :: Int, -- ^ The number of 1's in g+  getLLen :: Int, -- ^ The length of the encoded message length (should probably be 1)+  getDb :: Int, -- ^ The number of random bits prefixed to the message+  getMaxMsgLenBytes :: Int, -- ^ The max number of bytes in the message+  getBufferLenBits :: Int, -- ^ The size of the resulting message before conversion to trits+  getBufferLenTrits :: Int, -- ^ The size of the resulting message after conversion to trits+  getDm0 :: Int, -- ^ Minimum number of 1's, -1's and 0's in the message for decryption to succeed +  getShaLvl :: Int, -- ^ SHA algorithm to use. Should be either 1 or 256+  getDr :: Int, -- ^ The number of 1's in the blinding polynomial+  getC :: Int, -- ^ Used by index generator function+  getMinCallsR :: Integer, -- ^ Used by mask generator+  getMinCallsMask :: Int, -- ^ Used by mask generator+  getOID :: [Int], -- ^ Parameter set ID+  getPkLen :: Int, -- ^ Used to create SData+  getBitLvl :: Int -- ^ Bit level security+} deriving (Show)++getSHA :: ParamSet -> ([Integer] -> [Integer])+getSHA params = case (getShaLvl params) of +  256 -> sha256Octets+  1 -> sha1Octets+  _ -> error "Unsupported SHA function"++getHLen :: ParamSet -> Int+getHLen params = case (getShaLvl params) of+  256 -> 32+  1 -> 20+  _ -> error "Unsupported SHA function"
+ src/Math/NTRU/EES1087EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES1087EP1 parameter set, for use at the 192-bit security level. +-}++module Math.NTRU.EES1087EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES1087EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES1087EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES1087EP1")
+ src/Math/NTRU/EES1087EP2.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES1087EP2 parameter set, for use at the 256-bit security level. +-}++module Math.NTRU.EES1087EP2 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES1087EP2") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES1087EP2")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES1087EP2")
+ src/Math/NTRU/EES1171EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES1171EP1 parameter set, for use at the 256-bit security level. +-}++module Math.NTRU.EES1171EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES1171EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES1171EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES1171EP1")
+ src/Math/NTRU/EES1499EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES1499EP1 parameter set, for use at the 256-bit security level. +-}++module Math.NTRU.EES1499EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES1499EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES1499EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES1499EP1")
+ src/Math/NTRU/EES401EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES401EP1 parameter set, for use at the 112-bit security level. +-}++module Math.NTRU.EES401EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES401EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES401EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES401EP1")
+ src/Math/NTRU/EES449EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES449EP1 parameter set, for use at the 128-bit security level. +-}++module Math.NTRU.EES449EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES449EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES449EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES449EP1")
+ src/Math/NTRU/EES541EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES541EP1 parameter set, for use at the 112-bit security level. +-}++module Math.NTRU.EES541EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES541EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES541EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES541EP1")
+ src/Math/NTRU/EES613EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES613EP1 parameter set, for use at the 128-bit security level. +-}++module Math.NTRU.EES613EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES613EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES613EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES613EP1")
+ src/Math/NTRU/EES659EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES659EP1 parameter set, for use at the 112-bit security level. +-}++module Math.NTRU.EES659EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES659EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES659EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES659EP1")
+ src/Math/NTRU/EES677EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES677EP1 parameter set, for use at the 192-bit security level. +-}++module Math.NTRU.EES677EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES677EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES677EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES677EP1")
+ src/Math/NTRU/EES761EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES761EP1 parameter set, for use at the 128-bit security level. +-}++module Math.NTRU.EES761EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES761EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES761EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES761EP1")
+ src/Math/NTRU/EES887EP1.hs view
@@ -0,0 +1,25 @@+{- |+	NTRU cryptographic system using the EES887EP1 parameter set, for use at the 192-bit security level. +-}++module Math.NTRU.EES887EP1 (keyGen, encrypt, decrypt) where ++	import qualified Math.NTRU as NTRU ++	-- | Generates a random PublicKey-PrivateKey pair +	keyGen :: IO ([Integer], [Integer]) -- ^ A tuple representing (PublicKey, PrivateKey) where PrivateKey = 1 + pf, per <https://www.securityinnovation.com/uploads/Crypto/NTRU%20Enhancements%201.pdf enahncement#2>.+	keyGen = NTRU.keyGen (NTRU.genParams "EES887EP1") +++	-- | Encrypts a message with the given public key+	encrypt :: [Integer] -- ^ A list of ASCII values representing the message+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> IO [Integer] -- ^ A list of numbers representing the ciphertext+	encrypt = NTRU.encrypt (NTRU.genParams "EES887EP1")++	-- | Decrypts and verifies a cyphertext with the given keys+	decrypt :: [Integer] -- ^ A list of numbers representing the private key+	              -> [Integer] -- ^ A list of numbers representing the public key+	              -> [Integer] -- ^ A list of numbers representing the ciphertext+	              -> Maybe [Integer] -- ^ A list of numbers representing the original message, or nothing on failure+	decrypt = NTRU.decrypt (NTRU.genParams "EES887EP1")