2012-04-19 17 views
7

Estoy usando Codec.Crypto.RSA para cifrar una cadena aleatoria que se pasa a procesos externos sobre un socket en la representación de base64. El proceso externo (un programa ruby ​​que usa openssl para descifrado) algunas veces no descifra el mensaje.Codec.Crypto.RSA: (descifrar. Encrypt)/= id cuando se usa PKCS # 1 v1.5 padding?

Para depurar esto configuré una secuencia de comandos simple en haskell que encripta y descifra un mensaje fijo, todo sin codificar/decodificar base64. Lo que me desconcierta es que este programa muy simple resulta en una falla después de algunas iteraciones. El texto cifrado descifrado no es igual al mensaje original, aunque el mensaje está contenido en el descifrado (después de algunos caracteres no imprimibles).

Aquí está el código:

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 

A medida que el banco de pruebas para Codec.Crypto.RSA pasa, ciertamente debe haber un problema con mi programa.

Después de reemplazar RSA.encrypt' RSA.UsePKCS1_v1_5 con RSA.encrypt (por defecto a OAEP ) y RSA.decrypt' RSA.UsePKCS1_v1_5 con RSA.decrypt, el fracaso ya no se dispara.

¿Alguien ve lo que está mal aquí?


[1] Voy a utilizar OAEP más tarde, pero el texto cifrado generado no se puede descifrar con echo ciphertext | openssl rsautl -oaep -inkey keypair.pem -decrypt por alguna razón, pero eso es otro problema.

Actualización: Para poner en funcionamiento OAEP con OpenSSL uno tiene que utilizar SHA-1 como la función hash:

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 

Respuesta

11

No hay nada malo con su código, un error en una biblioteca utilizada.

El problema es que

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' 

que se supone que generar un azar ByteString de longitud dada sin 0 bytes, no lo hace.

Hackear la fuente de Codec.Crypto.RSA para probarla, siempre obtengo un error de 0 bytes muy pronto.

Eso significa que el mensaje decodificado se cree que es más largo de lo que realmente es y se obtiene algo de basura delante de él.

El error concreto es que a veces produce una crandomR 0 bytes debido a un error en crandomR_Num:

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

Aquí, es mask0xFF (255), low es 1. Si el byte sin restricciones generado es 255 , a continuación,

res = fromIntegral 256 

que es 0 y por lo tanto no > high.

El error debe ser se ha fijado en la próxima versión (0.4.1) de monadcryptorandom que es derecho pronto que ya están en hackage.

Los métodos OAEP no se ven afectados, por lo que puedo ver, porque utilizan un esquema de relleno diferente para llenar los trozos a la longitud requerida.

+0

Eso fue muy útil. ¡Gracias! – rekado

+0

No he encontrado este error en el rastreador de errores para monadcryptorandom, ni he visto información allí en una próxima versión. ¿Sabía que próximamente el próximo lanzamiento del autor del paquete? – rekado

+2

No, he enviado por correo el autor/mantenedor sobre el error. Como es algo bastante sustancial, estoy extrapolando que Thomas lo soluciona lo antes posible y saca la solución sin demora. Voy a agregarlo al rastreador de errores también, creo. –

Cuestiones relacionadas