2012-04-19 3 views
7

Я использую Codec.Crypto.RSA для шифрования случайной строки, которая передается внешним процессам через сокет в представлении base64. Внешний процесс (рубиновая программа с использованием openssl для дешифрования) иногда не может расшифровать сообщение.Codec.Crypto.RSA: (decrypt. Encrypt)/= id, когда используется дополнение PKCS # 1 v1.5?

Чтобы отладить это, я установил простой скрипт в 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 (недобросовестный OAEP ) и RSA.decrypt' RSA.UsePKCS1_v1_5 с RSA.decrypt, отказ больше не срабатывает.

Кто-нибудь видит, что здесь не так?


[1] Я планирую использовать OAEP позже, но генерируемый шифротекста не могут быть расшифрованы с echo ciphertext | openssl rsautl -oaep -inkey keypair.pem -decrypt по какой-то причине, но это другая проблема.

Update: Чтобы сделать 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 

ответ

11

Там нет ничего плохого в вашем коде, это ошибка в используемой библиотеке.

Проблема заключается в том, что

generate_random_bytestring :: CryptoRandomGen g => g -> Int64 -> (ByteString, g) 
generate_random_bytestring g 0 = (BS.empty, g) 
generate_random_bytestring g x = (BS.cons' first rest, g'') 
where 
    (rest, g') = generate_random_bytestring g (x - 1) 
    (first, g'') = throwLeft $ crandomR (1,255) g' 

который должен генерировать случайный ByteString заданной длины без каких-либо 0 байт, не делает.

Взломанный источник Codec.Crypto.RSA, чтобы проверить его, я получаю ошибку 0-байтов очень скоро.

Это означает, что декодированное сообщение считается длиннее, чем оно есть на самом деле, и перед вами появляется мусор.

Конкретная ошибка в том, что иногда производит crandomR 0 байт из-за ошибки в crandomR_Num:

 Right (bs, g') -> 
       let res = fromIntegral $ fromIntegral low + (bs2i bs .&. mask) 
       in if res > high then go g' else Right (res, g') 

Здесь mask является 0xFF (255), low равен 1. Если генерируются неограниченные байты 255 , а затем

res = fromIntegral 256 

, который равен 0, и, следовательно, не > high.

Исправлена ​​ошибка должна быть была исправлена ​​в следующей версии (0.4.1) из monadcryptorandom, который благодаря вскоре уже на hackage.

Методы OAEP не влияют, насколько я вижу, потому что они используют другую схему заполнения, чтобы заполнить куски необходимой длины.

+0

Это было очень полезно. Спасибо! – rekado

+0

Я не нашел эту ошибку, указанную в трекере ошибок для monadcryptorandom, и я не видел там никакой информации о предстоящем выпуске. Знаете ли вы, что следующий выпуск скоро появится у автора пакета? – rekado

+2

Нет, я отправил автора сообщения об ошибке. Поскольку это довольно существенная вещь, я экстраполирую то, что Томас исправляет ее как можно скорее и отталкивает исправление без задержки. Думаю, я собираюсь добавить его к ошибке-трекеру. –