2012-06-15 22 views
11

Ho bisogno di scrivere un semplice strumento che codifica/decodifica i file.Come crittografare i file con Ruby?

Credo che il modo migliore è quello di utilizzare OpenSSL:

generare una chiave:

openssl rand -base64 2048 > secret_key 

crittografare un file:

openssl aes-256-cbc -a -e -in file -out file.enc -k secret_key 

decifrare un file:

openssl aes-256-cbc -d -in file.enc -out file -k secret_key 

C'è un modo semplice per implementare questo in Ruby? C'è un modo migliore per farlo? Forse usando PGP?

+1

Così che cosa esattamente la questione: utilizzando OpenSSL, senza la necessità di chiamare un programma esterno? –

+0

il comando per decrittografare dovrebbe essere: 'openssl aes-256-cbc -d -a -in file.enc -out file -k secret_key' altrimenti otterrai un' numero magico errato' – aelor

risposta

17

di Ruby OpenSSL è un wrapper sottile intorno OpenSSL stesso e fornisce quasi tutte le funzionalità che OpenSSL si fa, quindi sì, c'è una mappatura uno-a-uno per tutti i vostri esempi:

openssl rand -base64 2048 > secret_key 

che in realtà è esagerato , stai usando AES-256, quindi hai solo bisogno di una chiave a 256 bit, non stai usando RSA qui. Ruby OpenSSL prende questa decisione dalle tue spalle, determinerà automaticamente la dimensione della chiave corretta dato l'algoritmo che desideri utilizzare.

Si sta commettendo anche l'errore di utilizzare un IV deterministico durante la crittografia. Perché? Dato che non si specifica affatto un IV, OpenSSL stesso imposterà automaticamente un IV di tutti i byte zero. Non è una buona cosa, quindi ti mostrerò il modo corretto per farlo, per maggiori informazioni dai un'occhiata allo Cipher documentation.

require 'openssl' 

# encryption 
cipher = OpenSSL::Cipher.new('aes-256-cbc') 
cipher.encrypt 
key = cipher.random_key 
iv = cipher.random_iv 

buf = "" 
File.open("file.enc", "wb") do |outf| 
    File.open("file", "rb") do |inf| 
    while inf.read(4096, buf) 
     outf << cipher.update(buf) 
    end 
    outf << cipher.final 
    end 
end 

# decryption 
cipher = OpenSSL::Cipher.new('aes-256-cbc') 
cipher.decrypt 
cipher.key = key 
cipher.iv = iv # key and iv are the ones from above 

buf = "" 
File.open("file.dec", "wb") do |outf| 
    File.open("file.enc", "rb") do |inf| 
    while inf.read(4096, buf) 
     outf << cipher.update(buf) 
    end 
    outf << cipher.final 
    end 
end 

Come si può vedere, la crittografia e la decrittografia sono abbastanza simili, quindi probabilmente è possibile combinare la lettura in streaming/scrittura in un metodo condiviso e solo passare un correttamente configurati Cipher più i nomi di file corrispondenti, ho appena affermato loro esplicitamente per motivi di chiarezza.

Se desideri Base64-codificare la chiave (e probabilmente il IV, anche), è possibile utilizzare il modulo Base64:

base64_key = Base64.encode64(key) 
+1

Mi chiedo se questa risposta abbia bisogno di aggiornamenti o meno, se così fosse sarebbe bello aggiungerne alcuni. –

4

Ruby ha uno OpenSSL library che dovrebbe occuparsi del sollevamento di carichi pesanti.

+0

Grazie. Potrei aver bisogno di passare a PGP perché supporta PKI per i file (ho dei file piccoli) in modo da poter facilmente supportare più utenti senza avere problemi a memorizzare la chiave segreta. – Istvan

+0

@Istvan Esiste anche il supporto PKI in OpenSSL. – emboss

Problemi correlati