#!/usr/bin/perl # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Module to simplify cross-language encryption/decryption w/ Blowfish. # Copyright (C) 2006 Josh Kuo # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library 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 # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301 USA # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # package Crypt; use strict; use warnings::register; use Crypt::CBC; use Digest::SHA qw(sha256_hex); use MIME::Base64; sub new { my $class = shift; my $self = { CIPHER => undef, }; bless $self, $class; $self->init(@_); return $self if $self; } sub decrypt { my $self = shift; my $encoded_encrypted = shift; my $encrypted = decode_base64($encoded_encrypted); my $decrypted = $self->{CIPHER}->decrypt($encrypted); chomp ($decrypted); return $decrypted; } sub encrypt { my $self = shift; my $plain_text = shift; my $encrypted = $self->{CIPHER}->encrypt($plain_text); my $encoded_encrypted = encode_base64($encrypted); chomp ($encoded_encrypted); return $encoded_encrypted; } sub init { my $self = shift; my $secret_phrase = shift; my $method = (caller(0))[3] . "()"; my $digest = sha256_hex($secret_phrase); my $iv = substr($digest, 0, 8); my $key = substr($digest, 8, 56); my $cipher = Crypt::CBC->new({ 'cipher' => 'Blowfish', 'iv' => $iv, 'key' => $key, 'padding' => 'null', 'prepend_iv' => 0, 'regenerate_key' => 0, }); if (!$cipher && warnings::enabled()) { warnings::warn($self, "$method: could not create CBC cipher"); } $self->{CIPHER} = $cipher; } 1; __END__ =head1 NAME qrypto::Crypt - Module to simplify cross-language encryption/decryption w/ Blowfish. =head1 SYNOPSIS use qrypto::Crypt; use qrypto::Crypt; use warnings 'qrypto::Crypt'; use strict; my $qrypto = new Crypt('my ultra secret password'); my $encrypted = $qrypto->encrypt('plain text goes here'); my $decrypted = $qrypto->decrypt($encrypted); =head1 METHODS =head2 new The constructor takes one argument, which is your secret password/passphrase. Use it as follows: my $qryto = new Crypt('secret password'); =head2 decrypt Reads the encrypted-encoded data, remove the Base64 encoding first, then decrypt the binary data, and returns the plain text. =head2 encrypt Encrypts the input (plain text) into encrypted data encoded with Base64. =head1 ALGORITHM Blowfish requires two inputs, the IV (Initialization Vector) and the key. The key must be 56 in length. The easiest and secure way to provide both inputs is to take a single input (the pass-phrase) and run SHA256 on it to produce a hex string that is 64 in length. Use the first 8 for the IV, and the remaining 56 for the key. So it looks like this: $passphrase = 'this is a pass-phrase'; $sha256 = '15343cba39004cd07d79ac972fa4bf50c7c504a8add5cb1c900e2263f82996f3'; $iv = '15343cba'; $key= '39004cd07d79ac972fa4bf50c7c504a8add5cb1c900e2263f82996f3'; =head1 BASE64 ENCODING Base64 Encoding: ================ The Blowfish encryption usually yields raw binary output, and when printed to screen or stored to file, it looks like this: zԐ���E|s��E^�� The biggest problem is when this is stored to a database table, and retrieving it. This not only messes up the terminal display, it sometimes cause some data loss because some binary bits cannot be displayed or stored properly. One of the solutions is to change the database column type to BLOB instead of VARCHAR (MySQL), but sometimes that may not be desirable. To side step this problem, encode the binary output with Base64, so the garabe you see above becomes the following ASCII string: etSQutPwRXxzjclFXuC29g== =head1 AUTHOR Josh Kuo http://www.qbangsolutions.com =head1 COPYRIGHT AND LICENSE Copyright 2007 by Josh Kuo This library is free software; you can redistribute it and/or modify it under the terms of LGPL. =cut