NAME

Secret::Simple - Secure secrets in configurations and code

VERSION

This document describes Secret::Simple version 0.10

SYNOPSIS

# OOP style
my $ss = Secret::Simple->new();
my $ciphertext = $ss->encrypt($plaintext);
my $plaintext  = $ss->decrypt($ciphertext);

# procedural style
my $ciphertext = ssencrypt($plaintext);
my $plaintext  = ssdecrypt($ciphertext);

DESCRIPTION

This module implements a straightforward interface for encrypting and decrypting secret information such as user IDs and passwords (e.g. database connection or remote account credentials). Secret::Simple can also be used on a limited basis to protect arbitrary data. By default the ciphertext returned is Base 64 encoded so as to be easily embedded within configurations or scripts. A command-line utility called sstool is included to facilitate easy manipulation of cipher and plaintext snippets.

The encryption mechanism utilizes the strong AES algorithm, so any weaknesses in Secret::Simple predominantly lie in how keys are protected. A balance must be struck between key accessibility, key protection, and overall complexity. The calling code can supply a key, series of keys, key files, or a combination. If no key information is explicitly passed, the module will attempt to use the OS user's private SSH DSA key file by default if it exists.

The major goal of this module is to be as secure as possible while being simple and convenient enough to encourage its use. Psychology does factor in: simple is a very important consideration. If the security methods are too onerous or complicated to use, many sysadmins or developers may simply use plaintext (no protection other that OS file permissions) or simple ciphers like rot13. The security of the Secret::Simple method is not perfect, but it does represent a significant improvement over commonly-used nonsecure methods of embedding credentials and other secrets in Perl configurations and scripts. If used appropriately, Secret::Simple can greatly improve application and configuration security. Even so, care must always be taken to protect files and file permissions.

METHODS

new()

my $ss = Secret::Simple->new(); # default to user's private SSH DSA key

my $ss = Secret::Simple->new('my secret key');

my $ss = Secret::Simple->new( %options );

my $ss = Secret::Simple->new( \%options );

The constructor returns a Secret::Simple object. Valid options are:

-key

The value of this parameter can be a scalar or array reference. Multiple elements will simply be concatenated together. This option accepts raw key data by default, but can also accept file-based key data according to the following parameter value syntax:

'secret key phrase'        - string is the literal key (default)

'{sskeyfile}/path/key.raw' - read raw key from file

'{sskeyfile}'              - read raw key from default file

Specifying {sskeyfile} by itself will designate the same behavior as the default of passing no key information: the constructor will attempt to use the literal contents of the current user's ~/.ssh/id_dsa file as a key.

-keyfilesize

Specifies the maximum number of bytes to read from a single key file. The default value of 0 is unlimited, but performance problems may quickly arise if large files (e.g. MP3) are utilized as keys.

decrypt()

    Returns the literal plaintext of the supplied encrypted and Base 64 encoded value.

    Example:

    my $DBCRED = 'zzpjnDlUqz3+KCke5Rr4dA=='; # plaintext is jblow^secret
    
    my $ss = Secret::Simple->new();
    my ($user, $pass) = split /\^/, $ss->decrypt($DBCRED);

decryptraw()

    Performs identically to the decrypt() method except that the value passed is assumed to be raw ciphertext (no Base 64 encoding).

encrypt()

    Returns the Base 64 encoded ciphertext of the supplied literal plaintext.

    Example:

    my $ss = Secret::Simple->new();
    my $ciphertext = $ss->encrypt('jblow^secret');
    # ciphertext will resemble: zzpjnDlUqz3+KCke5Rr4dA==

encryptraw()

    Performs identically to the encrypt() method except the resulting ciphertext is returned without the Base 64 encoding.

key()

    This method can be invoked without an argument to obtain the current key specification value(s). Note that this is not necessarily the same as the information returned by the keydata() method. Invoking with an argument will establish new settings. See the description of the new() method's -key option for more details.

keydata()

    Returns the combined raw key data. The returned data represents the aggregate raw key if multiple keys and key files were specified.

keyfilesize()

    The maximum number of bytes to read from a single key file. This method can be invoked without an argument to obtain the current limit setting (default 0 is unlimited). Invoking with an argument will establish the new setting.

EXPORTED FUNCTIONS

Secret::Simple exports some functions you may use to avoid the OOP interface if you wish.

ssdecrypt($b64ciphertext, [key1], [key2], ...)

    This function requires a minimum of one argument: the Base 64 encoded ciphertext to be decrypted. Any number of optional additional arguments may be specified as key values that follow the same rules as the new() constructor's -key option.

    Examples:

    my $DBCRED = 'zzpjnDlUqz3+KCke5Rr4dA=='; # plaintext is jblow^secret
    
    # 1. simple
    my ($user, $pass) = split /\^/, ssdecrypt($DBCRED);
    
    # 2. id_rsa instead of id_dsa
    my ($user, $pass) = split /\^/, ssdecrypt($DBCRED,
      '{sskeyfile}~/.ssh/id_rsa');
    
    # 3. more complex example
    my ($user, $pass) = split /\^/, ssdecrypt($DBCRED,
      '{sskeyfile}', '{sskeyfile}/path/otherkey');

ssdecryptraw($ciphertext, [key1], [key2], ...)

    Performs identically to the ssdecrypt() function except that the value passed must be raw ciphertext without Base 64 encoding.

ssencrypt($plaintext, [key1], [key2]...)

    This function requires a minimum of one argument: the plaintext to be encrypted. Any number of optional additional arguments may be specified as key values that follow the same rules as the new() constructor's -key option.

    Examples:

    # use default ~/.ssh/id_dsa key
    my $ciphertext = ssencrypt('jblow^secret');
    
    # use explicit passphrase
    my $ciphertext = ssencrypt('jblow^secret', 'secret key');
    
    # use combination of two key files
    my $ciphertext = ssencrypt('jblow^secret',
      '{sskeyfile}/path1/key1', '{sskeyfile}/path2/key2');

ssencryptraw($plaintext, [key1], [key2], ...)

    Performs identically to the ssencrypt() function except the resulting ciphertext is returned without the Base 64 encoding.

DEPENDENCIES

This module requires the following other modules:

  • Carp

  • Crypt::CBC

  • Crypt::Rijndael_PP

  • Exporter

  • MIME::Base64

AUTHOR

Adam G. Foust, <nospam-agf@cpan.org>

COPYRIGHT AND LICENSE

Copyright (c) 2006, Adam G. Foust. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.