mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-10-22 15:22:18 +00:00
save keys as binary to db, remove legacy encoding (#114)
* save keys as binary to db, remove legacy encoding * import list
This commit is contained in:
1 parent
729cf10ad8
commit
6ceeb2c9db
9 files changed
+59
-73
No files matched your search
@@ -33,7 +33,7 @@ module Simplex.Messaging.Crypto
|
||||
decryptAES,
|
||||
serializePrivKey,
|
||||
serializePubKey,
|
||||
binaryEncodePubKey,
|
||||
encodePubKey,
|
||||
serializeKeyHash,
|
||||
getKeyHash,
|
||||
privKeyP,
|
||||
@@ -50,7 +50,6 @@ module Simplex.Messaging.Crypto
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Applicative ((<|>))
|
||||
import Control.Exception (Exception)
|
||||
import Control.Monad.Except
|
||||
import Control.Monad.Trans.Except
|
||||
@@ -60,7 +59,6 @@ import qualified Crypto.Error as CE
|
||||
import Crypto.Hash (Digest, SHA256 (..), digestFromByteString, hash)
|
||||
import Crypto.Number.Generate (generateMax)
|
||||
import Crypto.Number.Prime (findPrimeFrom)
|
||||
import Crypto.Number.Serialize (os2ip)
|
||||
import qualified Crypto.PubKey.RSA as R
|
||||
import qualified Crypto.PubKey.RSA.OAEP as OAEP
|
||||
import qualified Crypto.PubKey.RSA.PSS as PSS
|
||||
@@ -72,7 +70,7 @@ import Data.Attoparsec.ByteString.Char8 (Parser)
|
||||
import qualified Data.Attoparsec.ByteString.Char8 as A
|
||||
import Data.Bifunctor (bimap, first)
|
||||
import qualified Data.ByteArray as BA
|
||||
import Data.ByteString.Base64
|
||||
import Data.ByteString.Base64 (decode, encode)
|
||||
import Data.ByteString.Char8 (ByteString)
|
||||
import qualified Data.ByteString.Char8 as B
|
||||
import Data.ByteString.Internal (c2w, w2c)
|
||||
@@ -86,8 +84,8 @@ import Database.SQLite.Simple.Internal (Field (..))
|
||||
import Database.SQLite.Simple.Ok (Ok (Ok))
|
||||
import Database.SQLite.Simple.ToField (ToField (..))
|
||||
import Network.Transport.Internal (decodeWord32, encodeWord32)
|
||||
import Simplex.Messaging.Parsers (base64P, base64StringP, parseAll)
|
||||
import Simplex.Messaging.Util (liftEitherError)
|
||||
import Simplex.Messaging.Parsers (base64P, parseAll)
|
||||
import Simplex.Messaging.Util (liftEitherError, (<$?>))
|
||||
|
||||
newtype PublicKey = PublicKey {rsaPublicKey :: R.PublicKey} deriving (Eq, Show)
|
||||
|
||||
@@ -112,21 +110,21 @@ instance PrivateKey FullPrivateKey where
|
||||
mkPrivateKey = FullPrivateKey
|
||||
|
||||
instance IsString FullPrivateKey where
|
||||
fromString = parseString decodePrivKey
|
||||
fromString = parseString (decode >=> decodePrivKey)
|
||||
|
||||
instance IsString PublicKey where
|
||||
fromString = parseString decodePubKey
|
||||
fromString = parseString (decode >=> decodePubKey)
|
||||
|
||||
parseString :: (ByteString -> Either String a) -> (String -> a)
|
||||
parseString parse = either error id . parse . B.pack
|
||||
|
||||
instance ToField SafePrivateKey where toField = toField . serializePrivKey
|
||||
instance ToField SafePrivateKey where toField = toField . encodePrivKey
|
||||
|
||||
instance ToField PublicKey where toField = toField . serializePubKey
|
||||
instance ToField PublicKey where toField = toField . encodePubKey
|
||||
|
||||
instance FromField SafePrivateKey where fromField = keyFromField privKeyP
|
||||
instance FromField SafePrivateKey where fromField = keyFromField binaryPrivKeyP
|
||||
|
||||
instance FromField PublicKey where fromField = keyFromField pubKeyP
|
||||
instance FromField PublicKey where fromField = keyFromField binaryPubKeyP
|
||||
|
||||
keyFromField :: Typeable k => Parser k -> FieldParser k
|
||||
keyFromField p = \case
|
||||
@@ -336,35 +334,22 @@ verify :: PublicKey -> Signature -> ByteString -> Bool
|
||||
verify (PublicKey k) (Signature sig) msg = PSS.verify pssParams k msg sig
|
||||
|
||||
serializePubKey :: PublicKey -> ByteString
|
||||
serializePubKey k = "rsa:" <> encodePubKey k
|
||||
serializePubKey = ("rsa:" <>) . encode . encodePubKey
|
||||
|
||||
serializePrivKey :: PrivateKey k => k -> ByteString
|
||||
serializePrivKey pk = "rsa:" <> encodePrivKey pk
|
||||
serializePrivKey = ("rsa:" <>) . encode . encodePrivKey
|
||||
|
||||
pubKeyP :: Parser PublicKey
|
||||
pubKeyP = keyP decodePubKey <|> legacyPubKeyP
|
||||
pubKeyP = decodePubKey <$?> ("rsa:" *> base64P)
|
||||
|
||||
binaryPubKeyP :: Parser PublicKey
|
||||
binaryPubKeyP = either fail pure . binaryDecodePubKey =<< A.takeByteString
|
||||
binaryPubKeyP = decodePubKey <$?> A.takeByteString
|
||||
|
||||
privKeyP :: PrivateKey k => Parser k
|
||||
privKeyP = keyP decodePrivKey <|> legacyPrivKeyP
|
||||
privKeyP = decodePrivKey <$?> ("rsa:" *> base64P)
|
||||
|
||||
keyP :: (ByteString -> Either String k) -> Parser k
|
||||
keyP dec = either fail pure . dec =<< ("rsa:" *> base64StringP)
|
||||
|
||||
legacyPubKeyP :: Parser PublicKey
|
||||
legacyPubKeyP = do
|
||||
(public_size, public_n, public_e) <- legacyKeyParser_
|
||||
return . PublicKey $ R.PublicKey {public_size, public_n, public_e}
|
||||
|
||||
legacyPrivKeyP :: PrivateKey k => Parser k
|
||||
legacyPrivKeyP = _privateKey . safeRsaPrivateKey <$> legacyKeyParser_
|
||||
|
||||
legacyKeyParser_ :: Parser (Int, Integer, Integer)
|
||||
legacyKeyParser_ = (,,) <$> (A.decimal <* ",") <*> (intP <* ",") <*> intP
|
||||
where
|
||||
intP = os2ip <$> base64P
|
||||
binaryPrivKeyP :: PrivateKey k => Parser k
|
||||
binaryPrivKeyP = decodePrivKey <$?> A.takeByteString
|
||||
|
||||
safePrivateKey :: (Int, Integer, Integer) -> SafePrivateKey
|
||||
safePrivateKey = SafePrivateKey . safeRsaPrivateKey
|
||||
@@ -387,34 +372,28 @@ safeRsaPrivateKey (size, n, d) =
|
||||
}
|
||||
|
||||
encodePubKey :: PublicKey -> ByteString
|
||||
encodePubKey = encode . binaryEncodePubKey
|
||||
|
||||
binaryEncodePubKey :: PublicKey -> ByteString
|
||||
binaryEncodePubKey = binaryEncodeKey . PubKeyRSA . rsaPublicKey
|
||||
encodePubKey = encodeKey . PubKeyRSA . rsaPublicKey
|
||||
|
||||
encodePrivKey :: PrivateKey k => k -> ByteString
|
||||
encodePrivKey = encode . binaryEncodeKey . PrivKeyRSA . rsaPrivateKey
|
||||
encodePrivKey = encodeKey . PrivKeyRSA . rsaPrivateKey
|
||||
|
||||
binaryEncodeKey :: ASN1Object a => a -> ByteString
|
||||
binaryEncodeKey k = toStrict . encodeASN1 DER $ toASN1 k []
|
||||
encodeKey :: ASN1Object a => a -> ByteString
|
||||
encodeKey k = toStrict . encodeASN1 DER $ toASN1 k []
|
||||
|
||||
decodePubKey :: ByteString -> Either String PublicKey
|
||||
decodePubKey = binaryDecodePubKey <=< decode
|
||||
|
||||
binaryDecodePubKey :: ByteString -> Either String PublicKey
|
||||
binaryDecodePubKey =
|
||||
binaryDecodeKey >=> \case
|
||||
decodePubKey =
|
||||
decodeKey >=> \case
|
||||
(PubKeyRSA k, []) -> Right $ PublicKey k
|
||||
r -> keyError r
|
||||
|
||||
decodePrivKey :: PrivateKey k => ByteString -> Either String k
|
||||
decodePrivKey =
|
||||
decode >=> binaryDecodeKey >=> \case
|
||||
decodeKey >=> \case
|
||||
(PrivKeyRSA pk, []) -> Right $ mkPrivateKey pk
|
||||
r -> keyError r
|
||||
|
||||
binaryDecodeKey :: ASN1Object a => ByteString -> Either String (a, [ASN1])
|
||||
binaryDecodeKey = fromASN1 <=< first show . decodeASN1 DER . fromStrict
|
||||
decodeKey :: ASN1Object a => ByteString -> Either String (a, [ASN1])
|
||||
decodeKey = fromASN1 <=< first show . decodeASN1 DER . fromStrict
|
||||
|
||||
keyError :: (a, [ASN1]) -> Either String b
|
||||
keyError = \case
|
||||
|
||||
@@ -11,10 +11,11 @@ import qualified Data.ByteString.Char8 as B
|
||||
import Data.Char (isAlphaNum)
|
||||
import Data.Time.Clock (UTCTime)
|
||||
import Data.Time.ISO8601 (parseISO8601)
|
||||
import Simplex.Messaging.Util ((<$?>))
|
||||
import Text.Read (readMaybe)
|
||||
|
||||
base64P :: Parser ByteString
|
||||
base64P = either fail pure . decode =<< base64StringP
|
||||
base64P = decode <$?> base64StringP
|
||||
|
||||
base64StringP :: Parser ByteString
|
||||
base64StringP = do
|
||||
|
||||
@@ -244,7 +244,7 @@ serverHandshake h (k, pk) = do
|
||||
where
|
||||
sendHeaderAndPublicKey_1 :: IO ()
|
||||
sendHeaderAndPublicKey_1 = do
|
||||
let sKey = C.binaryEncodePubKey k
|
||||
let sKey = C.encodePubKey k
|
||||
header = TransportHeader {blockSize = transportBlockSize, keySize = B.length sKey}
|
||||
B.hPut h $ binaryTransportHeader header <> sKey
|
||||
receiveEncryptedKeys_4 :: ExceptT TransportError IO ByteString
|
||||
|
||||
@@ -31,11 +31,14 @@ raceAny_ = r []
|
||||
r as (m : ms) = withAsync m $ \a -> r (a : as) ms
|
||||
r as [] = void $ waitAnyCancel as
|
||||
|
||||
infixl 4 <$$>
|
||||
infixl 4 <$$>, <$?>
|
||||
|
||||
(<$$>) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
|
||||
(<$$>) = fmap . fmap
|
||||
|
||||
(<$?>) :: MonadFail m => (a -> Either String b) -> m a -> m b
|
||||
f <$?> m = m >>= either fail pure . f
|
||||
|
||||
bshow :: Show a => a -> ByteString
|
||||
bshow = B.pack . show
|
||||
|
||||
|
||||
Reference in new issue
Block a user