7

Codec.Crypto.RSA を使用して、base64 表現のソケットを介して外部プロセスに渡されるランダムな文字列を暗号化しています。外部プロセス (復号化に openssl を使用する ruby​​ プログラム) は、メッセージの復号化に失敗することがあります。

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

コードは次のとおりです。

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 のテスト スイートに合格したので、プログラムに問題があることは間違いありません。

(デフォルトで OAEP 1 ) およびに置き換えた後RSA.encrypt' RSA.UsePKCS1_v1_5、障害はトリガーされなくなりました。RSA.encryptRSA.decrypt' RSA.UsePKCS1_v1_5RSA.decrypt

誰かがここで何が悪いのか分かりますか?


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

更新: 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
4

1 に答える 1

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( 0xFF255)lowは 1 です。生成された無制限バイトが 255 の場合、

res = fromIntegral 256

これは 0 であり、したがって ではありません> high

不具合する必要がありますmonadcryptorandomの次のリリース (0.4.1) で修正されました。お早めにすでにハッキング中。

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

于 2012-04-19T10:27:33.037 に答える