2012-08-03 14 views
5

Sto scrivendo uno script Perl che ha bisogno di connettersi a un server SMTP al fine di inviare una e-mail, ma io sinceramente non piace questo tipo di cose:Come potrei nascondere/proteggere password da uno script Perl

my $pass = '123456'; 

e ho trovato Data :: crittografato, che dovrebbe consentire all'utente per richiedere la prima volta e poi memorizzarlo crittografato.

use Data::Encrypted file => ".passwd", qw(encrypted); 
my $password = encrypted('password'); 

Ma non riesco a farlo funzionare, fa un errore di tempo di esecuzione:

Bad formato di file chiave alla linea /Library/Perl/5.12/Data/Encrypted.pm 78

Qualcuno ha lo stesso problema o conosce un altro modo per nascondere/proteggere la password?

+3

anche se funziona, come lo decodificherai? – pavel

+0

forse 'md5' ti aiuterà, controllando la somma e tutto ... – gaussblurinc

+0

Sì, lo vedo anche io. Il problema è in [Crypt :: RSA :: Key :: Private :: SSH :: deserialize line 68] (https://metacpan.org/source/VIPUL/Crypt-RSA-1.99/lib/Crypt/RSA/Key /Private/SSH.pm#L68). 'croak 'Formato file chiave errato" a meno che $ id eq PRIVKEY_ID; '** $ id ** è' ----- INIZIA A RSA PRIVATE KEY ----- ', ** PRIVKEY_ID ** è' SSH PRIVATE KEY FILE FORMATO 1.1'. – daxim

risposta

8

Il modulo Data::Encrypted è stato rilasciato l'ultima volta nel 2001. Direi che è un buon segno di non usarlo.

Normalmente, direi che memorizzare le password è una cattiva idea persino crittografata. Tuttavia, se è necessario memorizzare una password per l'utilizzo contattando un altro sistema, la crittografia è la strada da percorrere. Il modo in cui lo farei è qualcosa di simile:

# Rijndael is also known as AES, which is the encryption standard used by the NSA 
use Crypt::Rijndael; 
use IO::Prompter; 

# This secret is exactly 32 bytes long, you could prompt for this as a 
# passphrase or something and pad it with spaces or whatever you need 
my $app_secret = 'this_is_the_key_the_app_uses....'; 

# Setup the encryption system 
my $crypto = Crypt::Rijndael->new($app_secret, Crypt::Rijndael::MODE_CBC()); 

# Ask the user to enter the password the first time 
my $password = prompt "password: ", -echo => ''; # from IO::Prompter 

# Encrypt the password. You can save this off into a file however you need to 
my $enc_password = $crypto->encrypt($password); 

# Later load it from the file and decrypt it: 
my $password = $crypto->decrypt($password); 

Per ulteriori informazioni vedere Crypt::Rijndael e IO::Prompter.

+1

Un po 'fuori tema, ma cosa guadagni con questo? Se si richiede la passphrase, si potrebbe anche richiedere direttamente la password. E se si codifica la passphrase con difficoltà, non aiuta molto a nascondere la propria password "crittografata". O mi manca qualcosa? – pavel

+0

Non è necessario richiedere la passphrase, questo è solo un modo possibile per renderlo più sicuro. Inoltre, se ci sono più password da proteggere, una passphrase è più facile da scrivere e ricordare rispetto a più password. – zostay

+0

Anche senza una passphrase e semplicemente archiviando l'app segreta in un file separato o persino nello script stesso, è possibile evitare che qualcuno accidentalmente legga la propria password SMTP inavvertitamente. Se qualcuno è in grado di rubare il file della password, ma non ottiene l'app segreta, si ottiene un ritardo tra la password rubata e la password in fase di crack. È piuttosto sottile per quanto riguarda la sicurezza, ma è leggermente meglio di niente. – zostay

2

Quando si ha a che fare con uno script che invia password in testo semplice a un servizio senza alcuna interazione dell'utente, si è già condannati. Qualsiasi soluzione con cui verrai sarà solo la sicurezza per oscurità. Puoi venire con la soluzione come ha fatto zostay. Ma è equivalente all'acquisto del vault più avanzato, ma lasciando la chiave sotto il tappetino e attaccando la carta con il testo: "Controlla il tappetino per la chiave!" alla porta d'ingresso. Guarda, mi limiterò a copiare lo script, grep per la password. Quindi troverò la riga come my $password = $crypto->decrypt($password); e inserirò warn $password; proprio nella riga sottostante e eseguirò lo script. Questo è tutto. Non mi interessa quale algoritmo usi, non mi interessa dove e come memorizzi la password. Puoi rendermi più difficile, ma il mio sforzo di crack sarà sempre di un ordine di grandezza inferiore al tuo sforzo per renderlo difficile. La tua sceneggiatura è la chiave. Guarda tutta questa industria cinematografica. Hanno speso miliardi per venire con un mucchio di stupide merda. Sono finiti con uno speciale HW, anche il cavo ha la sua chiave. Divertente! Sta molestando solo gli utenti leali.

Inserisci la password semplice nello script se non vuoi sembrare sciocco. Se vuoi andare con sicurezza da oscurità, allora non nominare le variabili con nomi ragionevoli, non utilizzare alcun modulo standard (guarda, il metodo decrypt è indizio!) E non perdere tempo con raffinatezza. Non guarderò come memorizzi o cripti la password, cercherò dove dovrai usarla e collegarti lì. È molto più facile e molto più difficile da nascondere.

3

Grazie! Ecco la mia soluzione finale:

sub smtp_passwd(){ 
    #The secret pass phrase 
    my $app_secret = 'd.<,3eJ8sh[(#@1jHD829J,Z!*dGsH34'; 

    #password file name 
    my $passwd_file_name = ".passwd"; 

    # Setup the encryption system 
    my $crypto = Crypt::Rijndael->new($app_secret, Crypt::Rijndael::MODE_CBC()); 

    #File Handler 
    my $passwd_file; 

    #If we cannot open the password file we initiate a new one 
    unless (open ($passwd_file, '<', $passwd_file_name)) { 

     #Create a new file in write mode 
     open ($passwd_file, '>', $passwd_file_name); 

     # Ask the user to enter the password the first time 
     my $password = prompt "password: ", -echo => ''; # from IO::Prompter 

     #Password must be multiple of 16 (we deliberately chose 16) 
     my $pass_length = 16; 

     #If password is to short we complete with blank 
     $password = $password." "x ($pass_length - length ($password)) if (length ($password) < $pass_length); 

     #If password is to long we cut it 
     $password = substr ($password, 0, $pass_length) if (length ($password) > $pass_length); 

     #Encryption of the password 
     my $enc_password = $crypto->encrypt($password); 

     #we save the password in a file 
     print $passwd_file $enc_password; 

     #we close the file (Writing mode) 
     close $passwd_file; 

     #Reopen the file in reading mode 
     open ($passwd_file, '<', $passwd_file_name) 
    } 

    #Loading the password en decrypt it 
    my $password = $crypto->decrypt(<$passwd_file>); 

    #Close the file 
    close $passwd_file; 

    #Return the password (Here the password is not protected) 
    return $password; 
} 
0

Ecco il codice in piena regola che utilizza parte del codice di cui sopra e parte presa dal Perlmonk. Lo script richiede prima il nome utente e la password dell'utente, lo crittografa e lo memorizza nel file .crypt. Quindi legge da esso, decodifica e mostra il testo originale. Alla seconda volta utilizzerà le credenziali dell'utente esistenti.

use Crypt::Rijndael; 
use IO::Prompter; 
use Crypt::CBC; 
#keys 
my $key = "a" x 32; 
my $cipher = Crypt::CBC->new(-cipher => 'Rijndael', -key => $key); 
my @plaintext; 
my @ciphertext; 
#keys 

#filefield 
#password file name 
#my $file_name = ".crypt"; 
my $file_name = ".crypt"; 
#File Handler 
my $file; 


#If we cannot open the password file we initiate a new one 
unless (open ($file, '<:encoding(UTF-8)', $file_name)) { #<:encoding(UTF-8) 
#Create a new file in write mode 
    open ($file, '>', $file_name); 
    $plaintext[0]= prompt "Username:"; 
    $plaintext[1]= prompt "Password:", -echo => ''; 
    print "#################################################################################\n"; 
    print "# User credentials will be encrypted and stored in .crypt file and same is  #\n"; 
    print "# reused next time. If you need to add new user credentials delete the .crypt #\n"; 
    print "# file and re run the same script.            #\n"; 
    print "#################################################################################\n"; 
    $plaintext[0]=~ s/^\s*(.*?)\s*$/$1/; 
    $plaintext[1]=~ s/^\s*(.*?)\s*$/$1/; 


    while($plaintext[0] =~ /^\s*$/){ 
    $plaintext[0]= prompt "Username is mandatory:"; 
    $plaintext[0]=~ s/^\s*(.*?)\s*$/$1/; 
    } 
    while($plaintext[1] =~ /^\s*$/){ 
    $plaintext[1]= prompt "Password is mandatory:"; 
    $plaintext[1]=~ s/^\s*(.*?)\s*$/$1/; 
    } 


    $ciphertext[0] = $cipher->encrypt($plaintext[0]); 
    $ciphertext[1] = $cipher->encrypt($plaintext[1]); 

    #we save the password in a file 
    print $file $ciphertext[0]; 

    #print $file "\n"; 
    #we save the password in a file 
    print $file $ciphertext[1]; 
    #we close the file (Writing mode) 
    close $file; 

    #Reopen the file in reading mode 
    open ($file, '<', $file_name) 
} 


my @holder; 
my $content; 
if (open($file, '<', $file_name)) { 
    #chomp(@holder = <$file>); 
local $/; 
    $content = <$file>; 

} else { 
    warn "Could not open file '$filename' $!"; 
} 
@holder = split(/(?=Salted__)/, $content); 
    print "Encrypted username:",$holder[0]; 
    print "\n"; 
    print "Encrypted password:",$holder[1],"\n"; 

#Loading the password en decrypt it 
$plaintext[0] = $cipher->decrypt($holder[0]); 
$plaintext[1] = $cipher->decrypt($holder[1]); 

print "\n\n"; 

print 'Username is:',"$plaintext[0]\n"; 
print 'Password is:',"$plaintext[1]\n"; 
#Close the file 
close $file; 

#filefield 
Problemi correlati