mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-08-04 22:00:39 +00:00
simplify RSA private key types (#207)
* simplify RSA private key types * remove updateSignKey method
This commit is contained in:
@@ -101,7 +101,7 @@ getConfig opts = do
|
||||
storeLog <- liftIO $ openStoreLog opts ini
|
||||
pure $ makeConfig ini pk storeLog
|
||||
|
||||
makeConfig :: IniOpts -> C.FullPrivateKey -> Maybe (StoreLog 'ReadMode) -> ServerConfig
|
||||
makeConfig :: IniOpts -> C.PrivateKey -> Maybe (StoreLog 'ReadMode) -> ServerConfig
|
||||
makeConfig IniOpts {serverPort, blockSize, enableWebsockets} pk storeLog =
|
||||
let transports = (serverPort, transport @TCP) : [("80", transport @WS) | enableWebsockets]
|
||||
in serverConfig {serverPrivateKey = pk, storeLog, blockSize, transports}
|
||||
@@ -200,11 +200,11 @@ createIni ServerOpts {enableStoreLog} = do
|
||||
enableWebsockets = True
|
||||
}
|
||||
|
||||
readKey :: IniOpts -> ExceptT String IO C.FullPrivateKey
|
||||
readKey :: IniOpts -> ExceptT String IO C.PrivateKey
|
||||
readKey IniOpts {serverKeyFile} = do
|
||||
fileExists serverKeyFile
|
||||
liftIO (S.readKeyFile serverKeyFile) >>= \case
|
||||
[S.Unprotected (PrivKeyRSA pk)] -> pure $ C.FullPrivateKey pk
|
||||
[S.Unprotected (PrivKeyRSA pk)] -> pure $ C.PrivateKey pk
|
||||
[_] -> err "not RSA key"
|
||||
[] -> err "invalid key file format"
|
||||
_ -> err "more than one key"
|
||||
@@ -212,7 +212,7 @@ readKey IniOpts {serverKeyFile} = do
|
||||
err :: String -> ExceptT String IO b
|
||||
err e = throwE $ e <> ": " <> serverKeyFile
|
||||
|
||||
createKey :: IniOpts -> IO C.FullPrivateKey
|
||||
createKey :: IniOpts -> IO C.PrivateKey
|
||||
createKey IniOpts {serverKeyFile} = do
|
||||
(_, pk) <- C.generateKeyPair newKeySize
|
||||
S.writeKeyFile S.TraditionalFormat serverKeyFile [PrivKeyRSA $ C.rsaPrivateKey pk]
|
||||
@@ -233,7 +233,7 @@ confirm msg = do
|
||||
ok <- getLine
|
||||
when (map toLower ok /= "y") exitFailure
|
||||
|
||||
serverKeyHash :: C.FullPrivateKey -> B.ByteString
|
||||
serverKeyHash :: C.PrivateKey -> B.ByteString
|
||||
serverKeyHash = encode . C.unKeyHash . C.publicKeyHash . C.publicKey'
|
||||
|
||||
openStoreLog :: ServerOpts -> IniOpts -> IO (Maybe (StoreLog 'ReadMode))
|
||||
|
||||
@@ -40,9 +40,7 @@ It provides:
|
||||
SMP agent protocol provides no encryption or security on the client side - it is assumed that the agent is executed in the trusted and secure environment, in one of three ways:
|
||||
- via TCP network using secure connection.
|
||||
- via local port (when the agent runs on the same device as a separate process).
|
||||
- via agent library, when the agent logic is included directly into the client application.
|
||||
|
||||
The last option is the most secure, as it reduces the number of attack vectors in comparison with other options. [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat) uses this approach.
|
||||
- via agent library, when the agent logic is included directly into the client application - [SimpleX Chat for terminal](https://github.com/simplex-chat/simplex-chat) uses this approach.
|
||||
|
||||
## SMP agent
|
||||
|
||||
|
||||
@@ -298,30 +298,27 @@ subscribeConnection' c connId =
|
||||
SomeConn _ (DuplexConnection _ rq sq) -> do
|
||||
resumeMsgDelivery c connId sq
|
||||
case status (sq :: SndQueue) of
|
||||
Confirmed -> withVerifyKey sq $ \verifyKey -> do
|
||||
Confirmed -> do
|
||||
conf <- withStore (`getAcceptedConfirmation` connId)
|
||||
secureQueue c rq $ senderKey (conf :: AcceptedConfirmation)
|
||||
withStore $ \st -> setRcvQueueStatus st rq Secured
|
||||
activateSecuredQueue rq sq verifyKey
|
||||
Secured -> withVerifyKey sq $ activateSecuredQueue rq sq
|
||||
activateSecuredQueue rq sq
|
||||
Secured -> activateSecuredQueue rq sq
|
||||
Active -> subscribeQueue c rq connId
|
||||
_ -> throwError $ INTERNAL "unexpected queue status"
|
||||
SomeConn _ (SndConnection _ sq) -> do
|
||||
resumeMsgDelivery c connId sq
|
||||
case status (sq :: SndQueue) of
|
||||
Confirmed -> withVerifyKey sq $ \verifyKey ->
|
||||
activateQueueJoining c connId sq verifyKey =<< resumeInterval
|
||||
Confirmed -> activateQueueJoining c connId sq (verifyKey sq) =<< resumeInterval
|
||||
Active -> throwError $ CONN SIMPLEX
|
||||
_ -> throwError $ INTERNAL "unexpected queue status"
|
||||
SomeConn _ (RcvConnection _ rq) -> subscribeQueue c rq connId
|
||||
where
|
||||
withVerifyKey :: SndQueue -> (C.PublicKey -> m ()) -> m ()
|
||||
withVerifyKey sq action =
|
||||
let err = throwError $ INTERNAL "missing signing key public counterpart"
|
||||
in maybe err action . C.publicKey $ signKey sq
|
||||
activateSecuredQueue :: RcvQueue -> SndQueue -> C.PublicKey -> m ()
|
||||
activateSecuredQueue rq sq verifyKey = do
|
||||
activateQueueInitiating c connId sq verifyKey =<< resumeInterval
|
||||
verifyKey :: SndQueue -> C.PublicKey
|
||||
verifyKey = C.publicKey' . signKey
|
||||
activateSecuredQueue :: RcvQueue -> SndQueue -> m ()
|
||||
activateSecuredQueue rq sq = do
|
||||
activateQueueInitiating c connId sq (verifyKey sq) =<< resumeInterval
|
||||
subscribeQueue c rq connId
|
||||
resumeInterval :: m RetryInterval
|
||||
resumeInterval = do
|
||||
@@ -600,12 +597,7 @@ activateQueue c connId sq verifyKey retryInterval afterActivation =
|
||||
sendHello c sq verifyKey retryInterval
|
||||
withStore $ \st -> setSndQueueStatus st sq Active
|
||||
removeActivation c connId
|
||||
removeVerificationKey
|
||||
afterActivation
|
||||
removeVerificationKey :: m ()
|
||||
removeVerificationKey =
|
||||
let safeSignKey = C.removePublicKey $ signKey sq
|
||||
in withStore $ \st -> updateSignKey st sq safeSignKey
|
||||
|
||||
notifyConnected :: AgentMonad m => AgentClient -> ConnId -> m ()
|
||||
notifyConnected c connId = atomically $ writeTBQueue (subQ c) ("", connId, CON)
|
||||
|
||||
@@ -339,10 +339,10 @@ data SMPQueueInfo = SMPQueueInfo SMPServer SMP.SenderId EncryptionKey
|
||||
type EncryptionKey = C.PublicKey
|
||||
|
||||
-- | Private key used to E2E decrypt SMP messages.
|
||||
type DecryptionKey = C.SafePrivateKey
|
||||
type DecryptionKey = C.PrivateKey
|
||||
|
||||
-- | Private key used to sign SMP commands
|
||||
type SignatureKey = C.APrivateKey
|
||||
type SignatureKey = C.PrivateKey
|
||||
|
||||
-- | Public key used by SMP server to authorize (verify) SMP commands.
|
||||
type VerificationKey = C.PublicKey
|
||||
|
||||
@@ -43,7 +43,6 @@ class Monad m => MonadAgentStore s m where
|
||||
setRcvQueueStatus :: s -> RcvQueue -> QueueStatus -> m ()
|
||||
setRcvQueueActive :: s -> RcvQueue -> VerificationKey -> m ()
|
||||
setSndQueueStatus :: s -> SndQueue -> QueueStatus -> m ()
|
||||
updateSignKey :: s -> SndQueue -> SignatureKey -> m ()
|
||||
|
||||
-- Confirmations
|
||||
createConfirmation :: s -> TVar ChaChaDRG -> NewConfirmation -> m ConfirmationId
|
||||
|
||||
@@ -279,18 +279,6 @@ instance (MonadUnliftIO m, MonadError StoreError m) => MonadAgentStore SQLiteSto
|
||||
|]
|
||||
[":status" := status, ":host" := host, ":port" := serializePort_ port, ":snd_id" := sndId]
|
||||
|
||||
updateSignKey :: SQLiteStore -> SndQueue -> SignatureKey -> m ()
|
||||
updateSignKey st SndQueue {sndId, server = SMPServer {host, port}} signatureKey =
|
||||
liftIO . withTransaction st $ \db ->
|
||||
DB.executeNamed
|
||||
db
|
||||
[sql|
|
||||
UPDATE snd_queues
|
||||
SET sign_key = :sign_key
|
||||
WHERE host = :host AND port = :port AND snd_id = :snd_id;
|
||||
|]
|
||||
[":sign_key" := signatureKey, ":host" := host, ":port" := serializePort_ port, ":snd_id" := sndId]
|
||||
|
||||
createConfirmation :: SQLiteStore -> TVar ChaChaDRG -> NewConfirmation -> m ConfirmationId
|
||||
createConfirmation st gVar NewConfirmation {connId, senderKey, senderConnInfo} =
|
||||
liftIOEither . withTransaction st $ \db ->
|
||||
|
||||
@@ -333,14 +333,14 @@ suspendSMPQueue = okSMPCommand $ Cmd SRecipient OFF
|
||||
deleteSMPQueue :: SMPClient -> RecipientPrivateKey -> QueueId -> ExceptT SMPClientError IO ()
|
||||
deleteSMPQueue = okSMPCommand $ Cmd SRecipient DEL
|
||||
|
||||
okSMPCommand :: Cmd -> SMPClient -> C.SafePrivateKey -> QueueId -> ExceptT SMPClientError IO ()
|
||||
okSMPCommand :: Cmd -> SMPClient -> C.PrivateKey -> QueueId -> ExceptT SMPClientError IO ()
|
||||
okSMPCommand cmd c pKey qId =
|
||||
sendSMPCommand c (Just pKey) qId cmd >>= \case
|
||||
Cmd _ OK -> return ()
|
||||
_ -> throwE SMPUnexpectedResponse
|
||||
|
||||
-- | Send any SMP command ('Cmd' type).
|
||||
sendSMPCommand :: SMPClient -> Maybe C.SafePrivateKey -> QueueId -> Cmd -> ExceptT SMPClientError IO Cmd
|
||||
sendSMPCommand :: SMPClient -> Maybe C.PrivateKey -> QueueId -> Cmd -> ExceptT SMPClientError IO Cmd
|
||||
sendSMPCommand SMPClient {sndQ, sentCommands, clientCorrId, tcpTimeout} pKey qId cmd = do
|
||||
corrId <- lift_ getNextCorrId
|
||||
t <- signTransmission $ serializeTransmission (corrId, qId, cmd)
|
||||
|
||||
+21
-109
@@ -20,20 +20,14 @@
|
||||
-- <https://hackage.haskell.org/package/cryptonite cryptonite package>.
|
||||
module Simplex.Messaging.Crypto
|
||||
( -- * RSA keys
|
||||
PrivateKey (rsaPrivateKey, publicKey),
|
||||
SafePrivateKey (..), -- constructor is not exported
|
||||
FullPrivateKey (..),
|
||||
APrivateKey (..),
|
||||
PrivateKey (..),
|
||||
PublicKey (..),
|
||||
SafeKeyPair,
|
||||
FullKeyPair,
|
||||
KeyPair,
|
||||
KeyHash (..),
|
||||
generateKeyPair,
|
||||
publicKey',
|
||||
publicKeySize,
|
||||
validKeySize,
|
||||
safePrivateKey,
|
||||
removePublicKey,
|
||||
|
||||
-- * E2E hybrid encryption scheme
|
||||
encrypt,
|
||||
@@ -114,86 +108,25 @@ import Simplex.Messaging.Util (liftEitherError, (<$?>))
|
||||
-- | A newtype of 'Crypto.PubKey.RSA.PublicKey'.
|
||||
newtype PublicKey = PublicKey {rsaPublicKey :: R.PublicKey} deriving (Eq, Show)
|
||||
|
||||
-- | A newtype of 'Crypto.PubKey.RSA.PrivateKey', with PublicKey removed.
|
||||
--
|
||||
-- It is not possible to recover PublicKey from SafePrivateKey.
|
||||
-- The constructor of this type is not exported.
|
||||
newtype SafePrivateKey = SafePrivateKey {unPrivateKey :: R.PrivateKey} deriving (Eq, Show)
|
||||
|
||||
-- | A newtype of 'Crypto.PubKey.RSA.PrivateKey' (with PublicKey inside).
|
||||
newtype FullPrivateKey = FullPrivateKey {unPrivateKey :: R.PrivateKey} deriving (Eq, Show)
|
||||
|
||||
-- | A newtype of 'Crypto.PubKey.RSA.PrivateKey' (PublicKey may be inside).
|
||||
newtype APrivateKey = APrivateKey {unPrivateKey :: R.PrivateKey} deriving (Eq, Show)
|
||||
newtype PrivateKey = PrivateKey {rsaPrivateKey :: R.PrivateKey} deriving (Eq, Show)
|
||||
|
||||
-- | Type-class used for both private key types: SafePrivateKey and FullPrivateKey.
|
||||
class PrivateKey k where
|
||||
-- unwraps 'Crypto.PubKey.RSA.PrivateKey'
|
||||
rsaPrivateKey :: k -> R.PrivateKey
|
||||
|
||||
-- equivalent to data type constructor, not exported
|
||||
_privateKey :: R.PrivateKey -> k
|
||||
|
||||
-- smart constructor removing public key from SafePrivateKey but keeping it in FullPrivateKey
|
||||
mkPrivateKey :: R.PrivateKey -> k
|
||||
|
||||
-- extracts public key from private key
|
||||
publicKey :: k -> Maybe PublicKey
|
||||
|
||||
-- | Remove public key exponent from APrivateKey.
|
||||
removePublicKey :: APrivateKey -> APrivateKey
|
||||
removePublicKey (APrivateKey R.PrivateKey {private_pub = k, private_d}) =
|
||||
APrivateKey $ unPrivateKey (safePrivateKey (R.public_size k, R.public_n k, private_d) :: SafePrivateKey)
|
||||
|
||||
instance PrivateKey SafePrivateKey where
|
||||
rsaPrivateKey = unPrivateKey
|
||||
_privateKey = SafePrivateKey
|
||||
mkPrivateKey R.PrivateKey {private_pub = k, private_d} =
|
||||
safePrivateKey (R.public_size k, R.public_n k, private_d)
|
||||
publicKey _ = Nothing
|
||||
|
||||
instance PrivateKey FullPrivateKey where
|
||||
rsaPrivateKey = unPrivateKey
|
||||
_privateKey = FullPrivateKey
|
||||
mkPrivateKey = FullPrivateKey
|
||||
publicKey = Just . PublicKey . R.private_pub . rsaPrivateKey
|
||||
|
||||
instance PrivateKey APrivateKey where
|
||||
rsaPrivateKey = unPrivateKey
|
||||
_privateKey = APrivateKey
|
||||
mkPrivateKey = APrivateKey
|
||||
publicKey pk =
|
||||
let k = R.private_pub $ rsaPrivateKey pk
|
||||
in if R.public_e k == 0
|
||||
then Nothing
|
||||
else Just $ PublicKey k
|
||||
|
||||
instance IsString FullPrivateKey where
|
||||
instance IsString PrivateKey where
|
||||
fromString = parseString $ decode >=> decodePrivKey
|
||||
|
||||
instance IsString PublicKey where
|
||||
fromString = parseString $ decode >=> decodePubKey
|
||||
|
||||
instance ToField SafePrivateKey where toField = toField . encodePrivKey
|
||||
|
||||
instance ToField APrivateKey where toField = toField . encodePrivKey
|
||||
instance ToField PrivateKey where toField = toField . encodePrivKey
|
||||
|
||||
instance ToField PublicKey where toField = toField . encodePubKey
|
||||
|
||||
instance FromField SafePrivateKey where fromField = blobFieldParser binaryPrivKeyP
|
||||
|
||||
instance FromField APrivateKey where fromField = blobFieldParser binaryPrivKeyP
|
||||
instance FromField PrivateKey where fromField = blobFieldParser binaryPrivKeyP
|
||||
|
||||
instance FromField PublicKey where fromField = blobFieldParser binaryPubKeyP
|
||||
|
||||
-- | Tuple of RSA 'PublicKey' and 'PrivateKey'.
|
||||
type KeyPair k = (PublicKey, k)
|
||||
|
||||
-- | Tuple of RSA 'PublicKey' and 'SafePrivateKey'.
|
||||
type SafeKeyPair = (PublicKey, SafePrivateKey)
|
||||
|
||||
-- | Tuple of RSA 'PublicKey' and 'FullPrivateKey'.
|
||||
type FullKeyPair = (PublicKey, FullPrivateKey)
|
||||
type KeyPair = (PublicKey, PrivateKey)
|
||||
|
||||
-- | RSA signature newtype.
|
||||
newtype Signature = Signature {unSignature :: ByteString} deriving (Eq, Show)
|
||||
@@ -230,8 +163,8 @@ aesKeySize = 256 `div` 8
|
||||
authTagSize :: Int
|
||||
authTagSize = 128 `div` 8
|
||||
|
||||
-- | Generate RSA key pair with either SafePrivateKey or FullPrivateKey.
|
||||
generateKeyPair :: PrivateKey k => Int -> IO (KeyPair k)
|
||||
-- | Generate RSA key pair.
|
||||
generateKeyPair :: Int -> IO KeyPair
|
||||
generateKeyPair size = loop
|
||||
where
|
||||
publicExponent = findPrimeFrom . (+ 3) <$> generateMax pubExpRange
|
||||
@@ -241,12 +174,12 @@ generateKeyPair size = loop
|
||||
d = R.private_d pk
|
||||
if d * d < n
|
||||
then loop
|
||||
else pure (PublicKey k, mkPrivateKey pk)
|
||||
else pure (PublicKey k, PrivateKey pk)
|
||||
|
||||
privateKeySize :: PrivateKey k => k -> Int
|
||||
privateKeySize :: PrivateKey -> Int
|
||||
privateKeySize = R.public_size . R.private_pub . rsaPrivateKey
|
||||
|
||||
publicKey' :: FullPrivateKey -> PublicKey
|
||||
publicKey' :: PrivateKey -> PublicKey
|
||||
publicKey' = PublicKey . R.private_pub . rsaPrivateKey
|
||||
|
||||
publicKeySize :: PublicKey -> Int
|
||||
@@ -331,7 +264,7 @@ encrypt k paddedSize msg = do
|
||||
-- | E2E decrypt SMP agent messages.
|
||||
--
|
||||
-- https://github.com/simplex-chat/simplexmq/blob/master/rfcs/2021-01-26-crypto.md#e2e-encryption
|
||||
decrypt :: PrivateKey k => k -> ByteString -> ExceptT CryptoError IO ByteString
|
||||
decrypt :: PrivateKey -> ByteString -> ExceptT CryptoError IO ByteString
|
||||
decrypt pk msg'' = do
|
||||
let (encHeader, msg') = B.splitAt (privateKeySize pk) msg''
|
||||
header <- decryptOAEP pk encHeader
|
||||
@@ -410,7 +343,7 @@ encryptOAEP (PublicKey k) aesKey =
|
||||
-- | RSA OAEP decryption.
|
||||
--
|
||||
-- Used as part of hybrid E2E encryption scheme and for SMP transport handshake.
|
||||
decryptOAEP :: PrivateKey k => k -> ByteString -> ExceptT CryptoError IO ByteString
|
||||
decryptOAEP :: PrivateKey -> ByteString -> ExceptT CryptoError IO ByteString
|
||||
decryptOAEP pk encKey =
|
||||
liftEitherError RSADecryptError $
|
||||
OAEP.decryptSafer oaepParams (rsaPrivateKey pk) encKey
|
||||
@@ -421,7 +354,7 @@ pssParams = PSS.defaultPSSParams SHA256
|
||||
-- | RSA PSS message signing.
|
||||
--
|
||||
-- Used by SMP clients to sign SMP commands and by SMP agents to sign messages.
|
||||
sign :: PrivateKey k => k -> ByteString -> ExceptT CryptoError IO Signature
|
||||
sign :: PrivateKey -> ByteString -> ExceptT CryptoError IO Signature
|
||||
sign pk msg = ExceptT $ bimap RSASignError Signature <$> PSS.signSafer pssParams (rsaPrivateKey pk) msg
|
||||
|
||||
-- | RSA PSS signature verification.
|
||||
@@ -439,7 +372,7 @@ serializePubKey = ("rsa:" <>) . encode . encodePubKey
|
||||
-- | Base-64 PKCS8 encoding of PSA private key.
|
||||
--
|
||||
-- Not used as part of SMP protocols.
|
||||
serializePrivKey :: PrivateKey k => k -> ByteString
|
||||
serializePrivKey :: PrivateKey -> ByteString
|
||||
serializePrivKey = ("rsa:" <>) . encode . encodePrivKey
|
||||
|
||||
-- Base-64 X509 RSA public key parser.
|
||||
@@ -451,40 +384,19 @@ binaryPubKeyP :: Parser PublicKey
|
||||
binaryPubKeyP = decodePubKey <$?> A.takeByteString
|
||||
|
||||
-- Base-64 PKCS8 RSA private key parser.
|
||||
privKeyP :: PrivateKey k => Parser k
|
||||
privKeyP :: Parser PrivateKey
|
||||
privKeyP = decodePrivKey <$?> ("rsa:" *> base64P)
|
||||
|
||||
-- Binary PKCS8 RSA private key parser.
|
||||
binaryPrivKeyP :: PrivateKey k => Parser k
|
||||
binaryPrivKeyP :: Parser PrivateKey
|
||||
binaryPrivKeyP = decodePrivKey <$?> A.takeByteString
|
||||
|
||||
-- | Construct 'SafePrivateKey' from three numbers - used internally and in the tests.
|
||||
safePrivateKey :: (Int, Integer, Integer) -> SafePrivateKey
|
||||
safePrivateKey = SafePrivateKey . safeRsaPrivateKey
|
||||
|
||||
safeRsaPrivateKey :: (Int, Integer, Integer) -> R.PrivateKey
|
||||
safeRsaPrivateKey (size, n, d) =
|
||||
R.PrivateKey
|
||||
{ private_pub =
|
||||
R.PublicKey
|
||||
{ public_size = size,
|
||||
public_n = n,
|
||||
public_e = 0
|
||||
},
|
||||
private_d = d,
|
||||
private_p = 0,
|
||||
private_q = 0,
|
||||
private_dP = 0,
|
||||
private_dQ = 0,
|
||||
private_qinv = 0
|
||||
}
|
||||
|
||||
-- Binary X509 encoding of 'PublicKey'.
|
||||
encodePubKey :: PublicKey -> ByteString
|
||||
encodePubKey = encodeKey . PubKeyRSA . rsaPublicKey
|
||||
|
||||
-- Binary PKCS8 encoding of 'PrivateKey'.
|
||||
encodePrivKey :: PrivateKey k => k -> ByteString
|
||||
encodePrivKey :: PrivateKey -> ByteString
|
||||
encodePrivKey = encodeKey . PrivKeyRSA . rsaPrivateKey
|
||||
|
||||
encodeKey :: ASN1Object a => a -> ByteString
|
||||
@@ -498,10 +410,10 @@ decodePubKey =
|
||||
r -> keyError r
|
||||
|
||||
-- Decoding of binary PKCS8 'PrivateKey'.
|
||||
decodePrivKey :: PrivateKey k => ByteString -> Either String k
|
||||
decodePrivKey :: ByteString -> Either String PrivateKey
|
||||
decodePrivKey =
|
||||
decodeKey >=> \case
|
||||
(PrivKeyRSA pk, []) -> Right $ mkPrivateKey pk
|
||||
(PrivKeyRSA pk, []) -> Right $ PrivateKey pk
|
||||
r -> keyError r
|
||||
|
||||
decodeKey :: ASN1Object a => ByteString -> Either String (a, [ASN1])
|
||||
|
||||
@@ -177,7 +177,7 @@ instance IsString CorrId where
|
||||
-- | Recipient's private key used by the recipient to authorize (sign) SMP commands.
|
||||
--
|
||||
-- Only used by SMP agent, kept here so its definition is close to respective public key.
|
||||
type RecipientPrivateKey = C.SafePrivateKey
|
||||
type RecipientPrivateKey = C.PrivateKey
|
||||
|
||||
-- | Recipient's public key used by SMP server to verify authorization of SMP commands.
|
||||
type RecipientPublicKey = C.PublicKey
|
||||
@@ -185,13 +185,13 @@ type RecipientPublicKey = C.PublicKey
|
||||
-- | Sender's private key used by the recipient to authorize (sign) SMP commands.
|
||||
--
|
||||
-- Only used by SMP agent, kept here so its definition is close to respective public key.
|
||||
type SenderPrivateKey = C.SafePrivateKey
|
||||
type SenderPrivateKey = C.PrivateKey
|
||||
|
||||
-- | Sender's public key used by SMP server to verify authorization of SMP commands.
|
||||
type SenderPublicKey = C.PublicKey
|
||||
|
||||
-- | Private key used by push notifications server to authorize (sign) LSTN command.
|
||||
type NotifierPrivateKey = C.SafePrivateKey
|
||||
type NotifierPrivateKey = C.PrivateKey
|
||||
|
||||
-- | Public key used by SMP server to verify authorization of LSTN command sent by push notifications server.
|
||||
type NotifierPublicKey = C.PublicKey
|
||||
|
||||
@@ -30,7 +30,7 @@ data ServerConfig = ServerConfig
|
||||
msgIdBytes :: Int,
|
||||
storeLog :: Maybe (StoreLog 'ReadMode),
|
||||
blockSize :: Int,
|
||||
serverPrivateKey :: C.FullPrivateKey
|
||||
serverPrivateKey :: C.PrivateKey
|
||||
-- serverId :: ByteString
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ data Env = Env
|
||||
queueStore :: QueueStore,
|
||||
msgStore :: STMMsgStore,
|
||||
idsDrg :: TVar ChaChaDRG,
|
||||
serverKeyPair :: C.FullKeyPair,
|
||||
serverKeyPair :: C.KeyPair,
|
||||
storeLog :: Maybe (StoreLog 'WriteMode)
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ import Data.ByteArray (xor)
|
||||
import Data.ByteString.Char8 (ByteString)
|
||||
import qualified Data.ByteString.Char8 as B
|
||||
import Data.Functor (($>))
|
||||
import Data.Maybe(fromMaybe)
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as S
|
||||
import Data.String
|
||||
@@ -345,7 +345,7 @@ makeNextIV SessionKey {baseIV, counter} = atomically $ do
|
||||
-- See https://github.com/simplex-chat/simplexmq/blob/master/protocol/simplex-messaging.md#appendix-a
|
||||
--
|
||||
-- The numbers in function names refer to the steps in the document.
|
||||
serverHandshake :: forall c. Transport c => c -> Int -> C.FullKeyPair -> ExceptT TransportError IO (THandle c)
|
||||
serverHandshake :: forall c. Transport c => c -> Int -> C.KeyPair -> ExceptT TransportError IO (THandle c)
|
||||
serverHandshake c srvBlockSize (k, pk) = do
|
||||
checkValidBlockSize srvBlockSize
|
||||
liftIO sendHeaderAndPublicKey_1
|
||||
|
||||
@@ -149,14 +149,32 @@ testForeignKeysEnabled =
|
||||
cData1 :: ConnData
|
||||
cData1 = ConnData {connId = "conn1"}
|
||||
|
||||
testPrivateKey :: C.PrivateKey
|
||||
testPrivateKey =
|
||||
C.PrivateKey
|
||||
R.PrivateKey
|
||||
{ private_pub =
|
||||
R.PublicKey
|
||||
{ public_size = 1,
|
||||
public_n = 2,
|
||||
public_e = 0
|
||||
},
|
||||
private_d = 3,
|
||||
private_p = 0,
|
||||
private_q = 0,
|
||||
private_dP = 0,
|
||||
private_dQ = 0,
|
||||
private_qinv = 0
|
||||
}
|
||||
|
||||
rcvQueue1 :: RcvQueue
|
||||
rcvQueue1 =
|
||||
RcvQueue
|
||||
{ server = SMPServer "smp.simplex.im" (Just "5223") testKeyHash,
|
||||
rcvId = "1234",
|
||||
rcvPrivateKey = C.safePrivateKey (1, 2, 3),
|
||||
rcvPrivateKey = testPrivateKey,
|
||||
sndId = Just "2345",
|
||||
decryptKey = C.safePrivateKey (1, 2, 3),
|
||||
decryptKey = testPrivateKey,
|
||||
verifyKey = Nothing,
|
||||
status = New
|
||||
}
|
||||
@@ -166,9 +184,9 @@ sndQueue1 =
|
||||
SndQueue
|
||||
{ server = SMPServer "smp.simplex.im" (Just "5223") testKeyHash,
|
||||
sndId = "3456",
|
||||
sndPrivateKey = C.safePrivateKey (1, 2, 3),
|
||||
sndPrivateKey = testPrivateKey,
|
||||
encryptKey = C.PublicKey $ R.PublicKey 1 2 3,
|
||||
signKey = C.APrivateKey $ C.unPrivateKey (C.safePrivateKey (1, 2, 3) :: C.SafePrivateKey),
|
||||
signKey = testPrivateKey,
|
||||
status = New
|
||||
}
|
||||
|
||||
@@ -306,9 +324,9 @@ testUpgradeRcvConnToDuplex =
|
||||
SndQueue
|
||||
{ server = SMPServer "smp.simplex.im" (Just "5223") testKeyHash,
|
||||
sndId = "2345",
|
||||
sndPrivateKey = C.safePrivateKey (1, 2, 3),
|
||||
sndPrivateKey = testPrivateKey,
|
||||
encryptKey = C.PublicKey $ R.PublicKey 1 2 3,
|
||||
signKey = C.APrivateKey $ C.unPrivateKey (C.safePrivateKey (1, 2, 3) :: C.SafePrivateKey),
|
||||
signKey = testPrivateKey,
|
||||
status = New
|
||||
}
|
||||
upgradeRcvConnToDuplex store "conn1" anotherSndQueue
|
||||
@@ -326,9 +344,9 @@ testUpgradeSndConnToDuplex =
|
||||
RcvQueue
|
||||
{ server = SMPServer "smp.simplex.im" (Just "5223") testKeyHash,
|
||||
rcvId = "3456",
|
||||
rcvPrivateKey = C.safePrivateKey (1, 2, 3),
|
||||
rcvPrivateKey = testPrivateKey,
|
||||
sndId = Just "4567",
|
||||
decryptKey = C.safePrivateKey (1, 2, 3),
|
||||
decryptKey = testPrivateKey,
|
||||
verifyKey = Nothing,
|
||||
status = New
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ pattern Resp corrId queueId command <- ("", (corrId, queueId, Right (Cmd SBroker
|
||||
sendRecv :: Transport c => THandle c -> (ByteString, ByteString, ByteString, ByteString) -> IO SignedTransmissionOrError
|
||||
sendRecv h (sgn, corrId, qId, cmd) = tPutRaw h (sgn, corrId, encode qId, cmd) >> tGet fromServer h
|
||||
|
||||
signSendRecv :: Transport c => THandle c -> C.SafePrivateKey -> (ByteString, ByteString, ByteString) -> IO SignedTransmissionOrError
|
||||
signSendRecv :: Transport c => THandle c -> C.PrivateKey -> (ByteString, ByteString, ByteString) -> IO SignedTransmissionOrError
|
||||
signSendRecv h pk (corrId, qId, cmd) = do
|
||||
let t = B.intercalate " " [corrId, encode qId, cmd]
|
||||
Right sig <- runExceptT $ C.sign pk t
|
||||
@@ -332,7 +332,7 @@ testWithStoreLog at@(ATransport t) =
|
||||
Right l -> pure l
|
||||
Left (_ :: SomeException) -> logSize
|
||||
|
||||
createAndSecureQueue :: Transport c => THandle c -> SenderPublicKey -> IO (SenderId, RecipientId, C.SafePrivateKey)
|
||||
createAndSecureQueue :: Transport c => THandle c -> SenderPublicKey -> IO (SenderId, RecipientId, C.PrivateKey)
|
||||
createAndSecureQueue h sPub = do
|
||||
(rPub, rKey) <- C.generateKeyPair rsaKeySize
|
||||
Resp "abcd" "" (IDS rId sId) <- signSendRecv h rKey ("abcd", "", "NEW " <> C.serializePubKey rPub)
|
||||
|
||||
Reference in New Issue
Block a user