2012-08-03 77 views
5

我正在寫一個Perl腳本需要連接到SMTP服務器以發送郵件,但我真的不喜歡這種事情:我怎麼能隱藏/保護密碼Perl腳本

my $pass = '123456'; 

而且我發現數據加密::,應該允許用戶提示它的第一次,然後存儲它加密。

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

但我不能讓它工作,它使運行時錯誤:

壞密鑰文件格式的/Library/Perl/5.12/Data/Encrypted.pm線78

是否有人有同樣的問題,或知道另一種方法來隱藏/保護密碼?

+3

即使它工作,你將如何解密它? – pavel 2012-08-03 10:23:42

+0

也許'md5'會幫助你,檢查總數和所有... – gaussblurinc 2012-08-03 10:29:01

+0

是的,我也看到了。問題出在[Crypt :: RSA :: Key :: Private :: SSH :: deserialize第68行](https://metacpan.org/source/VIPUL/Crypt-RSA-1.99/lib/Crypt/RSA/Key /Private/SSH.pm#L68)。 'croak「錯誤的關鍵文件格式」除非$ id eq PRIVKEY_ID;'** $ id **是'----- BEGIN RSA PRIVATE KEY -----',** PRIVKEY_ID **是'SSH PRIVATE KEY FILE格式1.1'。 – daxim 2012-08-03 11:11:00

回答

8

Data::Encrypted模塊最後在​​2001年發佈。我想說這是一個不使用它的好兆頭。

通常,我會說存儲密碼是一個壞主意,即使加密。但是,如果您必須存儲密碼才能聯繫其他系統,則需要對其進行加密。我會做的方式是這樣的:

# 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); 

欲瞭解更多信息,請參閱Crypt::RijndaelIO::Prompter

+1

有點題外話,但你從​​中得到什麼?如果您提示輸入密碼,則可以直接提示輸入密碼。如果你對密碼進行了硬編碼,它對隱藏你的'加密'密碼沒有多大幫助。或者我錯過了什麼? – pavel 2012-08-03 13:16:21

+0

您不必提示輸入密碼,這只是使其更安全的一種可能方式。另外,如果有多個密碼要保護,則一個密碼短語比多個密碼更容易輸入和記憶。 – zostay 2012-08-03 14:09:01

+0

即使沒有密碼,只需將應用程序祕密存儲在單獨的文件中或甚至腳本本身中,也可以避免有人意外地無意中讀取真實的SMTP密碼。如果某人能夠竊取密碼文件,但沒有獲得應用程序的祕密,則會在密碼被盜和密碼被破解之間出現延遲。就安全性而言,它非常薄,但它比沒有好一點。 – zostay 2012-08-03 14:11:40

2

當你正在處理一個正在發送純文本密碼的服務而沒有任何用戶交互的服務時,你已經註定了。任何你將要出現的解決方案都只是默默無聞的安全。您可以像zostay那樣提供解決方案。但它相當於購買最先進的保險庫,但讓墊子下面的鑰匙和文字貼紙:「檢查墊子的鑰匙!」到前門。看,我只會複製腳本,grep輸入密碼。然後我會找到像my $password = $crypto->decrypt($password);這樣的行,並將warn $password;放在下面的行並運行腳本。而已。我不在乎你使用什麼算法,我不在乎你在哪裏以及如何存儲密碼。你可以讓我更加努力,但是我的努力要比努力讓它變得困難的努力總是少一個數量級。你的腳本是關鍵。看看這個電影業。他們花了數十億美元來與一堆愚蠢的廢話。他們結束了特殊的硬件,即使有線也有自己的鑰匙。爆笑!它只是騷擾公平用戶。

如果您不想看起來很傻,請在腳本中輸入簡明密碼。如果你想通過默默無聞的安全行爲,那麼不要使用明智的名稱命名變量,不要使用任何標準模塊(看,方法decrypt是線索!),不要浪費你的時間與複雜性。我不會看你如何存儲或加密密碼,我會看你將不得不使用它並在那裏掛鉤。隱藏起來要容易得多,而且要難得多。

3

謝謝!這裏是我的最終解決方案:

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

這裏是充分發揮的代碼,它利用了上面提到的部分代碼和部分代碼從Perlmonk。該腳本首先會向用戶詢問用戶名和密碼,並將其加密並存儲在.crypt文件中。然後從中讀取,解密並顯示原始文本。第二次它將使用現有的用戶憑證。

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