【问题标题】:How could I hide/protect password from a Perl script如何从 Perl 脚本中隐藏/保护密码
【发布时间】:2012-08-03 10:21:20
【问题描述】:

我正在编写一个 Perl 脚本,它需要连接到 SMTP 服务器 才能发送邮件,但我真的不喜欢这种东西:

my $pass = '123456';

我发现Data::Encrypted,应该允许用户第一次提示它,然后加密存储。

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

但我无法让它工作,它会导致运行时错误:

/Library/Perl/5.12/Data/Encrypted.pm 第 78 行的错误密钥文件格式

是否有人遇到同样的问题,或者知道隐藏/保护密码的另一种方法?

【问题讨论】:

  • 就算成功了,你要怎么解密呢?
  • 也许md5 会帮助你,检查总和等等......
  • 是的,我也看到了。问题出在Crypt::RSA::Key::Private::SSH::deserialize line 68croak "Bad key file format" unless $id eq PRIVKEY_ID; $id-----BEGIN RSA PRIVATE KEY-----PRIVKEY_IDSSH PRIVATE KEY FILE FORMAT 1.1

标签: perl encryption passwords


【解决方案1】:

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

【讨论】:

  • 有点跑题了,但是你从中得到了什么?如果您提示输入密码,您也可以直接提示输入密码。而且,如果您对密码进行硬编码,那么隐藏您的“加密”密码也无济于事。还是我错过了什么?
  • 您不必提示输入密码,这只是使其更安全的一种可能方式。此外,如果要保护多个密码,则一个密码短语比多个密码更容易输入和记住。
  • 即使没有密码,只是将应用程序密码存储在单独的文件中,甚至是脚本本身,您也可以避免有人无意中读取了您的真实 SMTP 密码。如果有人能够窃取密码文件,但没有获得应用程序机密,那么您会在密码被盗和密码被破解之间出现延迟。就安全性而言,它相当薄,但总比没有好。
【解决方案2】:

谢谢!这是我的最终解决方案:

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;
}

【讨论】:

    【解决方案3】:

    当您正在处理一个脚本,该脚本在没有任何用户交互的情况下向服务发送纯文本密码时,您已经注定要失败。您将提供的任何解决方案都只是默默无闻的安全性。您可以像zostay 那样提供解决方案。但这相当于买了最高级的保险库,但把钥匙放在垫子下面,然后在纸上贴上这样的文字:“检查垫子上的钥匙!”到前门。看,我将复制脚本,grep 密码。然后我会找到像my $password = $crypto-&gt;decrypt($password); 这样的行并将warn $password; 放在下面的行并运行脚本。而已。我不在乎你使用什么算法,我不在乎你在哪里以及如何存储密码。你可以让我变得更难,但我破解的努力总是比你让它变得困难的努力少几个数量级。你的脚本是关键。看看这一切电影业。他们花了数十亿美元来带一堆愚蠢的废话。他们最终得到了特殊的硬件,甚至电缆也有自己的密钥。好笑!它只会骚扰公平的用户。

    如果您不想看起来很傻,请在脚本中放置普通密码。如果你想通过默默无闻来保证安全,那么不要用合理的名称命名变量,不要使用任何标准模块(看,方法decrypt 是线索!)并且不要浪费你的时间与复杂性。我不会看你如何存储或加密密码,我会看看你必须在哪里使用它并挂在那里。隐藏起来更容易也更难。

    【讨论】:

      【解决方案4】:

      这里是完整的代码,它利用了上面提到的部分代码和来自 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
      

      【讨论】:

        猜你喜欢
        • 2010-10-10
        • 2013-04-16
        • 1970-01-01
        • 2013-06-05
        • 1970-01-01
        • 2021-04-06
        • 2019-09-18
        • 2011-05-18
        • 1970-01-01
        相关资源
        最近更新 更多