2012-04-19 10 views
7

私はCodec.Crypto.RSAを使用して、ソケットを介して外部プロセスに渡されるランダムな文字列をbase64形式で暗号化しています。外部プロセス(解読にopensslを使用するルビープログラム)は、時にはメッセージの解読に失敗します。Codec.Crypto.RSA:PKCS#1 v1.5パディングが使用されている場合、(decrypt。encrypt)/ = id?

これをデバッグするには、固定メッセージを暗号化および復号化する単純なスクリプトを、base64エンコーディング/デコードを使用せずにすべてセットアップします。何が私を困惑させるのは、この非常に単純なプログラムは、数回の反復後に失敗に終わるということです。復号化された暗号文は元のメッセージと同じではありませんが、復号化にメッセージが含まれています(印刷できない文字の後に)。ここで

コードです:Codec.Crypto.RSAのためのテストスイートを通過すると

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 

、確かに私のプログラムに問題がなければなりません。

RSA.encryptRSA.encrypt' RSA.UsePKCS1_v1_5交換後RSA.decryptとし、RSA.decrypt' RSA.UsePKCS1_v1_5(OAEP をデフォルト)、障害がもはやトリガされません。

ここに間違いがありますか?


[1]私は後でOAEPを使用する予定が、生成された暗号文は、何らかの理由でecho ciphertext | openssl rsautl -oaep -inkey keypair.pem -decryptで復号化することはできませんが、それは別の問題です。

更新: のOpenSSL 1でOAEP仕事をするためには、ハッシュ関数として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

あなたのコードと間違って何もない、それが使用されるライブラリのバグです。

問題はない0バイトで指定された長さのランダムByteStringを生成するようになっている

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' 

がないことです。

これをテストするためにCodec.Crypto.RSAのソースをハッキングすると、まもなく一貫して0バイトのエラーが発生します。

つまり、デコードされたメッセージは実際よりも長くなっていると考えられ、その前には何らかのゴミがあります。生成された無制限のバイトが255である場合lowが1である、ここで

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

mask0xFF(255)である:

具体的なバグが時々crandomR_Numのバグによるもの0バイトを生成crandomRということです0したがってない> highで、次いで

res = fromIntegral 256 

バグがhackageにすでにすぐによるあるmonadcryptorandomの次のリリース(0.4.1)で修正されていなければなりません。

OAEPメソッドは、必要な長さにチャンクを埋めるために異なるパディングスキームを使用するため、私が見る限り、影響を受けません。

+0

これは非常に役に立ちました。ありがとうございました! – rekado

+0

monadcryptorandomのバグトラッカーにこのバグが登録されていません。あなたは、次回のリリースがパッケージの作者から間もなく予定されていることをご存じですか? – rekado

+2

いいえ、私はバグについて著者/管理者に郵送しました。それはかなり重要なことなので、私はThomasが速やかにそれを修正し、遅滞なく修正を押し出すことを推測しています。バグ追跡システムにも追加する予定です。 –

関連する問題