2012-04-14 20 views
3

でbase64でバイト文字列を使用すると、ここで私はHaskellでやろうとしているものです:怠惰なバイト文字列

  • (怠惰や厳格な場合は本当に重要ではありません)形式のバイト列でメッセージを取る
  • 暗号化メッセージRSA公開鍵
  • base64では、私は、内部のハンドルに怠惰なバイト文字列を使用している暗号化されたメッセージ

RSA libraryをコードします。ただし、Base64ライブラリでは、厳密なByteStringのみが使用されます。私のアプリケーションでは、lazy ByteStringsを使用してネットワークソケットにメッセージを送信します。

だから、私はレイジーと厳密な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] 

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

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

私に教えてください。

+0

怠惰なbytestringはモナドな値ではないので、どうやって表記を使用していますか? – dave4420

答えて

4

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

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

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

おそらく、遅延バイトストリングをサポートするライブラリを見つけることですが、すべてのチャンク(最後のものを除く)のサイズが3の倍数になるようにすることで問題を回避できます。

また、メモリ全体を保持しても構わない場合は、レイジーのバイトテストを厳密なものに変換し、すべてをワンステップでエンコードし、必要に応じて変換し直してください。

+0

怠惰なバイトコードのサポートの欠如は、しかし、そのライブラリからのいくらか目立った省略のように見えます。誰かがそれをハックしたいと思えば、私はブライアンがパッチを受け入れることをうれしく思います。 – hammar

+0

OpenSSL.EVP.Base64に遅延バイトストリングの実装があります。私は、同じメッセージでHsOpenSSLの 'encodeBase64LBS'のものと変換されたバイトコードのbase64バイト文字列の' encode'の出力を比較しましたが、遅延文字列としての違いはありませんでした。 – rekado

+0

@rekado:Erm、はい?私が従うかわからない私はそれらの両方がうまく動作すると期待しています。それはL.fromChunksです。マップエンコード。 L.toChunks'それは壊れています。 – hammar

関連する問題