2012-04-19 41 views
7

Tôi đang sử dụng Codec.Crypto.RSA để mã hóa một chuỗi ngẫu nhiên được chuyển đến một quy trình bên ngoài qua ổ cắm trong biểu diễn base64. Quá trình bên ngoài (một chương trình ruby ​​sử dụng openssl để giải mã) đôi khi không giải mã được tin nhắn.Codec.Crypto.RSA: (giải mã mã hóa)/= id khi PKCS # 1 v1.5 padding được sử dụng?

Để gỡ lỗi này, tôi thiết lập một tập lệnh đơn giản trong haskell mã hóa và giải mã một thông báo cố định, tất cả đều không có mã hóa/giải mã base64. Điều khiến tôi bối rối là chương trình rất đơn giản này dẫn đến thất bại sau một vài lần lặp lại. Mật mã được giải mã không bằng thông điệp gốc, mặc dù thông điệp được chứa trong giải mã (sau một số ký tự không thể in được).

Dưới đây là các mã:

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 

Như các bộ kiểm tra cho Codec.Crypto.RSA đi, chắc chắn phải là một vấn đề với chương trình của tôi.

Sau khi thay thế RSA.encrypt' RSA.UsePKCS1_v1_5 với RSA.encrypt (mặc định cho OAEP ) và RSA.decrypt' RSA.UsePKCS1_v1_5 với RSA.decrypt, sự thất bại không còn được kích hoạt.

Có ai thấy điều gì sai ở đây không?


[1] tôi có kế hoạch sử dụng OAEP sau đó, nhưng bản mã được tạo ra không thể được giải mã với echo ciphertext | openssl rsautl -oaep -inkey keypair.pem -decrypt đối với một số lý do, nhưng đó là một vấn đề khác.

Cập nhật: Để làm OAEP làm việc với OpenSSL người ta phải sử dụng SHA-1 là hàm băm:

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 

Trả lời

11

Không có gì sai với mã của bạn là, đó là một lỗi trong một thư viện sử dụng.

Vấn đề là

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' 

mà là vụ phải tạo ra một ngẫu nhiên ByteString chiều dài cho không có 0 byte, thì không.

Lấy nguồn của Codec.Crypto.RSA để kiểm tra, tôi liên tục nhận được lỗi 0 byte rất sớm.

Điều đó có nghĩa là thông báo được giải mã được cho là dài hơn thực tế và bạn nhận được một số rác trước mặt.

Lỗi bê tông là crandomR đôi khi kết quả là 0 byte do một lỗi trong crandomR_Num:

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

Ở đây, mask0xFF (255), low là 1. Nếu byte không hạn chế được tạo ra là 255 , sau đó

res = fromIntegral 256 

là 0 và do đó không > high.

Lỗi nên đã được cố định trong phiên bản tiếp theo (0.4.1) của monadcryptorandom đó là do sớm đã có trên hackage.

Các phương pháp OAEP không bị ảnh hưởng, theo như tôi thấy, bởi vì chúng sử dụng một sơ đồ đệm khác nhau để lấp đầy các đoạn theo chiều dài yêu cầu.

+0

Điều đó rất hữu ích. Cảm ơn bạn! – rekado

+0

Tôi không tìm thấy lỗi này được liệt kê trong trình theo dõi lỗi cho monadcryptorandom, cũng như tôi không thấy bất kỳ thông tin nào có trong bản phát hành sắp tới. Bạn có biết rằng bản phát hành tiếp theo sắp ra mắt từ tác giả của gói không? – rekado

+2

Không, tôi đã gửi thư cho tác giả/người bảo trì về lỗi này. Vì nó là một điều khá đáng kể, tôi ngoại suy rằng Thomas sửa chữa nó càng sớm càng tốt và đẩy ra sửa chữa mà không chậm trễ. Tôi cũng sẽ thêm nó vào trình theo dõi lỗi. –

Các vấn đề liên quan