module Crypto.PubKey.RSA
( Error(..)
, PublicKey(..)
, PrivateKey(..)
, Blinder(..)
, generateWith
, generate
, generateBlinder
) where
import Crypto.Random
import Crypto.Types.PubKey.RSA
import Crypto.Number.ModArithmetic (inverse, inverseCoprimes)
import Crypto.Number.Generate (generateMax)
import Crypto.Number.Prime (generatePrime)
import Crypto.PubKey.RSA.Types
generateWith :: (Integer, Integer)
-> Int
-> Integer
-> Maybe (PublicKey, PrivateKey)
generateWith :: (Integer, Integer)
-> Int -> Integer -> Maybe (PublicKey, PrivateKey)
generateWith (p :: Integer
p,q :: Integer
q) size :: Int
size e :: Integer
e =
case Integer -> Integer -> Maybe Integer
inverse Integer
e Integer
phi of
Nothing -> Maybe (PublicKey, PrivateKey)
forall a. Maybe a
Nothing
Just d :: Integer
d -> (PublicKey, PrivateKey) -> Maybe (PublicKey, PrivateKey)
forall a. a -> Maybe a
Just (PublicKey
pub,Integer -> PrivateKey
priv Integer
d)
where n :: Integer
n = Integer
pInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
*Integer
q
phi :: Integer
phi = (Integer
pInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-1)Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*(Integer
qInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-1)
qinv :: Integer
qinv = Integer -> Integer -> Integer
inverseCoprimes Integer
q Integer
p
pub :: PublicKey
pub = PublicKey :: Int -> Integer -> Integer -> PublicKey
PublicKey { public_size :: Int
public_size = Int
size
, public_n :: Integer
public_n = Integer
n
, public_e :: Integer
public_e = Integer
e
}
priv :: Integer -> PrivateKey
priv d :: Integer
d = PrivateKey :: PublicKey
-> Integer
-> Integer
-> Integer
-> Integer
-> Integer
-> Integer
-> PrivateKey
PrivateKey { private_pub :: PublicKey
private_pub = PublicKey
pub
, private_d :: Integer
private_d = Integer
d
, private_p :: Integer
private_p = Integer
p
, private_q :: Integer
private_q = Integer
q
, private_dP :: Integer
private_dP = Integer
d Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` (Integer
pInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-1)
, private_dQ :: Integer
private_dQ = Integer
d Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`mod` (Integer
qInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-1)
, private_qinv :: Integer
private_qinv = Integer
qinv
}
generate :: CPRG g
=> g
-> Int
-> Integer
-> ((PublicKey, PrivateKey), g)
generate :: g -> Int -> Integer -> ((PublicKey, PrivateKey), g)
generate rng :: g
rng size :: Int
size e :: Integer
e = g -> ((PublicKey, PrivateKey), g)
forall b. CPRG b => b -> ((PublicKey, PrivateKey), b)
loop g
rng
where loop :: b -> ((PublicKey, PrivateKey), b)
loop g :: b
g =
let (pq :: (Integer, Integer)
pq, g' :: b
g') = b -> ((Integer, Integer), b)
forall b. CPRG b => b -> ((Integer, Integer), b)
generatePQ b
g
in case (Integer, Integer)
-> Int -> Integer -> Maybe (PublicKey, PrivateKey)
generateWith (Integer, Integer)
pq Int
size Integer
e of
Nothing -> b -> ((PublicKey, PrivateKey), b)
loop b
g'
Just pp :: (PublicKey, PrivateKey)
pp -> ((PublicKey, PrivateKey)
pp, b
g')
generatePQ :: b -> ((Integer, Integer), b)
generatePQ g :: b
g =
let (p :: Integer
p, g' :: b
g') = b -> Int -> (Integer, b)
forall g. CPRG g => g -> Int -> (Integer, g)
generatePrime b
g (8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
size Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` 2))
(q :: Integer
q, g'' :: b
g'') = Integer -> b -> (Integer, b)
forall b. CPRG b => Integer -> b -> (Integer, b)
generateQ Integer
p b
g'
in ((Integer
p,Integer
q), b
g'')
generateQ :: Integer -> b -> (Integer, b)
generateQ p :: Integer
p h :: b
h =
let (q :: Integer
q, h' :: b
h') = b -> Int -> (Integer, b)
forall g. CPRG g => g -> Int -> (Integer, g)
generatePrime b
h (8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
size Int -> Int -> Int
forall a. Num a => a -> a -> a
- (Int
size Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` 2)))
in if Integer
p Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
q then Integer -> b -> (Integer, b)
generateQ Integer
p b
h' else (Integer
q, b
h')
generateBlinder :: CPRG g
=> g
-> Integer
-> (Blinder, g)
generateBlinder :: g -> Integer -> (Blinder, g)
generateBlinder rng :: g
rng n :: Integer
n = (Integer -> Integer -> Blinder
Blinder Integer
r (Integer -> Integer -> Integer
inverseCoprimes Integer
r Integer
n), g
rng')
where (r :: Integer
r, rng' :: g
rng') = g -> Integer -> (Integer, g)
forall g. CPRG g => g -> Integer -> (Integer, g)
generateMax g
rng Integer
n