2012-08-03 9 views
5

Tôi đang viết một kịch bản Perl mà cần phải kết nối với một máy chủ SMTP để gửi thư, nhưng tôi thực sự không thích loại này điều:Làm thế nào tôi có thể ẩn/bảo vệ mật khẩu từ một kịch bản Perl

my $pass = '123456'; 

và tôi thấy dữ liệu :: Mã hóa, mà nên cho phép người sử dụng để nhắc nó lần đầu tiên và sau đó lưu nó được mã hóa.

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

Nhưng tôi không thể làm cho nó hoạt động, nó làm cho một lỗi thời gian chạy:

Bad định dạng tập tin quan trọng tại dòng /Library/Perl/5.12/Data/Encrypted.pm 78

Có ai có cùng vấn đề hoặc biết cách khác để ẩn/bảo vệ mật khẩu không?

+3

ngay cả khi nó hoạt động, bạn sẽ giải mã nó như thế nào? – pavel

+0

có thể 'md5' sẽ giúp bạn, kiểm tra tổng và tất cả ... – gaussblurinc

+0

Vâng, tôi cũng thấy nó. Vấn đề nằm trong [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" Định dạng tệp khóa không hợp lệ "trừ khi $ id eq PRIVKEY_ID;' ** $ id ** là '----- BEGIN RSA PRIVATE KEY -----', ** PRIVKEY_ID ** là 'TÊN CHÍNH RIÊNG CỦA SSH FORMAT 1.1'. – daxim

Trả lời

8

Mô-đun Data::Encrypted được phát hành lần cuối vào năm 2001. Tôi cho rằng đó là một dấu hiệu tốt để không sử dụng nó.

Thông thường, tôi muốn nói lưu trữ mật khẩu là một ý tưởng tồi thậm chí được mã hóa. Tuy nhiên, nếu bạn phải lưu trữ một mật khẩu để sử dụng liên hệ với một hệ thống khác, mã hóa nó là cách để đi. Con đường tôi sẽ làm điều đó là một cái gì đó như thế này:

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

Để biết thêm thông tin, xem Crypt::RijndaelIO::Prompter.

+1

Một chút tắt chủ đề, nhưng bạn có được gì với điều này? Nếu bạn nhắc mật khẩu, bạn cũng có thể nhắc mật khẩu trực tiếp. Và nếu bạn khó mã hóa cụm mật khẩu, nó sẽ không giúp bạn giấu mật khẩu 'mã hóa' của mình. Hoặc tôi thiếu một cái gì đó? – pavel

+0

Bạn không cần phải nhắc mật khẩu, đó chỉ là một cách có thể làm cho nó an toàn hơn. Ngoài ra, nếu có nhiều mật khẩu để bảo vệ, một cụm mật khẩu sẽ dễ dàng nhập và nhớ hơn nhiều mật khẩu. – zostay

+0

Ngay cả khi không có cụm mật khẩu và chỉ lưu trữ bí mật ứng dụng trong một tệp riêng biệt hoặc thậm chí trong tập lệnh, bạn có thể tránh vô tình đọc một người vô tình đọc mật khẩu SMTP thực của bạn. Nếu ai đó có thể ăn cắp tập tin mật khẩu, nhưng không nhận được các ứng dụng bí mật, bạn nhận được một sự chậm trễ giữa các mật khẩu bị đánh cắp và mật khẩu bị nứt. Nó khá mỏng như xa như an ninh đi, nhưng nó tốt hơn một chút so với không có gì. – zostay

2

Khi bạn đang xử lý một tập lệnh gửi mật khẩu thuần văn bản đến một dịch vụ mà không có bất kỳ tương tác nào của người dùng, bạn đã phải chịu số phận. Bất kỳ giải pháp bạn sẽ đi với sẽ chỉ là an ninh bởi tối tăm. Bạn có thể đi kèm với giải pháp như zostay đã làm. Nhưng nó là tương đương với việc mua vault tiên tiến nhất nhưng để chìa khóa dưới tấm thảm và dán giấy với văn bản: "Kiểm tra mat cho chìa khóa!" đến cửa trước. Hãy nhìn xem, tôi sẽ chỉ sao chép tập lệnh, grep cho mật khẩu. Sau đó, tôi sẽ tìm thấy dòng như my $password = $crypto->decrypt($password); và đặt warn $password; ngay tại dòng bên dưới và chạy tập lệnh. Đó là nó. Tôi không quan tâm bạn sử dụng thuật toán nào, tôi không quan tâm bạn lưu trữ mật khẩu ở đâu và như thế nào. Bạn có thể làm cho tôi khó khăn hơn, nhưng nỗ lực của tôi để crack sẽ luôn luôn là một vài thứ tự độ lớn ít hơn nỗ lực của bạn để làm cho nó khó khăn. Kịch bản của bạn là chìa khóa. Nhìn vào tất cả ngành công nghiệp điện ảnh này. Họ đã dành hàng tỷ đô la để đi kèm với đống crap ngớ ngẩn. Họ đã kết thúc với HW đặc biệt, thậm chí cáp có chìa khóa riêng của mình. Hilarious! Nó chỉ quấy rối người dùng công bằng.

Đặt mật khẩu thuần túy trong tập lệnh nếu bạn không muốn trông ngớ ngẩn. Nếu bạn muốn đi với bảo mật bằng cách tối tăm thì đừng đặt tên biến với tên hợp lý, không sử dụng bất kỳ mô-đun chuẩn nào (xem, phương pháp decrypt là đầu mối!) Và đừng lãng phí thời gian của bạn với sự tinh tế. Tôi sẽ không nhìn như thế nào bạn lưu trữ hoặc mật mã hóa mật khẩu, tôi sẽ xem nơi bạn sẽ phải sử dụng nó và móc ở đó. Nó là dễ dàng hơn và khó khăn hơn nhiều để ẩn.

3

Cảm ơn! Đây là giải pháp cuối cùng của tôi:

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

đây là mã đầy đủ sử dụng một phần mã được đề cập ở trên và một phần được lấy từ Perlmonk. Kịch bản đầu tiên yêu cầu tên người dùng và mật khẩu từ người dùng, mã hóa và lưu trữ nó trong tệp .crypt. Sau đó đọc từ nó, giải mã và hiển thị văn bản gốc. Vào lần thứ hai, nó sẽ sử dụng các thông tin người dùng hiện có.

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