Merge pull request #257 from ocheron/hash-shake-truncate
SHAKE with output length not divisible by 8
This commit is contained in:
commit
0f43451b4f
12
.haskell-ci
12
.haskell-ci
@ -1,20 +1,20 @@
|
|||||||
# compiler supported and their equivalent LTS
|
# compiler supported and their equivalent LTS
|
||||||
compiler: ghc-8.0 lts-9.21
|
compiler: ghc-8.0 lts-9.21
|
||||||
compiler: ghc-8.2 lts-11.6
|
compiler: ghc-8.2 lts-11.22
|
||||||
compiler: ghc-8.4 ghc-8.4.2
|
compiler: ghc-8.4 lts-12.15
|
||||||
|
compiler: ghc-8.6 nightly-2018-10-21
|
||||||
|
|
||||||
# options
|
# options
|
||||||
# option: alias x=y z=v
|
# option: alias x=y z=v
|
||||||
option: testdeps extradep=QuickCheck-2.11.3 extradep=ansi-terminal-0.8.0.1 extradep=async-2.1.1.1 extradep=call-stack-0.1.0 extradep=clock-0.7.2 extradep=optparse-applicative-0.14.0.0 extradep=random-1.1 extradep=tagged-0.8.5 extradep=unbounded-delays-0.1.1.0 extradep=tasty-1.0.0.1 extradep=tasty-hunit-0.10.0.1 extradep=tasty-kat-0.0.3 extradep=tasty-quickcheck-0.9.2 extradep=ansi-wl-pprint-0.6.8.2 extradep=colour-2.3.4 extradep=tf-random-0.5 extradep=transformers-compat-0.5.1.4 extradep=primitive-0.6.3.0 allow-newer
|
|
||||||
option: gaugedeps extradep=gauge-0.2.1
|
option: gaugedeps extradep=gauge-0.2.1
|
||||||
|
|
||||||
option: basementmin extradep=basement-0.0.6 extradep=foundation-0.0.19 extradep=memory-0.14.14
|
option: basementmin extradep=basement-0.0.6 extradep=foundation-0.0.19 extradep=memory-0.14.14
|
||||||
|
|
||||||
# builds
|
# builds
|
||||||
build: ghc-8.2 basementmin gaugedeps
|
build: ghc-8.2
|
||||||
build: ghc-8.0 basementmin gaugedeps
|
build: ghc-8.0 basementmin gaugedeps
|
||||||
build: ghc-8.0 basementmin gaugedeps os=osx
|
build: ghc-8.0 basementmin gaugedeps os=osx
|
||||||
build: ghc-8.4 basementmin testdeps gaugedeps extradep=vector-0.12.0.1
|
build: ghc-8.4
|
||||||
|
build: ghc-8.6
|
||||||
|
|
||||||
# packages
|
# packages
|
||||||
package: '.'
|
package: '.'
|
||||||
|
|||||||
12
.travis.yml
12
.travis.yml
@ -1,4 +1,4 @@
|
|||||||
# ~*~ auto-generated by haskell-ci with config : 7d7fe90696706f37292f4d718fa1a63b938490d653e3abf049623087b2e6e901 ~*~
|
# ~*~ auto-generated by haskell-ci with config : c5de1915986b17c62e2a4cbe1fb7b3d47a6b1dc45a8f4d4fa78654695dfd1f43 ~*~
|
||||||
|
|
||||||
# Use new container infrastructure to enable caching
|
# Use new container infrastructure to enable caching
|
||||||
sudo: false
|
sudo: false
|
||||||
@ -16,6 +16,7 @@ matrix:
|
|||||||
- { env: BUILD=stack RESOLVER=ghc-8.0, compiler: ghc-8.0, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=stack RESOLVER=ghc-8.0, compiler: ghc-8.0, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
- { env: BUILD=stack RESOLVER=ghc-8.0, compiler: ghc-8.0, language: generic, addons: { apt: { packages: [ libgmp-dev ] } }, os: osx }
|
- { env: BUILD=stack RESOLVER=ghc-8.0, compiler: ghc-8.0, language: generic, addons: { apt: { packages: [ libgmp-dev ] } }, os: osx }
|
||||||
- { env: BUILD=stack RESOLVER=ghc-8.4, compiler: ghc-8.4, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=stack RESOLVER=ghc-8.4, compiler: ghc-8.4, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
|
- { env: BUILD=stack RESOLVER=ghc-8.6, compiler: ghc-8.6, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
- { env: BUILD=hlint, compiler: hlint, language: generic }
|
- { env: BUILD=hlint, compiler: hlint, language: generic }
|
||||||
- { env: BUILD=weeder, compiler: weeder, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
- { env: BUILD=weeder, compiler: weeder, language: generic, addons: { apt: { packages: [ libgmp-dev ] } } }
|
||||||
allow_failures:
|
allow_failures:
|
||||||
@ -48,7 +49,7 @@ script:
|
|||||||
# create the build stack.yaml
|
# create the build stack.yaml
|
||||||
case "$RESOLVER" in
|
case "$RESOLVER" in
|
||||||
ghc-8.2)
|
ghc-8.2)
|
||||||
echo "{ resolver: lts-11.6, packages: [ '.' ], extra-deps: [ basement-0.0.6, foundation-0.0.19, memory-0.14.14, gauge-0.2.1 ], flags: {} }" > stack.yaml
|
echo "{ resolver: lts-11.22, packages: [ '.' ], extra-deps: [], flags: {} }" > stack.yaml
|
||||||
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
;;
|
;;
|
||||||
ghc-8.0)
|
ghc-8.0)
|
||||||
@ -60,7 +61,11 @@ script:
|
|||||||
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
;;
|
;;
|
||||||
ghc-8.4)
|
ghc-8.4)
|
||||||
echo "{ resolver: ghc-8.4.2, packages: [ '.' ], extra-deps: [ vector-0.12.0.1, basement-0.0.6, foundation-0.0.19, memory-0.14.14, QuickCheck-2.11.3, ansi-terminal-0.8.0.1, async-2.1.1.1, call-stack-0.1.0, clock-0.7.2, optparse-applicative-0.14.0.0, random-1.1, tagged-0.8.5, unbounded-delays-0.1.1.0, tasty-1.0.0.1, tasty-hunit-0.10.0.1, tasty-kat-0.0.3, tasty-quickcheck-0.9.2, ansi-wl-pprint-0.6.8.2, colour-2.3.4, tf-random-0.5, transformers-compat-0.5.1.4, primitive-0.6.3.0, gauge-0.2.1 ], flags: {}, allow-newer: true }" > stack.yaml
|
echo "{ resolver: lts-12.15, packages: [ '.' ], extra-deps: [], flags: {} }" > stack.yaml
|
||||||
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
|
;;
|
||||||
|
ghc-8.6)
|
||||||
|
echo "{ resolver: nightly-2018-10-21, packages: [ '.' ], extra-deps: [], flags: {} }" > stack.yaml
|
||||||
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
stack --no-terminal build --install-ghc --coverage --test --bench --no-run-benchmarks --haddock --no-haddock-deps
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -75,4 +80,3 @@ script:
|
|||||||
esac
|
esac
|
||||||
set +ex
|
set +ex
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,6 @@
|
|||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
{-# LANGUAGE KindSignatures #-}
|
{-# LANGUAGE KindSignatures #-}
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
{-# LANGUAGE ConstraintKinds #-}
|
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
@ -21,28 +20,31 @@ module Crypto.Hash.SHAKE
|
|||||||
( SHAKE128 (..), SHAKE256 (..)
|
( SHAKE128 (..), SHAKE256 (..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Control.Monad (when)
|
||||||
import Crypto.Hash.Types
|
import Crypto.Hash.Types
|
||||||
import Foreign.Ptr (Ptr)
|
import Foreign.Ptr (Ptr, castPtr)
|
||||||
|
import Foreign.Storable (Storable(..))
|
||||||
|
import Data.Bits
|
||||||
|
import Data.Data
|
||||||
import Data.Typeable
|
import Data.Typeable
|
||||||
import Data.Word (Word8, Word32)
|
import Data.Word (Word8, Word32)
|
||||||
|
|
||||||
import Data.Proxy (Proxy(..))
|
import Data.Proxy (Proxy(..))
|
||||||
import GHC.TypeLits (Nat, KnownNat, natVal)
|
import GHC.TypeLits (Nat, KnownNat, type (+))
|
||||||
import Crypto.Internal.Nat
|
import Crypto.Internal.Nat
|
||||||
|
|
||||||
-- | SHAKE128 (128 bits) extendable output function. Supports an arbitrary
|
-- | SHAKE128 (128 bits) extendable output function. Supports an arbitrary
|
||||||
-- digest size (multiple of 8 bits), to be specified as a type parameter
|
-- digest size, to be specified as a type parameter of kind 'Nat'.
|
||||||
-- of kind 'Nat'.
|
|
||||||
--
|
--
|
||||||
-- Note: outputs from @'SHAKE128' n@ and @'SHAKE128' m@ for the same input are
|
-- Note: outputs from @'SHAKE128' n@ and @'SHAKE128' m@ for the same input are
|
||||||
-- correlated (one being a prefix of the other). Results are unrelated to
|
-- correlated (one being a prefix of the other). Results are unrelated to
|
||||||
-- 'SHAKE256' results.
|
-- 'SHAKE256' results.
|
||||||
data SHAKE128 (bitlen :: Nat) = SHAKE128
|
data SHAKE128 (bitlen :: Nat) = SHAKE128
|
||||||
deriving (Show, Typeable)
|
deriving (Show, Data, Typeable)
|
||||||
|
|
||||||
instance (IsDivisibleBy8 bitlen, KnownNat bitlen) => HashAlgorithm (SHAKE128 bitlen) where
|
instance KnownNat bitlen => HashAlgorithm (SHAKE128 bitlen) where
|
||||||
type HashBlockSize (SHAKE128 bitlen) = 168
|
type HashBlockSize (SHAKE128 bitlen) = 168
|
||||||
type HashDigestSize (SHAKE128 bitlen) = Div8 bitlen
|
type HashDigestSize (SHAKE128 bitlen) = Div8 (bitlen + 7)
|
||||||
type HashInternalContextSize (SHAKE128 bitlen) = 376
|
type HashInternalContextSize (SHAKE128 bitlen) = 376
|
||||||
hashBlockSize _ = 168
|
hashBlockSize _ = 168
|
||||||
hashDigestSize _ = byteLen (Proxy :: Proxy bitlen)
|
hashDigestSize _ = byteLen (Proxy :: Proxy bitlen)
|
||||||
@ -52,18 +54,17 @@ instance (IsDivisibleBy8 bitlen, KnownNat bitlen) => HashAlgorithm (SHAKE128 bit
|
|||||||
hashInternalFinalize = shakeFinalizeOutput (Proxy :: Proxy bitlen)
|
hashInternalFinalize = shakeFinalizeOutput (Proxy :: Proxy bitlen)
|
||||||
|
|
||||||
-- | SHAKE256 (256 bits) extendable output function. Supports an arbitrary
|
-- | SHAKE256 (256 bits) extendable output function. Supports an arbitrary
|
||||||
-- digest size (multiple of 8 bits), to be specified as a type parameter
|
-- digest size, to be specified as a type parameter of kind 'Nat'.
|
||||||
-- of kind 'Nat'.
|
|
||||||
--
|
--
|
||||||
-- Note: outputs from @'SHAKE256' n@ and @'SHAKE256' m@ for the same input are
|
-- Note: outputs from @'SHAKE256' n@ and @'SHAKE256' m@ for the same input are
|
||||||
-- correlated (one being a prefix of the other). Results are unrelated to
|
-- correlated (one being a prefix of the other). Results are unrelated to
|
||||||
-- 'SHAKE128' results.
|
-- 'SHAKE128' results.
|
||||||
data SHAKE256 (bitlen :: Nat) = SHAKE256
|
data SHAKE256 (bitlen :: Nat) = SHAKE256
|
||||||
deriving (Show, Typeable)
|
deriving (Show, Data, Typeable)
|
||||||
|
|
||||||
instance (IsDivisibleBy8 bitlen, KnownNat bitlen) => HashAlgorithm (SHAKE256 bitlen) where
|
instance KnownNat bitlen => HashAlgorithm (SHAKE256 bitlen) where
|
||||||
type HashBlockSize (SHAKE256 bitlen) = 136
|
type HashBlockSize (SHAKE256 bitlen) = 136
|
||||||
type HashDigestSize (SHAKE256 bitlen) = Div8 bitlen
|
type HashDigestSize (SHAKE256 bitlen) = Div8 (bitlen + 7)
|
||||||
type HashInternalContextSize (SHAKE256 bitlen) = 344
|
type HashInternalContextSize (SHAKE256 bitlen) = 344
|
||||||
hashBlockSize _ = 136
|
hashBlockSize _ = 136
|
||||||
hashDigestSize _ = byteLen (Proxy :: Proxy bitlen)
|
hashDigestSize _ = byteLen (Proxy :: Proxy bitlen)
|
||||||
@ -72,7 +73,7 @@ instance (IsDivisibleBy8 bitlen, KnownNat bitlen) => HashAlgorithm (SHAKE256 bit
|
|||||||
hashInternalUpdate = c_sha3_update
|
hashInternalUpdate = c_sha3_update
|
||||||
hashInternalFinalize = shakeFinalizeOutput (Proxy :: Proxy bitlen)
|
hashInternalFinalize = shakeFinalizeOutput (Proxy :: Proxy bitlen)
|
||||||
|
|
||||||
shakeFinalizeOutput :: (IsDivisibleBy8 bitlen, KnownNat bitlen)
|
shakeFinalizeOutput :: KnownNat bitlen
|
||||||
=> proxy bitlen
|
=> proxy bitlen
|
||||||
-> Ptr (Context a)
|
-> Ptr (Context a)
|
||||||
-> Ptr (Digest a)
|
-> Ptr (Digest a)
|
||||||
@ -80,6 +81,16 @@ shakeFinalizeOutput :: (IsDivisibleBy8 bitlen, KnownNat bitlen)
|
|||||||
shakeFinalizeOutput d ctx dig = do
|
shakeFinalizeOutput d ctx dig = do
|
||||||
c_sha3_finalize_shake ctx
|
c_sha3_finalize_shake ctx
|
||||||
c_sha3_output ctx dig (byteLen d)
|
c_sha3_output ctx dig (byteLen d)
|
||||||
|
shakeTruncate d (castPtr dig)
|
||||||
|
|
||||||
|
shakeTruncate :: KnownNat bitlen => proxy bitlen -> Ptr Word8 -> IO ()
|
||||||
|
shakeTruncate d ptr =
|
||||||
|
when (bits > 0) $ do
|
||||||
|
byte <- peekElemOff ptr index
|
||||||
|
pokeElemOff ptr index (byte .&. mask)
|
||||||
|
where
|
||||||
|
mask = (1 `shiftL` bits) - 1
|
||||||
|
(index, bits) = integralNatVal d `divMod` 8
|
||||||
|
|
||||||
foreign import ccall unsafe "cryptonite_sha3_init"
|
foreign import ccall unsafe "cryptonite_sha3_init"
|
||||||
c_sha3_init :: Ptr (Context a) -> Word32 -> IO ()
|
c_sha3_init :: Ptr (Context a) -> Word32 -> IO ()
|
||||||
|
|||||||
@ -15,8 +15,8 @@ module Crypto.Internal.Nat
|
|||||||
|
|
||||||
import GHC.TypeLits
|
import GHC.TypeLits
|
||||||
|
|
||||||
byteLen :: (KnownNat bitlen, IsDivisibleBy8 bitlen, Num a) => proxy bitlen -> a
|
byteLen :: (KnownNat bitlen, Num a) => proxy bitlen -> a
|
||||||
byteLen d = fromInteger (natVal d `div` 8)
|
byteLen d = fromInteger ((natVal d + 7) `div` 8)
|
||||||
|
|
||||||
integralNatVal :: (KnownNat bitlen, Num a) => proxy bitlen -> a
|
integralNatVal :: (KnownNat bitlen, Num a) => proxy bitlen -> a
|
||||||
integralNatVal = fromInteger . natVal
|
integralNatVal = fromInteger . natVal
|
||||||
|
|||||||
@ -36,7 +36,7 @@ Build-Type: Simple
|
|||||||
Homepage: https://github.com/haskell-crypto/cryptonite
|
Homepage: https://github.com/haskell-crypto/cryptonite
|
||||||
Bug-reports: https://github.com/haskell-crypto/cryptonite/issues
|
Bug-reports: https://github.com/haskell-crypto/cryptonite/issues
|
||||||
Cabal-Version: >=1.18
|
Cabal-Version: >=1.18
|
||||||
tested-with: GHC==8.4.2, GHC==8.2.2, GHC==8.0.2
|
tested-with: GHC==8.6.1, GHC==8.4.4, GHC==8.2.2, GHC==8.0.2
|
||||||
extra-doc-files: README.md CHANGELOG.md
|
extra-doc-files: README.md CHANGELOG.md
|
||||||
extra-source-files: cbits/*.h
|
extra-source-files: cbits/*.h
|
||||||
cbits/aes/*.h
|
cbits/aes/*.h
|
||||||
|
|||||||
3
stack.yaml
Normal file
3
stack.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# ~*~ auto-generated by haskell-ci with config : c5de1915986b17c62e2a4cbe1fb7b3d47a6b1dc45a8f4d4fa78654695dfd1f43 ~*~
|
||||||
|
{ resolver: lts-12.15, packages: [ '.' ], extra-deps: [], flags: {} }
|
||||||
|
|
||||||
@ -1,5 +1,4 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
|
||||||
{-# LANGUAGE ExistentialQuantification #-}
|
{-# LANGUAGE ExistentialQuantification #-}
|
||||||
{-# LANGUAGE DataKinds #-}
|
{-# LANGUAGE DataKinds #-}
|
||||||
module Hash
|
module Hash
|
||||||
@ -9,7 +8,9 @@ module Hash
|
|||||||
import Crypto.Hash
|
import Crypto.Hash
|
||||||
|
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
|
import Data.ByteArray (convert)
|
||||||
import qualified Data.ByteArray.Encoding as B (convertToBase, Base(..))
|
import qualified Data.ByteArray.Encoding as B (convertToBase, Base(..))
|
||||||
|
import GHC.TypeLits
|
||||||
import Imports
|
import Imports
|
||||||
|
|
||||||
v0,v1,v2 :: ByteString
|
v0,v1,v2 :: ByteString
|
||||||
@ -235,7 +236,25 @@ makeTestChunk (hashName, hashAlg, _) =
|
|||||||
runhash hashAlg inp `propertyEq` runhashinc hashAlg (chunkS ckLen inp)
|
runhash hashAlg inp `propertyEq` runhashinc hashAlg (chunkS ckLen inp)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
-- SHAKE128 truncation example with expected byte at final position
|
||||||
|
-- <https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/ShakeTruncation.pdf>
|
||||||
|
shake128TruncationBytes = [0x01, 0x03, 0x07, 0x0f, 0x0f, 0x2f, 0x6f, 0x6f]
|
||||||
|
|
||||||
|
makeTestSHAKE128Truncation i byte =
|
||||||
|
testCase (show i) $ xof 4088 `B.snoc` byte @=? xof (4088 + i)
|
||||||
|
where
|
||||||
|
hashEmpty :: KnownNat n => proxy n -> Digest (SHAKE128 n)
|
||||||
|
hashEmpty _ = hash B.empty
|
||||||
|
|
||||||
|
xof n = case someNatVal n of
|
||||||
|
Nothing -> error ("invalid Nat: " ++ show n)
|
||||||
|
Just (SomeNat p) -> convert (hashEmpty p)
|
||||||
|
|
||||||
tests = testGroup "hash"
|
tests = testGroup "hash"
|
||||||
[ testGroup "KATs" (map makeTestAlg expected)
|
[ testGroup "KATs" (map makeTestAlg expected)
|
||||||
, testGroup "Chunking" (concatMap makeTestChunk expected)
|
, testGroup "Chunking" (concatMap makeTestChunk expected)
|
||||||
|
, testGroup "Truncating"
|
||||||
|
[ testGroup "SHAKE128"
|
||||||
|
(zipWith makeTestSHAKE128Truncation [1..] shake128TruncationBytes)
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user