module LibP2P.Crypto.RSA
( generate
, sign
, verify
, derivePublicKey
) where
import Crypto.Hash.Algorithms (SHA256 (..))
import Crypto.Number.Basic (numBytes)
import qualified Crypto.PubKey.RSA as RSA
import qualified Crypto.PubKey.RSA.PKCS15 as PKCS15
import Data.ASN1.BinaryEncoding (DER (..))
import Data.ASN1.Encoding (decodeASN1', encodeASN1')
import Data.ASN1.Types (ASN1 (..), ASN1ConstructionType (..), fromASN1, toASN1)
import Data.ByteString (ByteString)
import Data.X509 (PubKey (PubKeyRSA))
publicExponent :: Integer
publicExponent :: Integer
publicExponent = Integer
0x10001
keySizeBytes :: Int
keySizeBytes :: Int
keySizeBytes = Int
256
generate :: IO (ByteString, ByteString)
generate :: IO (ByteString, ByteString)
generate = do
(pub, priv) <- Int -> Integer -> IO (PublicKey, PrivateKey)
forall (m :: * -> *).
MonadRandom m =>
Int -> Integer -> m (PublicKey, PrivateKey)
RSA.generate Int
keySizeBytes Integer
publicExponent
pure (encodePublicKey pub, encodePrivateKey priv)
sign :: ByteString -> ByteString -> Either String ByteString
sign :: ByteString -> ByteString -> Either String ByteString
sign ByteString
privDer ByteString
msg = do
priv <- ByteString -> Either String PrivateKey
decodePrivateKey ByteString
privDer
case PKCS15.sign Nothing (Just SHA256) priv msg of
Left Error
err -> String -> Either String ByteString
forall a b. a -> Either a b
Left (String -> Either String ByteString)
-> String -> Either String ByteString
forall a b. (a -> b) -> a -> b
$ String
"RSA.sign: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Error -> String
forall a. Show a => a -> String
show Error
err
Right ByteString
sig -> ByteString -> Either String ByteString
forall a b. b -> Either a b
Right ByteString
sig
verify :: ByteString -> ByteString -> ByteString -> Bool
verify :: ByteString -> ByteString -> ByteString -> Bool
verify ByteString
pubDer ByteString
msg ByteString
sig =
case ByteString -> Either String PublicKey
decodePublicKey ByteString
pubDer of
Left String
_ -> Bool
False
Right PublicKey
pub -> Maybe SHA256 -> PublicKey -> ByteString -> ByteString -> Bool
forall hashAlg.
HashAlgorithmASN1 hashAlg =>
Maybe hashAlg -> PublicKey -> ByteString -> ByteString -> Bool
PKCS15.verify (SHA256 -> Maybe SHA256
forall a. a -> Maybe a
Just SHA256
SHA256) PublicKey
pub ByteString
msg ByteString
sig
derivePublicKey :: ByteString -> Either String ByteString
derivePublicKey :: ByteString -> Either String ByteString
derivePublicKey ByteString
privDer = PublicKey -> ByteString
encodePublicKey (PublicKey -> ByteString)
-> (PrivateKey -> PublicKey) -> PrivateKey -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrivateKey -> PublicKey
RSA.private_pub (PrivateKey -> ByteString)
-> Either String PrivateKey -> Either String ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> Either String PrivateKey
decodePrivateKey ByteString
privDer
encodePublicKey :: RSA.PublicKey -> ByteString
encodePublicKey :: PublicKey -> ByteString
encodePublicKey PublicKey
pub = DER -> [ASN1] -> ByteString
forall a. ASN1Encoding a => a -> [ASN1] -> ByteString
encodeASN1' DER
DER (PubKey -> ASN1S
forall a. ASN1Object a => a -> ASN1S
toASN1 (PublicKey -> PubKey
PubKeyRSA PublicKey
pub) [])
decodePublicKey :: ByteString -> Either String RSA.PublicKey
decodePublicKey :: ByteString -> Either String PublicKey
decodePublicKey ByteString
bs =
case DER -> ByteString -> Either ASN1Error [ASN1]
forall a.
ASN1Decoding a =>
a -> ByteString -> Either ASN1Error [ASN1]
decodeASN1' DER
DER ByteString
bs of
Left ASN1Error
err -> String -> Either String PublicKey
forall a b. a -> Either a b
Left (String -> Either String PublicKey)
-> String -> Either String PublicKey
forall a b. (a -> b) -> a -> b
$ String
"RSA.decodePublicKey: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> ASN1Error -> String
forall a. Show a => a -> String
show ASN1Error
err
Right [ASN1]
asn1 -> case [ASN1] -> Either String (PubKey, [ASN1])
forall a. ASN1Object a => [ASN1] -> Either String (a, [ASN1])
fromASN1 [ASN1]
asn1 of
Right (PubKeyRSA PublicKey
pub, [ASN1]
_) -> PublicKey -> Either String PublicKey
forall a b. b -> Either a b
Right PublicKey
pub
Right (PubKey, [ASN1])
_ -> String -> Either String PublicKey
forall a b. a -> Either a b
Left String
"RSA.decodePublicKey: not an RSA public key"
Left String
err -> String -> Either String PublicKey
forall a b. a -> Either a b
Left (String -> Either String PublicKey)
-> String -> Either String PublicKey
forall a b. (a -> b) -> a -> b
$ String
"RSA.decodePublicKey: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
err
encodePrivateKey :: RSA.PrivateKey -> ByteString
encodePrivateKey :: PrivateKey -> ByteString
encodePrivateKey PrivateKey
priv =
DER -> [ASN1] -> ByteString
forall a. ASN1Encoding a => a -> [ASN1] -> ByteString
encodeASN1' DER
DER ([ASN1] -> ByteString) -> [ASN1] -> ByteString
forall a b. (a -> b) -> a -> b
$
[ ASN1ConstructionType -> ASN1
Start ASN1ConstructionType
Sequence
, Integer -> ASN1
IntVal Integer
0
, Integer -> ASN1
IntVal (PublicKey -> Integer
RSA.public_n (PrivateKey -> PublicKey
RSA.private_pub PrivateKey
priv))
, Integer -> ASN1
IntVal (PublicKey -> Integer
RSA.public_e (PrivateKey -> PublicKey
RSA.private_pub PrivateKey
priv))
, Integer -> ASN1
IntVal (PrivateKey -> Integer
RSA.private_d PrivateKey
priv)
, Integer -> ASN1
IntVal (PrivateKey -> Integer
RSA.private_p PrivateKey
priv)
, Integer -> ASN1
IntVal (PrivateKey -> Integer
RSA.private_q PrivateKey
priv)
, Integer -> ASN1
IntVal (PrivateKey -> Integer
RSA.private_dP PrivateKey
priv)
, Integer -> ASN1
IntVal (PrivateKey -> Integer
RSA.private_dQ PrivateKey
priv)
, Integer -> ASN1
IntVal (PrivateKey -> Integer
RSA.private_qinv PrivateKey
priv)
, ASN1ConstructionType -> ASN1
End ASN1ConstructionType
Sequence
]
decodePrivateKey :: ByteString -> Either String RSA.PrivateKey
decodePrivateKey :: ByteString -> Either String PrivateKey
decodePrivateKey ByteString
bs =
case DER -> ByteString -> Either ASN1Error [ASN1]
forall a.
ASN1Decoding a =>
a -> ByteString -> Either ASN1Error [ASN1]
decodeASN1' DER
DER ByteString
bs of
Left ASN1Error
err -> String -> Either String PrivateKey
forall a b. a -> Either a b
Left (String -> Either String PrivateKey)
-> String -> Either String PrivateKey
forall a b. (a -> b) -> a -> b
$ String
"RSA.decodePrivateKey: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> ASN1Error -> String
forall a. Show a => a -> String
show ASN1Error
err
Right
( Start ASN1ConstructionType
Sequence
: IntVal Integer
_ver
: IntVal Integer
n
: IntVal Integer
e
: IntVal Integer
d
: IntVal Integer
p
: IntVal Integer
q
: IntVal Integer
dP
: IntVal Integer
dQ
: IntVal Integer
qinv
: End ASN1ConstructionType
Sequence
: [ASN1]
_
) ->
PrivateKey -> Either String PrivateKey
forall a b. b -> Either a b
Right
RSA.PrivateKey
{ private_pub :: PublicKey
RSA.private_pub =
RSA.PublicKey {public_size :: Int
RSA.public_size = Integer -> Int
numBytes Integer
n, public_n :: Integer
RSA.public_n = Integer
n, public_e :: Integer
RSA.public_e = Integer
e}
, private_d :: Integer
RSA.private_d = Integer
d
, private_p :: Integer
RSA.private_p = Integer
p
, private_q :: Integer
RSA.private_q = Integer
q
, private_dP :: Integer
RSA.private_dP = Integer
dP
, private_dQ :: Integer
RSA.private_dQ = Integer
dQ
, private_qinv :: Integer
RSA.private_qinv = Integer
qinv
}
Right [ASN1]
_ -> String -> Either String PrivateKey
forall a b. a -> Either a b
Left String
"RSA.decodePrivateKey: unexpected ASN.1 structure"