module Crypto.PubKey.RSA.Prim
(
dp
, ep
) where
import Crypto.PubKey.RSA.Types
import Crypto.Number.ModArithmetic (expFast, expSafe)
import Crypto.Number.Serialize (os2ip, i2ospOf_)
import Crypto.Internal.ByteArray (ByteArray)
dpSlow :: ByteArray ba => PrivateKey -> ba -> ba
dpSlow pk c = i2ospOf_ (private_size pk) $ expSafe (os2ip c) (private_d pk) (private_n pk)
dpFast :: ByteArray ba => Blinder -> PrivateKey -> ba -> ba
dpFast (Blinder r rm1) pk c =
i2ospOf_ (private_size pk) (multiplication rm1 (m2 + h * (private_q pk)) (private_n pk))
where
re = expFast r (public_e $ private_pub pk) (private_n pk)
iC = multiplication re (os2ip c) (private_n pk)
m1 = expSafe iC (private_dP pk) (private_p pk)
m2 = expSafe iC (private_dQ pk) (private_q pk)
h = ((private_qinv pk) * (m1 - m2)) `mod` (private_p pk)
dpFastNoBlinder :: ByteArray ba => PrivateKey -> ba -> ba
dpFastNoBlinder pk c = i2ospOf_ (private_size pk) (m2 + h * (private_q pk))
where iC = os2ip c
m1 = expSafe iC (private_dP pk) (private_p pk)
m2 = expSafe iC (private_dQ pk) (private_q pk)
h = ((private_qinv pk) * (m1 - m2)) `mod` (private_p pk)
dp :: ByteArray ba => Maybe Blinder -> PrivateKey -> ba -> ba
dp blinder pk
| private_p pk /= 0 && private_q pk /= 0 = maybe dpFastNoBlinder dpFast blinder $ pk
| otherwise = dpSlow pk
ep :: ByteArray ba => PublicKey -> ba -> ba
ep pk m = i2ospOf_ (public_size pk) $ expFast (os2ip m) (public_e pk) (public_n pk)
multiplication :: Integer -> Integer -> Integer -> Integer
multiplication a b m = (a * b) `mod` m