module Crypto.PubKey.RSA
( Error(..)
, PublicKey(..)
, PrivateKey(..)
, Blinder(..)
, generateWith
, generate
, generateBlinder
) where
import Crypto.Random.Types
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 (Integer
p,Integer
q) Int
size Integer
e =
case Integer -> Integer -> Maybe Integer
inverse Integer
e Integer
phi of
Maybe Integer
Nothing -> Maybe (PublicKey, PrivateKey)
forall a. Maybe a
Nothing
Just 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
-Integer
1)Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
*(Integer
qInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-Integer
1)
qinv :: Integer
qinv = Integer -> Integer -> Integer
inverseCoprimes Integer
q Integer
p
pub :: PublicKey
pub = 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 Integer
d = 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
-Integer
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
-Integer
1)
, private_qinv :: Integer
private_qinv = Integer
qinv
}
generate :: MonadRandom m
=> Int
-> Integer
-> m (PublicKey, PrivateKey)
generate :: forall (m :: * -> *).
MonadRandom m =>
Int -> Integer -> m (PublicKey, PrivateKey)
generate Int
size Integer
e = m (PublicKey, PrivateKey)
loop
where
loop :: m (PublicKey, PrivateKey)
loop = do
(Integer, Integer)
pq <- m (Integer, Integer)
generatePQ
case (Integer, Integer)
-> Int -> Integer -> Maybe (PublicKey, PrivateKey)
generateWith (Integer, Integer)
pq Int
size Integer
e of
Maybe (PublicKey, PrivateKey)
Nothing -> m (PublicKey, PrivateKey)
loop
Just (PublicKey, PrivateKey)
pp -> (PublicKey, PrivateKey) -> m (PublicKey, PrivateKey)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (PublicKey, PrivateKey)
pp
generatePQ :: m (Integer, Integer)
generatePQ = do
Integer
p <- Int -> m Integer
forall (m :: * -> *). MonadRandom m => Int -> m Integer
generatePrime (Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
size Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2))
Integer
q <- Integer -> m Integer
forall {m :: * -> *}. MonadRandom m => Integer -> m Integer
generateQ Integer
p
(Integer, Integer) -> m (Integer, Integer)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Integer
p,Integer
q)
generateQ :: Integer -> m Integer
generateQ Integer
p = do
Integer
q <- Int -> m Integer
forall (m :: * -> *). MonadRandom m => Int -> m Integer
generatePrime (Int
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` Int
2)))
if Integer
p Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
q then Integer -> m Integer
generateQ Integer
p else Integer -> m Integer
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Integer
q
generateBlinder :: MonadRandom m
=> Integer
-> m Blinder
generateBlinder :: forall (m :: * -> *). MonadRandom m => Integer -> m Blinder
generateBlinder Integer
n =
(\Integer
r -> Integer -> Integer -> Blinder
Blinder Integer
r (Integer -> Integer -> Integer
inverseCoprimes Integer
r Integer
n)) (Integer -> Blinder) -> m Integer -> m Blinder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Integer -> m Integer
forall {m :: * -> *}. MonadRandom m => Integer -> m Integer
generateMax Integer
n