[RSA] remove hashdescr in favor of just specifying the algorithm directly

The extra information is embedded in the HashAlgorithmASN1 class
that allow a digest to ASN1 structured.
This commit is contained in:
Vincent Hanquez 2015-06-10 12:27:37 +01:00
parent 9cc4ffdd04
commit a9df2a2180
3 changed files with 63 additions and 118 deletions

View File

@ -1,101 +0,0 @@
-- |
-- Module : Crypto.PubKey.HashDescr
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
-- Standard digests wrapped in ASN1 structure
--
module Crypto.PubKey.HashDescr
(
-- * Types
HashDescr
, runHashDescr
-- * List of known hash description
, hashDescrMD2
, hashDescrMD5
, hashDescrSHA1
, hashDescrSHA224
, hashDescrSHA256
, hashDescrSHA384
, hashDescrSHA512
, hashDescrRIPEMD160
) where
import Data.Word
import Crypto.Hash
import qualified Crypto.Internal.ByteArray as B
--
-- ** Hack **
--
-- this happens to not need a real ASN1 encoder, because
-- thanks to the digest being a specific size AND
-- that the digest data is the last bytes in the encoding,
-- this allows to just prepend the right prefix to the
-- computed digest, to make it in the expected and valid shape.
--
-- Otherwise the expected structure is in the following form:
--
-- Start Sequence
-- ,Start Sequence
-- ,OID oid
-- ,Null
-- ,End Sequence
-- ,OctetString digest
-- ,End Sequence
hashDescr :: (B.ByteArray ba, HashAlgorithm hashAlg)
=> hashAlg -- ^ hash algorithm to use
-> [Word8] -- ^ the raw DER encoded ASN1 description of hash algorithm followed by the digest to be filled
-> HashDescr hashAlg ba
hashDescr hashAlg preASN1Descr =
HashDescr (\input -> B.pack preASN1Descr `B.append` B.convert (hashWith hashAlg input))
-- | A hash methods to generate a ASN.1 structure digest
data HashDescr hashAlg ba = HashDescr { unHashDescr :: ba -> ba }
-- | Run the digest function on some input and get the raw bytes
runHashDescr :: (HashAlgorithm hashAlg, B.ByteArray ba) => HashDescr hashAlg ba -> ba -> ba
runHashDescr h = unHashDescr h
-- | Describe the MD2 hashing algorithm
hashDescrMD2 :: B.ByteArray ba => HashDescr MD2 ba
hashDescrMD2 =
hashDescr MD2 [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,0x04,0x10]
-- | Describe the MD5 hashing algorithm
hashDescrMD5 :: B.ByteArray ba => HashDescr MD5 ba
hashDescrMD5 =
hashDescr MD5 [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10]
-- | Describe the SHA1 hashing algorithm
hashDescrSHA1 :: B.ByteArray ba => HashDescr SHA1 ba
hashDescrSHA1 =
hashDescr SHA1 [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14]
-- | Describe the SHA224 hashing algorithm
hashDescrSHA224 :: B.ByteArray ba => HashDescr SHA224 ba
hashDescrSHA224 =
hashDescr SHA224 [0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c]
-- | Describe the SHA256 hashing algorithm
hashDescrSHA256 :: B.ByteArray ba => HashDescr SHA256 ba
hashDescrSHA256 =
hashDescr SHA256 [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20]
-- | Describe the SHA384 hashing algorithm
hashDescrSHA384 :: B.ByteArray ba => HashDescr SHA384 ba
hashDescrSHA384 =
hashDescr SHA384 [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30]
-- | Describe the SHA512 hashing algorithm
hashDescrSHA512 :: B.ByteArray ba => HashDescr SHA512 ba
hashDescrSHA512 =
hashDescr SHA512 [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40]
-- | Describe the RIPEMD160 hashing algorithm
hashDescrRIPEMD160 :: B.ByteArray ba => HashDescr RIPEMD160 ba
hashDescrRIPEMD160 =
hashDescr RIPEMD160 [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14]

View File

@ -19,6 +19,8 @@ module Crypto.PubKey.RSA.PKCS15
-- * public key operations -- * public key operations
, encrypt , encrypt
, verify , verify
-- * hash ASN1 description
, HashAlgorithmASN1
) where ) where
import Crypto.Random.Types import Crypto.Random.Types
@ -26,14 +28,59 @@ import Crypto.PubKey.Internal (and')
import Crypto.PubKey.RSA.Types import Crypto.PubKey.RSA.Types
import Crypto.PubKey.RSA.Prim import Crypto.PubKey.RSA.Prim
import Crypto.PubKey.RSA (generateBlinder) import Crypto.PubKey.RSA (generateBlinder)
import Crypto.PubKey.HashDescr import Crypto.Hash
import Crypto.Hash (HashAlgorithm)
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.Word
import Crypto.Internal.ByteArray (ByteArray, Bytes) import Crypto.Internal.ByteArray (ByteArray, Bytes)
import qualified Crypto.Internal.ByteArray as B import qualified Crypto.Internal.ByteArray as B
-- | A specialized class for hash algorithm that can product
-- a ASN1 wrapped description the algorithm plus the content
-- of the digest.
class HashAlgorithm hashAlg => HashAlgorithmASN1 hashAlg where
hashDigestASN1 :: ByteArray out => Digest hashAlg -> out
instance HashAlgorithmASN1 MD2 where
hashDigestASN1 = addDigestPrefix [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,0x04,0x10]
instance HashAlgorithmASN1 MD5 where
hashDigestASN1 = addDigestPrefix [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10]
instance HashAlgorithmASN1 SHA1 where
hashDigestASN1 = addDigestPrefix [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14]
instance HashAlgorithmASN1 SHA224 where
hashDigestASN1 = addDigestPrefix [0x30,0x2d,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1c]
instance HashAlgorithmASN1 SHA256 where
hashDigestASN1 = addDigestPrefix [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20]
instance HashAlgorithmASN1 SHA384 where
hashDigestASN1 = addDigestPrefix [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30]
instance HashAlgorithmASN1 SHA512 where
hashDigestASN1 = addDigestPrefix [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40]
instance HashAlgorithmASN1 RIPEMD160 where
hashDigestASN1 = addDigestPrefix [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14]
--
-- ** Hack **
--
-- this happens to not need a real ASN1 encoder, because
-- thanks to the digest being a specific size AND
-- that the digest data is the last bytes in the encoding,
-- this allows to just prepend the right prefix to the
-- computed digest, to make it in the expected and valid shape.
--
-- Otherwise the expected structure is in the following form:
--
-- Start Sequence
-- ,Start Sequence
-- ,OID oid
-- ,Null
-- ,End Sequence
-- ,OctetString digest
-- ,End Sequence
addDigestPrefix :: ByteArray out => [Word8] -> Digest hashAlg -> out
addDigestPrefix prefix digest =
B.pack prefix `B.append` B.convert digest
-- | This produce a standard PKCS1.5 padding for encryption -- | This produce a standard PKCS1.5 padding for encryption
pad :: (MonadRandom m, ByteArray message) => Int -> message -> m (Either Error message) pad :: (MonadRandom m, ByteArray message) => Int -> message -> m (Either Error message)
pad len m pad len m
@ -116,40 +163,40 @@ encrypt pk m = do
-- information from the timing of the operation, the blinder can be set to None. -- information from the timing of the operation, the blinder can be set to None.
-- --
-- If unsure always set a blinder or use signSafer -- If unsure always set a blinder or use signSafer
sign :: HashAlgorithm hashAlg sign :: HashAlgorithmASN1 hashAlg
=> Maybe Blinder -- ^ optional blinder => Maybe Blinder -- ^ optional blinder
-> HashDescr hashAlg ByteString -- ^ hash descriptor -> hashAlg -- ^ hash algorithm
-> PrivateKey -- ^ private key -> PrivateKey -- ^ private key
-> ByteString -- ^ message to sign -> ByteString -- ^ message to sign
-> Either Error ByteString -> Either Error ByteString
sign blinder hashDescr pk m = dp blinder pk `fmap` makeSignature hashDescr (private_size pk) m sign blinder hashDescr pk m = dp blinder pk `fmap` makeSignature hashDescr (private_size pk) m
-- | sign message using the private key and by automatically generating a blinder. -- | sign message using the private key and by automatically generating a blinder.
signSafer :: (HashAlgorithm hashAlg, MonadRandom m) signSafer :: (HashAlgorithmASN1 hashAlg, MonadRandom m)
=> HashDescr hashAlg ByteString -- ^ Hash descriptor => hashAlg -- ^ Hash algorithm
-> PrivateKey -- ^ private key -> PrivateKey -- ^ private key
-> ByteString -- ^ message to sign -> ByteString -- ^ message to sign
-> m (Either Error ByteString) -> m (Either Error ByteString)
signSafer hashDescr pk m = do signSafer hashAlg pk m = do
blinder <- generateBlinder (private_n pk) blinder <- generateBlinder (private_n pk)
return (sign (Just blinder) hashDescr pk m) return (sign (Just blinder) hashAlg pk m)
-- | verify message with the signed message -- | verify message with the signed message
verify :: HashAlgorithm hashAlg verify :: HashAlgorithmASN1 hashAlg
=> HashDescr hashAlg ByteString => hashAlg
-> PublicKey -> PublicKey
-> ByteString -> ByteString
-> ByteString -> ByteString
-> Bool -> Bool
verify hashDescr pk m sm = verify hashAlg pk m sm =
case makeSignature hashDescr (public_size pk) m of case makeSignature hashAlg (public_size pk) m of
Left _ -> False Left _ -> False
Right s -> s == (ep pk sm) Right s -> s == (ep pk sm)
-- | make signature digest, used in 'sign' and 'verify' -- | make signature digest, used in 'sign' and 'verify'
makeSignature :: HashAlgorithm hashAlg makeSignature :: HashAlgorithmASN1 hashAlg
=> HashDescr hashAlg ByteString => hashAlg
-> Int -> Int
-> ByteString -> ByteString
-> Either Error ByteString -> Either Error ByteString
makeSignature hashDescr klen m = padSignature klen (runHashDescr hashDescr m) makeSignature hashAlg klen m = padSignature klen (hashDigestASN1 $ hashWith hashAlg m)

View File

@ -1,5 +1,5 @@
Name: cryptonite Name: cryptonite
Version: 0.2 Version: 0.3
Synopsis: Cryptography Primitives sink Synopsis: Cryptography Primitives sink
Description: Description:
A repository of cryptographic primitives. A repository of cryptographic primitives.
@ -93,7 +93,6 @@ Library
Crypto.Hash.IO Crypto.Hash.IO
Crypto.Hash.Algorithms Crypto.Hash.Algorithms
Crypto.PubKey.Curve25519 Crypto.PubKey.Curve25519
Crypto.PubKey.HashDescr
Crypto.PubKey.MaskGenFunction Crypto.PubKey.MaskGenFunction
Crypto.PubKey.DH Crypto.PubKey.DH
Crypto.PubKey.DSA Crypto.PubKey.DSA