The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Crypt::CreditCard - 256-bit AES credit card encryption

SYNOPSIS

  use Crypt::CreditCard;

  my $ciphertext;
  my $password = 'f00b@r'; # acquire from user
  my $key;

  {
    # Encryption
    my $card = Crypt::CreditCard->new();
    $key = $card->key(); # generates key, suitable for a secure cookie

    $card->number('5276440065421319') || die $card->errstr();
    $card->cvv2('2345') || die $card->errstr(); # optional, may be omitted
    $card->month('12') || die $card->errstr(); # optional, may be omitted
    $card->year('03') || die $card->errstr(); # optional, may be omitted
    $card->password($password);

    $ciphertext = $card->encrypt() || die $card->errstr(); # store in db
  }

  {
    # Decryption
    my $card = Crypt::CreditCard->new();
    $card->password($password); # acquire from user
    $card->key($key); # acquire from a secure cookie
    $card->decrypt($ciphertext) || die $card->errstr(); # get from db

    my $number = $card->number(); # 5276440065421319
    my $cvv2 = $card->cvv2(); # 2345
    my $month = $card->month(); # 12
    my $year = $card->year(); # 03
  }

DESCRIPTION

Note: You are advised to read the 'CAVEATS' section later in this document. Additionally, until this distribution reaches a non-developer (stable) release stage the interface and implementation may change at any time. It is therefore not recommended to make use of this distribution in a production environment until a non-developer release is made.

This module uses the United States Government's Advanced Encryption Standard (AES/Rijndael) with 256-bit keys to encrypt a credit card, and optionally a CVV2 number, expiration month and year. The encrypted representation, which includes all the given credit card components, is suitable for storing in a database field, e.g., TEXT (for the default datasize), or VARCHAR (if you manually decrease the datasize).

In order to encrypt, a password (something the user knows) and a key (something the user has) must first be specified. The password that the user uses to log into your service that requires secure credit card storage is usually what's used as the password. The password itself, if it's being stored in a databse, should ideally be encrypted using, say, SQL's PASSWORD(). The key is an automatically generated crytographically secure 256-bit randomly generated number. This key is suitable for storage in, say, a *secure* cookie.

Before a credit card number is encrypted, a check is made as to the validity of the credit card number using a mod-10 check. An error will be raised if the credit card number is invalid.

In the interest of heightened reliability and security an MD5 checksum is stored along with the credit card information, the key is xor'd against the password before being used as a basis for encryption, and the credit card information is padded with cryptographically secure data.

Assuming that someone built a machine that could crack a DES key in one second, it would still take that machine 149 trillion years to crack a 128-bit AES key. Crypt::CreditCard, by default, uses 256-bit keys.

PUBLIC METHODS

  • new

    Constructor. Takes no arguments. Returns a credit card object.

  • errstr

    Gets the error string (if applicable). See 'CAVEATS'.

  • key

    Generates or sets a 256-bit (by default) crytographically secure number suitable for storage in, say, a secure cookie. This method is mandatory.

  • password

    Sets the password that will be xor'd against the key prior to encryption. This method is mandatory.

  • keylength

    Gets or sets the keylength, which must be one of: 128, 192 or 256. This method is optional, and by default is set to 256.

  • datasize

    Gets or sets the datasize, which is usually one of: 128, 192 or 256. This method is optional, and by default is set to 256. The datasize must be a multiple of 32, and greater than or equal to 96.

  • strength

    Gets or sets the strength of randomness (see Crypt::Random and CAVEATS). This is either /dev/random, /dev/urandom, or an alternative in /dev/. This method is optional, and by default is set to /dev/random.

  • cvv2

    Gets or sets the cvv2 number. See: http://www.google.com/search?q=CVV2&ie=UTF-8&oe=UTF-8. This method requires a string representation of a number, not a number (see CAVEATS). This method is optional. If given, argument must be integral and between 3 and 4 digits.

  • month

    Gets or sets the expiration month. This method requires a string representation of a number, not a number (see CAVEATS). This method is optional. If given, argument must be integral and either 1 or 2 digits.

  • year

    Gets or sets the expiration year. This can be either, for example, "04" or "2004". This method requires a string representation of a number, not a number (see CAVEATS). This method is optional. If given, argument must be integral and either 2 or 4 digits.

  • number

    Gets or sets the credit card number. The credit card must be valid or an error will be raised. This method requires a string representation of a number, not a number (see CAVEATS). This method is mandatory.

  • encrypt

    Encrypts the credit card previously given and returns the ciphertext representation. The key(), number(), and password() methods must be called prior to calling encrypt().

  • decrypt

    Decrypts the credit card information. Takes the ciphertext as an argument. The key(), and password() methods must be called prior to calling decrypt().

  • mode

    Gets or sets the mode, which is one of the following (see Crypt::Rijndael for details):

    ecb (electronic codebook mode), cbc (cipher block chaining, the default), cfb (128-bit cipher feedback), ofb (128-bit output feedback), ctr (counter mode).

    This is optional and defaults to cipher block chaining mode.

  • iv

    Gets or sets the initial vector (see Crypt::Rijndael for details).

PRIVATE METHODS

  • _pack_cc

  • _unpack_cc

  • _pad_missing

    Pads cvv2, month, and year with random cryptographically secure data if they were not given.

  • _is_string

    Returns 1 if the argument was a string, 0 otherwise.

  • _validate

    Returns true if the mod10 passes for the credit card.

  • _pad

    Generates an amount of crytographically secure padding based upon the datasize by calling gen_pad().

  • _gen_pad

    Generates 32 bits of crytographically secure padding.

  • _kill

    Renders the object passed to it unusable for future operations.

CAVEATS

The methods: number(), cvv2(), month(), and year() *MUST* be passed string arguments, not numeric arguments. This means that, for example, you must do $card->number('5276440065421319'), and not $card->number(5276440065421319). If you attempt to call any of the above methods with numeric arguments, Crypt::CreditCard will detect it and generate an error.

An object reference is rendered unusuable for any further access after an encrypt() is called against it. This is a security feature.

By default, strength() is set to use /dev/random, however IF YOU DON'T DESIRE BLOCKING AND DECREASED SPEED FOR THE PURPOSE OF MORE RANDOM DATA, CONSIDER SETTING strength() TO USE /dev/urandom. The following excerpt from Crypt::Random states, "The /dev/random driver maintains an estimate of true randomness in the pool and decreases it every time random strings are requested for use. When the estimate goes down to zero, the routine blocks and waits for the occurrence of non-deterministic events to refresh the pool. When the routine is blocked, Crypt::Random's read() will be blocked till desired amount of random bytes have been read off of the device. The /dev/random kernel module also provides another interface, /dev/urandom, that does not wait for the entropy-pool to recharge and returns as many bytes as requested. For applications that must not block (for a potentially long time) should use /dev/urandom. /dev/random should be reserved for instances where very high quality randomness is desired. If there's a hardware random number generator available, for instance the Intel i8x0 random number generator, please use it instead of /dev/random! It'll be high quality, a lot faster and it won't block! Usually your OS will provide access to the RNG as a device, eg (/dev/intel_rng)."

IN ORDER TO BE GUARANTEED NOMINAL OPERATION, YOU MUST check for errstr() on the following methods: mode(), strength(), keylength(), datasize(), encrypt(), and decrypt(). Additionally, you must check for errstr() on the following methods, but *only* when you are assigning to them: cvv2(), month(), year(), number().

BUGS

  Please report any bugs to (patches welcome):
  http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Crypt-CreditCard

COPYRIGHT

  Copyright (c) 2003 Adam J. Foxson. All rights reserved.
  Copyright (c) 2003 Marty Pauley. All rights reserved.

LICENSE

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

SEE ALSO

AUTHORS

Adam J. Foxson <afoxson@pobox.com>, with patches from Marty Pauley at <kasei@cpan.org>.