packages feed

crypto-numbers 0.2.2 → 0.2.3

raw patch · 8 files changed

+117/−15 lines, 8 filesdep ~base

Dependency ranges changed: base

Files

Crypto/Number/Basic.hs view
@@ -1,5 +1,8 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}+#ifndef MIN_VERSION_integer_gmp+#define MIN_VERSION_integer_gmp(a,b,c) 0+#endif #if MIN_VERSION_integer_gmp(0,5,1) {-# LANGUAGE UnboxedTuples #-} #endif
Crypto/Number/F2m.hs view
@@ -1,4 +1,7 @@ {-# LANGUAGE CPP #-}+#ifndef MIN_VERSION_integer_gmp+#define MIN_VERSION_integer_gmp(a,b,c) 0+#endif #ifdef VERSION_integer_gmp {-# LANGUAGE MagicHash #-} #endif
Crypto/Number/ModArithmetic.hs view
@@ -1,6 +1,9 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE CPP #-}+#ifndef MIN_VERSION_integer_gmp+#define MIN_VERSION_integer_gmp(a,b,c) 0+#endif -- | -- Module      : Crypto.Number.ModArithmetic -- License     : BSD-style
Crypto/Number/Prime.hs view
@@ -1,5 +1,8 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-}+#ifndef MIN_VERSION_integer_gmp+#define MIN_VERSION_integer_gmp(a,b,c) 0+#endif #if MIN_VERSION_integer_gmp(0,5,1) {-# LANGUAGE MagicHash #-} #endif
Crypto/Number/Serialize.hs view
@@ -1,3 +1,18 @@+{-# LANGUAGE CPP #-}+#ifndef MIN_VERSION_integer_gmp+#define MIN_VERSION_integer_gmp(a,b,c) 0+#endif+#if MIN_VERSION_integer_gmp(0,5,1)+{-# LANGUAGE MagicHash, UnboxedTuples, BangPatterns #-}+#endif+-- |+-- Module      : Crypto.Number.Serialize+-- License     : BSD-style+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>+-- Stability   : experimental+-- Portability : Good+--+-- fast serialization primitives for integer module Crypto.Number.Serialize     ( i2osp     , os2ip@@ -7,28 +22,55 @@     ) where  import Data.ByteString (ByteString)-import qualified Data.ByteString as B import qualified Data.ByteString.Internal as B-import Data.Bits-import Foreign.Storable import Foreign.Ptr +#if MIN_VERSION_integer_gmp(0,5,1)+import GHC.Integer.GMP.Internals+import GHC.Base+import GHC.Ptr+import System.IO.Unsafe+import Foreign.ForeignPtr+#else+import qualified Data.ByteString as B+import Foreign.Storable+import Data.Bits+#endif++#if !MIN_VERSION_integer_gmp(0,5,1) {-# INLINE divMod256 #-} divMod256 :: Integer -> (Integer, Integer) divMod256 n = (n `shiftR` 8, n .&. 0xff)+#endif  -- | os2ip converts a byte string into a positive integer-{-# INLINE os2ip #-} os2ip :: ByteString -> Integer+#if MIN_VERSION_integer_gmp(0,5,1)+os2ip bs = unsafePerformIO $ withForeignPtr fptr $ \ptr ->+    let !(Ptr ad) = (ptr `plusPtr` ofs)+     in IO $ \s -> importIntegerFromAddr ad (int2Word# n) 1# s+  where !(fptr, ofs, !(I# n)) = B.toForeignPtr bs+{-# NOINLINE os2ip #-}+#else os2ip = B.foldl' (\a b -> (256 * a) .|. (fromIntegral b)) 0+{-# INLINE os2ip #-}+#endif  -- | i2osp converts a positive integer into a byte string i2osp :: Integer -> ByteString+#if MIN_VERSION_integer_gmp(0,5,1)+i2osp m = B.unsafeCreate (I# (word2Int# sz)) fillPtr+  where !sz = sizeInBaseInteger m 256#+        fillPtr (Ptr srcAddr) = IO $ \s -> case exportIntegerToAddr m srcAddr 1# s of+                                                (# s2, _ #) -> (# s2, () #)+{-# NOINLINE i2osp #-}+#else i2osp m     | m < 0     = error "i2osp: cannot convert a negative integer to a bytestring"     | otherwise = B.reverse $ B.unfoldr fdivMod256 m     where fdivMod256 0 = Nothing           fdivMod256 n = Just (fromIntegral a,b) where (b,a) = divMod256 n+#endif   -- | just like i2osp, but take an extra parameter for size.@@ -37,19 +79,44 @@ -- -- FIXME: use unsafeCreate to fill the bytestring i2ospOf :: Int -> Integer -> Maybe ByteString+#if MIN_VERSION_integer_gmp(0,5,1) i2ospOf len m+    | sz <= len = Just $ i2ospOf_ len m+    | otherwise = Nothing+  where !sz = I# (word2Int# (sizeInBaseInteger m 256#))+#else+i2ospOf len m     | lenbytes < len  = Just $ B.replicate (len - lenbytes) 0 `B.append` bytes     | lenbytes == len = Just bytes     | otherwise       = Nothing-    where-        lenbytes = B.length bytes+  where lenbytes = B.length bytes         bytes    = i2osp m+#endif --- | just like i2ospOf except that it doesn't expect a failure.+-- | just like i2ospOf except that it doesn't expect a failure: i.e.+-- an integer larger than the number of output bytes requested+-- -- for example if you just took a modulo of the number that represent -- the size (example the RSA modulo n).-{-# INLINE i2ospOf_ #-} i2ospOf_ :: Int -> Integer -> ByteString+#if MIN_VERSION_integer_gmp(0,5,1)+i2ospOf_ len m = unsafePerformIO $ B.create len fillPtr+  where !sz = (sizeInBaseInteger m 256#)+        isz = I# (word2Int# sz)+        fillPtr ptr+            | len < isz  = error "cannot compute i2ospOf_ with integer larger than output bytes"+            | len == isz =+                let !(Ptr srcAddr) = ptr in+                IO $ \s -> case exportIntegerToAddr m srcAddr 1# s of+                                (# s2, _ #) -> (# s2, () #)+            | otherwise = do+                let z = len-isz+                _ <- B.memset ptr 0 (fromIntegral len)+                let !(Ptr addr) = ptr `plusPtr` z+                IO $ \s -> case exportIntegerToAddr m addr 1# s of+                                (# s2, _ #) -> (# s2, () #)+{-# NOINLINE i2ospOf_ #-}+#else i2ospOf_ len m = B.unsafeCreate len fillPtr     where fillPtr srcPtr = loop m (srcPtr `plusPtr` (len-1))             where loop n ptr = do@@ -63,11 +130,17 @@                       if ptr == srcPtr                           then return ()                           else fillerLoop (ptr `plusPtr` (-1))+{-# INLINE i2ospOf_ #-}+#endif  -- | returns the number of bytes to store an integer with i2osp ----- FIXME: really slow implementation. use log or bigger shifts.+-- with integer-simple, this function is really slow. lengthBytes :: Integer -> Int+#if MIN_VERSION_integer_gmp(0,5,1)+lengthBytes n = I# (word2Int# (sizeInBaseInteger n 256#))+#else lengthBytes n     | n < 256   = 1     | otherwise = 1 + lengthBytes (n `shiftR` 8)+#endif
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2010-2012 Vincent Hanquez <vincent@snarc.org>+Copyright (c) 2010-2013 Vincent Hanquez <vincent@snarc.org>  All rights reserved. 
Tests/Tests.hs view
@@ -1,11 +1,11 @@ {-# LANGUAGE OverloadedStrings #-} -import Test.Framework (defaultMain, testGroup)+import Test.Framework (defaultMain, testGroup, Test) import Test.Framework.Providers.QuickCheck2 (testProperty) import Test.Framework.Providers.HUnit (testCase)  import Test.QuickCheck-import Test.HUnit+import Test.HUnit ((@?=)) --import Test.QuickCheck.Test  import Control.Applicative ((<$>))@@ -45,12 +45,14 @@ prop_sqrti_valid :: Positive Integer -> Bool prop_sqrti_valid (Positive i) = l*l <= i && i <= u*u where (l, u) = sqrti i +{- prop_generate_prime_valid :: Seed -> Bool prop_generate_prime_valid i =     -- because of the next naive test, we can't generate easily number above 32 bits     -- otherwise it slows down the tests to uselessness. when AKS or ECPP is implemented     -- we can revisit the number here     primalityTestNaive $ withRNG i (\g -> generatePrime g 32)+-}  prop_miller_rabin_valid :: (Seed, PositiveSmall) -> Bool prop_miller_rabin_valid (seed, PositiveSmall i)@@ -121,9 +123,10 @@ instance Arbitrary Seed where     arbitrary = arbitrary >>= \(Positive i) -> return (Seed i) +serializationKATTests :: [Test] serializationKATTests = concatMap f vectors-    where f (v, bs) = [ testCase ("i2osp " ++ show v) (i2osp v  @=? bs)-                      , testCase ("os2ip " ++ show v) (os2ip bs @=? v)+    where f (v, bs) = [ testCase ("i2osp " ++ show v) (i2osp v  @?= bs)+                      , testCase ("os2ip " ++ show v) (os2ip bs @?= v)                       ]           vectors =             [ (0x10000, "\SOH\NUL\NUL")@@ -133,12 +136,26 @@             , (0x7521908421feabd21490, "u!\144\132!\254\171\210\DC4\144")             ] +serializationOfKATTests :: [Test]+serializationOfKATTests = concatMap f vectors+    where f (elen, v, bs) = [ testCase ("i2osp " ++ show v) (i2ospOf elen v @?= Just bs)+                            , testCase ("os2ip " ++ show v) (os2ip bs @?= v)+                            ]+          vectors =+            [ (5, 0x10000, "\NUL\NUL\SOH\NUL\NUL")+            , (3, 0x1234, "\NUL\DC24")+            , (8, 0xf123456, "\NUL\NUL\NUL\NUL\SI\DC24V")+            , (10, 0xf21908421feabd21490, "\SI!\144\132!\254\171\210\DC4\144")+            , (12, 0x7521908421feabd21490, "\NUL\NULu!\144\132!\254\171\210\DC4\144")+            ]+ main :: IO () main = defaultMain     [ testGroup "serialization"         [ testProperty "unbinary.binary==id" (\(Positive i) -> os2ip (i2osp i) == i)         , testProperty "length integer" (\(Positive i) -> B.length (i2osp i) == lengthBytes i)         , testGroup "KAT" serializationKATTests+        , testGroup "KAT2" serializationOfKATTests         ]     , testGroup "gcde binary"         [ testProperty "gcde" prop_gcde_binary_valid
crypto-numbers.cabal view
@@ -1,5 +1,5 @@ Name:                crypto-numbers-Version:             0.2.2+Version:             0.2.3 Description:         Cryptographic numbers: functions and algorithms License:             BSD3 License-file:        LICENSE