2012-04-19 13 views
7

Sto utilizzando Codec.Crypto.RSA per crittografare una stringa casuale che viene passata a un processo esterno su un socket nella rappresentazione base64. Il processo esterno (un programma ruby ​​che utilizza openssl per la decrittografia) a volte non riesce a decodificare il messaggio.Codec.Crypto.RSA: (decrypt. Encrypt)/= id quando si utilizza il padding PKCS # 1 v1.5?

Per eseguire il debug di questo ho impostato un semplice script in haskell che crittografa e decrittografa un messaggio fisso, tutto senza codifica/decodifica base64. Ciò che mi confonde è che questo programma molto semplice risulta in un fallimento dopo alcune iterazioni. Il testo cifrato decrittografato non è uguale al messaggio originale, sebbene il messaggio sia contenuto nella decrittografia (dopo alcuni caratteri non stampabili).

Ecco il codice:

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 

Come la suite di test per Codec.Crypto.RSA passa, ci certamente deve essere un problema con il mio programma.

Dopo aver sostituito RSA.encrypt' RSA.UsePKCS1_v1_5 con RSA.encrypt (per default OAEP ) e RSA.decrypt' RSA.UsePKCS1_v1_5 con RSA.decrypt, l'errore non è più attivato.

Qualcuno vede cosa c'è che non va qui?


[1] ho intenzione di usare OAEP più tardi, ma il testo cifrato generato non possono essere decifrati con echo ciphertext | openssl rsautl -oaep -inkey keypair.pem -decrypt per qualche ragione, ma questo è un altro problema.

Aggiornamento: Per far funzionare OAEP con OpenSSL si deve usare SHA-1 come la funzione 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 

risposta

11

c'è niente di sbagliato con il codice, si tratta di un bug in una libreria usata.

Il problema è che

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' 

che dovrebbe generare un casuale ByteString di lunghezza determinata senza 0-byte, non lo fa.

Hacking della fonte di Codec.Crypto.RSA per verificarlo, ottengo sempre un errore di 0 byte molto presto.

Ciò significa che il messaggio decodificato è pensato per essere più lungo di quello che è in realtà e si ottiene un po 'di spazzatura di fronte ad esso.

Il baco cemento è che crandomR talvolta produce un 0-byte a causa di un errore nel crandomR_Num:

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

Qui, mask è 0xFF (255), low è 1. Se il byte libero generato è 255 , quindi

res = fromIntegral 256 

che è 0 e quindi non > high.

Il baco dovrebbe essere è stato risolto nel prossimo rilascio (0.4.1) del monadcryptorandom che è dovuto presto già hackage.

I metodi OAEP non sono interessati, per quanto posso vedere, perché utilizzano uno schema di riempimento diverso per riempire i blocchi alla lunghezza richiesta.

+0

Questo è stato molto utile. Grazie! – rekado

+0

Non ho trovato questo bug elencato nel bug tracker per monadcryptorandom, né ho visto alcuna informazione lì su una prossima versione. Sai che la prossima versione sarà presto disponibile dall'autore del pacchetto? – rekado

+2

No, ho inviato all'autore/manutentore del bug. Dato che è una cosa abbastanza sostanziale, sto estrapolando che Thomas lo aggiorna ASAP e spinge fuori la correzione senza indugio. Lo aggiungerò anche al bug-tracker, penso. –

Problemi correlati