Codec.Crypto.RSA: (decrypt. Encrypt) / = id when using the PKCS # 1 v1.5 add-on?

I use Codec.Crypto.RSA to encrypt a random string that is passed to external processes through a socket in a base64 view. An external process (a ruby ​​program using openssl to decrypt) sometimes cannot decrypt a message.

To debug this, I installed a simple script in haskell that encrypts and decrypts a fixed message, without base64 encoding / decoding. What puzzles me is that this simple program crashes after several iterations. The decrypted encrypted text is not equal to the original message, although the message is decrypted (after some non-printable characters).

Here is the code:

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 

As the test suite for Codec.Crypto.RSA passes, there must be a problem with my program.

After replacing RSA.encrypt' RSA.UsePKCS1_v1_5 with RSA.encrypt (default for OAEP 1 ) and RSA.decrypt' RSA.UsePKCS1_v1_5 with RSA.decrypt crash no longer works.

Does anyone see what's wrong here?


[1] I plan to use OAEP later, but the generated ciphertext cannot be decrypted using echo ciphertext | openssl rsautl -oaep -inkey keypair.pem -decrypt echo ciphertext | openssl rsautl -oaep -inkey keypair.pem -decrypt for some reason, but this is another problem.

Update: To make OAEP work with OpenSSL, you need to use SHA-1 as a hash function:

 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 
+7
source share
1 answer

There is nothing wrong with the code; this is a mistake in the library used.

The problem is

 generate_random_bytestring :: CryptoRandomGen g => g -> Int64 -> (ByteString, g) generate_random_bytestring g 0 = (BS.empty, g) generate_random_bytestring gx = (BS.cons' first rest, g'') where (rest, g') = generate_random_bytestring g (x - 1) (first, g'') = throwLeft $ crandomR (1,255) g' 

which should generate a random ByteString given length without a 0-byte does not.

Hacking the source code of Codec.Crypto.RSA to check it, I get a 0-byte error very quickly.

This means that the decoded message is considered longer than it actually is, and garbage appears in front of it.

The specific error is that crandomR sometimes produces a 0-byte result due to an error in crandomR_Num :

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

Here mask is 0xFF (255), low is 1. If the generated unlimited byte is 255, then

 res = fromIntegral 256 

which is 0 and therefore not > high .

In the next version (0.4.1) of monadcryptorandom, the error should be fixed must be . will be soon already on the hack.

OAEP methods do not affect, as far as I see, because they use a different padding scheme to fill pieces of the required length.

+11
source

All Articles