Я использую Codec.Crypto.RSA для шифрования случайной строки, которая передается внешним процессам через сокет в представлении base64. Внешний процесс (программа ruby, использующая openssl для расшифровки), иногда не может расшифровать сообщение.
Чтобы отладить это, я создал простой скрипт на haskell, который шифрует и расшифровывает фиксированное сообщение, и все это без кодирования/декодирования base64. Что меня сбивает с толку, так это то, что эта очень простая программа приводит к сбою после нескольких итераций. Расшифрованный зашифрованный текст не равен исходному сообщению, хотя сообщение содержится в расшифровке (после некоторых непечатаемых символов).
Вот код:
import Crypto.Random
import qualified Codec.Crypto.RSA as RSA
import qualified Data.ByteString.Lazy.Char8 as L
m :: L.ByteString
m = L.pack "11111222223333344444555556666600"
main = do
gen <- newGenIO :: IO SystemRandom
let (pub, priv, _) = RSA.generateKeyPair gen 1024
doStuff pub priv
doStuff pub priv = do
gen <- newGenIO :: IO SystemRandom
let (e,_) = RSA.encrypt' RSA.UsePKCS1_v1_5 gen pub m
let d = RSA.decrypt' RSA.UsePKCS1_v1_5 priv e
if (m == d)
then do
putStrLn "SUCCESS"
doStuff pub priv
else do
putStrLn "FAILED"
putStrLn $ "expected: " ++ show m
putStrLn $ "got: " ++ show d
Поскольку набор тестов для Codec.Crypto.RSA проходит успешно, в моей программе определенно должна быть проблема.
После замены RSA.encrypt' RSA.UsePKCS1_v1_5
наRSA.encrypt
(по умолчанию на OAEP1)и RSA.decrypt' RSA.UsePKCS1_v1_5
на RSA.decrypt
сбой больше не возникает.
Кто-нибудь видит, что здесь не так?
[1] Я планирую использовать OAEP позже, но сгенерированный зашифрованный текст не может быть расшифрован с помощью echo ciphertext | openssl rsautl -oaep -inkey keypair.pem -decrypt
по какой-то причине, но это другая проблема.
Обновление: Чтобы заставить OAEP работать с OpenSSL, необходимо использовать SHA-1 в качестве хэш-функции:
cryptOptions :: RSA.EncryptionOptions
cryptOptions = RSA.UseOAEP sha1' (RSA.generate_MGF1 sha1') BS.empty
where sha1' = bytestringDigest. sha1
-- then, to encrypt
enc = RSA.encrypt' cryptOptions gen pubkey