rek*_*ado 7 encryption haskell rsa padding
我正在使用Codec.Crypto.RSA来加密随机字符串,该字符串通过base64表示中的套接字传递给外部进程.外部进程(使用openssl进行解密的ruby程序)有时无法解密消息.
为了调试这个,我在haskell中设置了一个简单的脚本,用于加密和解密固定的消息,所有这些都没有base64编码/解码.令我困惑的是,这个非常简单的程序在几次迭代后导致失败.解密的密文不等于原始消息,尽管消息包含在解密中(在一些不可打印的字符之后).
这是代码:
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
Run Code Online (Sandbox Code Playgroud)
由于Codec.Crypto.RSA的测试套件通过,我的程序肯定存在问题.
置换后RSA.encrypt' RSA.UsePKCS1_v1_5用RSA.encrypt(默认为OAEP 1)和RSA.decrypt' RSA.UsePKCS1_v1_5与RSA.decrypt,则故障不再触发.
有谁看到这里有什么问题?
[1]我计划稍后使用OAEP,但生成的密文echo ciphertext | openssl rsautl -oaep -inkey keypair.pem -decrypt由于某种原因无法解密,但这是另一个问题.
更新: 要使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
Run Code Online (Sandbox Code Playgroud)
Dan*_*her 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'
Run Code Online (Sandbox Code Playgroud)
应该生成一个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')
Run Code Online (Sandbox Code Playgroud)
这里,mask是0xFF(255),low是1.如果生成的无限制字节是255,那么
res = fromIntegral 256
Run Code Online (Sandbox Code Playgroud)
这是0,因此不是> high.
错误 应该已被固定在的下一个版本(0.4.1)monadcryptorandom这是即将到期 已经在hackage.
据我所知,OAEP方法不受影响,因为它们使用不同的填充方案将块填充到所需的长度.