3

これが私がHaskellでやろうとしていることです:

  • ByteString形式でメッセージを受け取ります(怠惰であるか厳密であるかは実際には関係ありません)
  • RSA公開鍵でメッセージを暗号化する
  • base64は暗号化されたメッセージをエンコードします

私が使用しているRSAライブラリは、レイジーByteStringsを内部で処理しますただし、Base64ライブラリは厳密なByteStringのみを使用します。私のアプリケーションは、怠惰なByteStringsを使用してメッセージをネットワークソケットに送信します。

したがって、怠惰なByteStringと厳密なByteStringの間で変換する必要があるようです。これが私がすることです:

encrypt :: CryptoRandomGen t => t -> RSA.PublicKey -> L.ByteString -> L.ByteString
encrypt gen pubkey msg = do
  let (ciphertext,_) = RSA.encrypt gen pubkey msg
  (L.fromChunks . map encode . L.toChunks) $ ciphertext

decrypt :: RSA.PrivateKey -> L.ByteString -> Either String L.ByteString
decrypt privkey ciphertext = do
  dec <- decode $ S.concat $ L.toChunks ciphertext
  return $ RSA.decrypt privkey $ L.fromChunks [dec]

残念ながら、これが失敗することがあります。この方法で暗号化されたメッセージを復号化すると、実際のメッセージの後にガベージが続くことがあります。問題がどこにあるのか正確にはわかりません。レイジーから厳密なByteStringsへの変換なのか、それともbase64エンコーディングステップなのか。それとも両方ですか?

Lazy ByteStringsは、厳密なByteStringチャンクの単なるリストです。メッセージを変換して暗黙的にメッセージの長さを変更しますか?

教えてください。

4

1 に答える 1

4

問題は、base64エンコーディングが入力の3バイト(3×8ビット)ごとに出力の4バイト(4×6ビット)にマップするため、入力のサイズが3の倍数でない場合、パディングを追加する必要があることです。つまり、各チャンクを個別にエンコードした結果を連結しても、全体をエンコードした場合と同じ結果が得られない場合があります。

> encode "Haskell"
"SGFza2VsbA=="
> encode "Hask" `append` encode "ell"
"SGFzaw==ZWxs"

=出力の埋め込みに使用された文字を削除しても、これらは異なることに注意してください。入力のパディングは依然として問題を引き起こします。

おそらく最善の策は、遅延バイト文字列をサポートするライブラリを見つけることですが、すべてのチャンク(最後を除く)のサイズが3の倍数であることを確認すると、回避策として機能します。

または、すべてをメモリに保持してもかまわない場合は、遅延バイト文字列を厳密なバイト文字列に変換し、すべてを1つのステップでエンコードして、(必要に応じて)元に戻します。

于 2012-04-14T15:29:13.123 に答える