{-# LANGUAGE OverloadedStrings #-}
module Crypto.PubKey.RSA.PKCS15
(
pad
, padSignature
, unpad
, decrypt
, decryptSafer
, sign
, signSafer
, encrypt
, verify
) where
import Crypto.Random
import Crypto.PubKey.Internal (and')
import Crypto.Types.PubKey.RSA
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Crypto.PubKey.RSA.Prim
import Crypto.PubKey.RSA.Types
import Crypto.PubKey.RSA (generateBlinder)
import Crypto.PubKey.HashDescr
pad :: CPRG g => g -> Int -> ByteString -> Either Error (ByteString, g)
pad :: g -> Int -> ByteString -> Either Error (ByteString, g)
pad rng :: g
rng len :: Int
len m :: ByteString
m
| ByteString -> Int
B.length ByteString
m Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- 11 = Error -> Either Error (ByteString, g)
forall a b. a -> Either a b
Left Error
MessageTooLong
| Bool
otherwise =
let (padding :: ByteString
padding, rng' :: g
rng') = g -> Int -> (ByteString, g)
forall g. CPRG g => g -> Int -> (ByteString, g)
getNonNullRandom g
rng (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- ByteString -> Int
B.length ByteString
m Int -> Int -> Int
forall a. Num a => a -> a -> a
- 3)
in (ByteString, g) -> Either Error (ByteString, g)
forall a b. b -> Either a b
Right ([ByteString] -> ByteString
B.concat [ Word8 -> ByteString
B.singleton 0, Word8 -> ByteString
B.singleton 2, ByteString
padding, Word8 -> ByteString
B.singleton 0, ByteString
m ], g
rng')
where
getNonNullRandom :: CPRG g => g -> Int -> (ByteString, g)
getNonNullRandom :: g -> Int -> (ByteString, g)
getNonNullRandom g :: g
g n :: Int
n =
let (bs0 :: ByteString
bs0,g' :: g
g') = Int -> g -> (ByteString, g)
forall gen. CPRG gen => Int -> gen -> (ByteString, gen)
cprgGenerate Int
n g
g
bytes :: ByteString
bytes = [Word8] -> ByteString
B.pack ([Word8] -> ByteString) -> [Word8] -> ByteString
forall a b. (a -> b) -> a -> b
$ (Word8 -> Bool) -> [Word8] -> [Word8]
forall a. (a -> Bool) -> [a] -> [a]
filter (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= 0) ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall a b. (a -> b) -> a -> b
$ ByteString -> [Word8]
B.unpack (ByteString -> [Word8]) -> ByteString -> [Word8]
forall a b. (a -> b) -> a -> b
$ ByteString
bs0
left :: Int
left = (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- ByteString -> Int
B.length ByteString
bytes)
in if Int
left Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 0
then (ByteString
bytes, g
g')
else let (bend :: ByteString
bend, g'' :: g
g'') = g -> Int -> (ByteString, g)
forall g. CPRG g => g -> Int -> (ByteString, g)
getNonNullRandom g
g' Int
left
in (ByteString
bytes ByteString -> ByteString -> ByteString
`B.append` ByteString
bend, g
g'')
padSignature :: Int -> ByteString -> Either Error ByteString
padSignature :: Int -> ByteString -> Either Error ByteString
padSignature klen :: Int
klen signature :: ByteString
signature
| Int
klen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
siglenInt -> Int -> Int
forall a. Num a => a -> a -> a
+1 = Error -> Either Error ByteString
forall a b. a -> Either a b
Left Error
SignatureTooLong
| Bool
otherwise = ByteString -> Either Error ByteString
forall a b. b -> Either a b
Right (ByteString -> Either Error ByteString)
-> ByteString -> Either Error ByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
B.concat [Word8 -> ByteString
B.singleton 0,Word8 -> ByteString
B.singleton 1,ByteString
padding,Word8 -> ByteString
B.singleton 0,ByteString
signature]
where
siglen :: Int
siglen = ByteString -> Int
B.length ByteString
signature
padding :: ByteString
padding = Int -> Word8 -> ByteString
B.replicate (Int
klen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
siglen Int -> Int -> Int
forall a. Num a => a -> a -> a
- 3) 0xff
unpad :: ByteString -> Either Error ByteString
unpad :: ByteString -> Either Error ByteString
unpad packed :: ByteString
packed
| Bool
paddingSuccess = ByteString -> Either Error ByteString
forall a b. b -> Either a b
Right ByteString
m
| Bool
otherwise = Error -> Either Error ByteString
forall a b. a -> Either a b
Left Error
MessageNotRecognized
where
(zt :: ByteString
zt, ps0m :: ByteString
ps0m) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt 2 ByteString
packed
(ps :: ByteString
ps, zm :: ByteString
zm) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
B.span (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= 0) ByteString
ps0m
(z :: ByteString
z, m :: ByteString
m) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt 1 ByteString
zm
paddingSuccess :: Bool
paddingSuccess = [Bool] -> Bool
and' [ ByteString
zt ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== "\x00\x02"
, ByteString
z ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== "\x00"
, ByteString -> Int
B.length ByteString
ps Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= 8
]
decrypt :: Maybe Blinder
-> PrivateKey
-> ByteString
-> Either Error ByteString
decrypt :: Maybe Blinder
-> PrivateKey -> ByteString -> Either Error ByteString
decrypt blinder :: Maybe Blinder
blinder pk :: PrivateKey
pk c :: ByteString
c
| ByteString -> Int
B.length ByteString
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= (PrivateKey -> Int
private_size PrivateKey
pk) = Error -> Either Error ByteString
forall a b. a -> Either a b
Left Error
MessageSizeIncorrect
| Bool
otherwise = ByteString -> Either Error ByteString
unpad (ByteString -> Either Error ByteString)
-> ByteString -> Either Error ByteString
forall a b. (a -> b) -> a -> b
$ Maybe Blinder -> PrivateKey -> ByteString -> ByteString
dp Maybe Blinder
blinder PrivateKey
pk ByteString
c
decryptSafer :: CPRG g
=> g
-> PrivateKey
-> ByteString
-> (Either Error ByteString, g)
decryptSafer :: g -> PrivateKey -> ByteString -> (Either Error ByteString, g)
decryptSafer rng :: g
rng pk :: PrivateKey
pk b :: ByteString
b =
let (blinder :: Blinder
blinder, rng' :: g
rng') = g -> Integer -> (Blinder, g)
forall g. CPRG g => g -> Integer -> (Blinder, g)
generateBlinder g
rng (PrivateKey -> Integer
private_n PrivateKey
pk)
in (Maybe Blinder
-> PrivateKey -> ByteString -> Either Error ByteString
decrypt (Blinder -> Maybe Blinder
forall a. a -> Maybe a
Just Blinder
blinder) PrivateKey
pk ByteString
b, g
rng')
encrypt :: CPRG g => g -> PublicKey -> ByteString -> (Either Error ByteString, g)
encrypt :: g -> PublicKey -> ByteString -> (Either Error ByteString, g)
encrypt rng :: g
rng pk :: PublicKey
pk m :: ByteString
m = do
case g -> Int -> ByteString -> Either Error (ByteString, g)
forall g.
CPRG g =>
g -> Int -> ByteString -> Either Error (ByteString, g)
pad g
rng (PublicKey -> Int
public_size PublicKey
pk) ByteString
m of
Left err :: Error
err -> (Error -> Either Error ByteString
forall a b. a -> Either a b
Left Error
err, g
rng)
Right (em :: ByteString
em, rng' :: g
rng') -> (ByteString -> Either Error ByteString
forall a b. b -> Either a b
Right (PublicKey -> ByteString -> ByteString
ep PublicKey
pk ByteString
em), g
rng')
sign :: Maybe Blinder
-> HashDescr
-> PrivateKey
-> ByteString
-> Either Error ByteString
sign :: Maybe Blinder
-> HashDescr -> PrivateKey -> ByteString -> Either Error ByteString
sign blinder :: Maybe Blinder
blinder hashDescr :: HashDescr
hashDescr pk :: PrivateKey
pk m :: ByteString
m = Maybe Blinder -> PrivateKey -> ByteString -> ByteString
dp Maybe Blinder
blinder PrivateKey
pk (ByteString -> ByteString)
-> Either Error ByteString -> Either Error ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` HashDescr -> Int -> ByteString -> Either Error ByteString
makeSignature HashDescr
hashDescr (PrivateKey -> Int
private_size PrivateKey
pk) ByteString
m
signSafer :: CPRG g
=> g
-> HashDescr
-> PrivateKey
-> ByteString
-> (Either Error ByteString, g)
signSafer :: g
-> HashDescr
-> PrivateKey
-> ByteString
-> (Either Error ByteString, g)
signSafer rng :: g
rng hashDescr :: HashDescr
hashDescr pk :: PrivateKey
pk m :: ByteString
m =
let (blinder :: Blinder
blinder, rng' :: g
rng') = g -> Integer -> (Blinder, g)
forall g. CPRG g => g -> Integer -> (Blinder, g)
generateBlinder g
rng (PrivateKey -> Integer
private_n PrivateKey
pk)
in (Maybe Blinder
-> HashDescr -> PrivateKey -> ByteString -> Either Error ByteString
sign (Blinder -> Maybe Blinder
forall a. a -> Maybe a
Just Blinder
blinder) HashDescr
hashDescr PrivateKey
pk ByteString
m, g
rng')
verify :: HashDescr -> PublicKey -> ByteString -> ByteString -> Bool
verify :: HashDescr -> PublicKey -> ByteString -> ByteString -> Bool
verify hashDescr :: HashDescr
hashDescr pk :: PublicKey
pk m :: ByteString
m sm :: ByteString
sm =
case HashDescr -> Int -> ByteString -> Either Error ByteString
makeSignature HashDescr
hashDescr (PublicKey -> Int
public_size PublicKey
pk) ByteString
m of
Left _ -> Bool
False
Right s :: ByteString
s -> ByteString
s ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== (PublicKey -> ByteString -> ByteString
ep PublicKey
pk ByteString
sm)
makeSignature :: HashDescr -> Int -> ByteString -> Either Error ByteString
makeSignature :: HashDescr -> Int -> ByteString -> Either Error ByteString
makeSignature hashDescr :: HashDescr
hashDescr klen :: Int
klen m :: ByteString
m = Int -> ByteString -> Either Error ByteString
padSignature Int
klen ByteString
signature
where signature :: ByteString
signature = (HashDescr -> ByteString -> ByteString
digestToASN1 HashDescr
hashDescr) (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ (HashDescr -> ByteString -> ByteString
hashFunction HashDescr
hashDescr) ByteString
m