module Crypto.PubKey.RSA
( Error(..)
, PublicKey(..)
, PrivateKey(..)
, Blinder(..)
, generateWith
, generate
, generateBlinder
) where
import Crypto.Random.API
import Crypto.Types.PubKey.RSA
import Crypto.Number.ModArithmetic (inverseCoprimes)
import Crypto.Number.Generate (generateMax)
import Crypto.Number.Prime (generatePrime)
import Crypto.PubKey.RSA.Types
generateWith :: (Integer, Integer) -> Int -> Integer -> (PublicKey, PrivateKey)
generateWith (p,q) size e = (pub,priv)
where n = p*q
phi = (p1)*(q1)
d = inverseCoprimes e phi
pub = PublicKey { public_size = size
, public_n = n
, public_e = e
}
priv = PrivateKey { private_pub = pub
, private_d = d
, private_p = p
, private_q = q
, private_dP = d `mod` (p1)
, private_dQ = d `mod` (q1)
, private_qinv = inverseCoprimes q p
}
generate :: CPRG g => g -> Int -> Integer -> ((PublicKey, PrivateKey), g)
generate rng size e = do
let (pq, rng') = generatePQ rng
in (generateWith pq size e, rng')
where
generatePQ g =
let (p, g') = generatePrime g (8 * (size `div` 2))
(q, g'') = generateQ p g'
in ((p,q), g'')
generateQ p h =
let (q, h') = generatePrime h (8 * (size (size `div` 2)))
in if p == q then generateQ p h' else (q, h')
generateBlinder :: CPRG g
=> g
-> Integer
-> (Blinder, g)
generateBlinder rng n =
let (r, rng') = generateMax rng n
in (Blinder r (inverseCoprimes r n), rng')