Crypt-Rijndael_PP
view release on metacpan or search on metacpan
Rijndael_PP.pm view on Meta::CPAN
#!/usr/bin/perl -w
# $Id: Rijndael_PP.pm,v 1.21 2010/09/22 13:31:36 lackas Exp $
package Crypt::Rijndael_PP;
require 5.004;
use strict;
use integer;
use Carp;
use vars qw'$VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS @ISA';
require Exporter;
@ISA = 'Exporter';
$VERSION = 0.05;
@EXPORT_OK = qw(
blockDecrypt blockEncrypt blockEncryptRound blockDecryptRound
cipherUpdateRounds cipherInit makeKey
MODE_ECB MODE_CBC MODE_CFB1
DIR_ENCRYPT DIR_DECRYPT
);
@EXPORT = qw(rijndael_encrypt rijndael_decrypt);
%EXPORT_TAGS = (
all => [@EXPORT_OK,@EXPORT],
modes => [qw(MODE_ECB MODE_CBC MODE_CFB1)],
directions => [qw(DIR_ENCRYPT DIR_DECRYPT)],
CAPI => [qw(cipherInit makeKey blockDecrypt blockEncrypt)]
);
# boxes-ref.dat
use constant Logtable => [
0, 0, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7
];
use constant Algotable => [
1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
];
my @S = (
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
Rijndael_PP.pm view on Meta::CPAN
# KeyAddition(a,rk[ROUNDS],BC);
# Substitution(a,Si,BC);
# ShiftRow(a,1,BC);
KeyAddition(@a,$rk->[$ROUNDS],$BC);
Substitution(@a,@Si,$BC);
ShiftRow(@a,1,$BC);
#
# /* ROUNDS-1 ordinary rounds
# */
# for(r = ROUNDS-1; r > rounds; r--) {
# KeyAddition(a,rk[r],BC);
# InvMixColumn(a,BC);
# Substitution(a,Si,BC);
# ShiftRow(a,1,BC);
# }
for ($r = $ROUNDS-1; $r > $rounds; $r--) {
KeyAddition(@a,$rk->[$r],$BC);
InvMixColumn(@a,$BC);
Substitution(@a,@Si,$BC);
ShiftRow(@a,1,$BC);
}
#
# if (rounds == 0) {
# /* End with the extra key addition
# */
# KeyAddition(a,rk[0],BC);
# }
if ($rounds == 0) {
KeyAddition(@a,$rk->[0],$BC);
}
#
# return 0;
#}
@_[0..3] = @a;
return 0
}
##################################
# api-ref.c
# define DIR_ENCRYPT 0 /* Are we encrpyting? */
sub DIR_ENCRYPT() { 0 }
# define DIR_DECRYPT 1 /* Are we decrpyting? */
sub DIR_DECRYPT() { 1 }
# define MODE_ECB 1 /* Are we ciphering in ECB mode? */
sub MODE_ECB() { 1 }
# define MODE_CBC 2 /* Are we ciphering in CBC mode? */
sub MODE_CBC() { 2 }
# define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */
sub MODE_CFB1() { 3 }
# define TRUE 1
sub TRUE() { 1 }
# define FALSE 0
sub FALSE() { 0 }
# define BITSPERBLOCK 128 /* Default number of bits in a cipher block */
sub BITSPERBLOCK() { 128 }
# /* Error Codes - CHANGE POSSIBLE: inclusion of additional error codes */
#define BAD_KEY_DIR -1 /* Key direction is invalid, e.g., unknown value */
#define BAD_KEY_MAT -2 /* Key material not of correct length */
#define BAD_KEY_INSTANCE -3 /* Key passed is not valid */
#define BAD_CIPHER_MODE -4 /* Params struct passed to cipherInit invalid */
#define BAD_CIPHER_STATE -5 /* Cipher in wrong state (e.g., not initialized) */
#define BAD_CIPHER_INSTANCE -7
# /* CHANGE POSSIBLE: inclusion of algorithm specific defines */
#define MAX_KEY_SIZE 64 /* # of ASCII char's needed to represent a key */
sub MAX_KEY_SIZE() { 64 }
#define MAX_IV_SIZE BITSPERBLOCK/8 /* # bytes needed to represent an IV */
sub MAX_IV_SIZE() { BITSPERBLOCK/8 }
#int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial)
#{
# word8 k[4][MAXKC];
# int i, j, t;
sub makeKey($$$$) {
my ($key, $direction, $keyLen, $keyMaterial) = @_;
#$keyLen = length $keyMaterial; # hey, it's perl :-)
my @k;
#
# if (key == NULL) {
# return BAD_KEY_INSTANCE;
# }
unless ( defined $key and ref $key eq 'HASH') {
die "BAD_KEY_INSTANCE";
}
#
# if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
# key->direction = direction;
# } else {
# return BAD_KEY_DIR;
# }
if ($direction == DIR_ENCRYPT or $direction == DIR_DECRYPT) {
$key->{direction} = $direction
} else {
die "BAD_KEY_DIR";
}
Rijndael_PP.pm view on Meta::CPAN
if (defined $keyMaterial) {
$key->{keyMaterial} = substr ($keyMaterial,0,$keyLen/4)
}
#
# /* initialize key schedule: */
# for(i = 0; i < key->keyLen/8; i++) {
# t = key->keyMaterial[2*i];
# if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
# else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
# else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
# else return BAD_KEY_MAT;
#
# t = key->keyMaterial[2*i+1];
# if ((t >= '0') && (t <= '9')) j ^= (t - '0');
# else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
# else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
# else return BAD_KEY_MAT;
#
# k[i % 4][i / 4] = (word8) j;
# }
my $i;
my @keyMaterial = unpack 'A2'x(length($key->{keyMaterial})/2), $key->{keyMaterial};
for $i (0..$keyLen/8-1) {
$k[$i % 4][$i / 4] = hex $keyMaterial[$i];
}
#
# rijndaelKeySched (k, key->keyLen, key->blockLen, key->keySched);
#my @W;
#rijndaelKeySched(@k, $key->{keyLen}, $key->{blockLen}, @W);
rijndaelKeySched(@k, $key->{keyLen}, $key->{blockLen}, $key->{keySched});
# $key->{keySched} = \@W;
#
# return TRUE;
#}
$_[0] = $key;
return TRUE;
}
#int cipherInit(cipherInstance *cipher, BYTE mode, char *IV)
#{
# int i, j, t;
sub cipherInit($$;$) {
my ($cipher, $mode, $IV) = @_;
my $i;
#
# if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
# cipher->mode = mode;
# } else {
# return BAD_CIPHER_MODE;
# }
if ($mode == MODE_ECB or $mode == MODE_CBC or $mode == MODE_CFB1) {
$cipher->{mode} = $mode
} else {
die "BAD_CIPHER_MODE";
}
#
# if (IV != NULL) {
# for(i = 0; i < cipher->blockLen/8; i++) {
# t = IV[2*i];
# if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
# else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
# else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
# else return BAD_CIPHER_INSTANCE;
#
# t = IV[2*i+1];
# if ((t >= '0') && (t <= '9')) j ^= (t - '0');
# else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
# else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
# else return BAD_CIPHER_INSTANCE;
#
# cipher->IV[i] = (BYTE) j;
# }
# }
if (defined $IV) {
# my @block = unpack 'C'x(length $IV), $IV;
# for $i (0..$cipher->{blockLen}/8-1) {
# $cipher->{IV}[$i] = $block[$i];
# }
$cipher->{IV} = [ unpack 'C'x(length $IV), $IV ]
}
#
# return TRUE;
#}
$_[0] = $cipher;
return TRUE;
}
#int blockEncrypt(cipherInstance *cipher,
# keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer)
#{
# int i, j, t, numBlocks;
# word8 block[4][MAXBC];
sub blockEncrypt($$$$$) {
my ($cipher, $key, $input, $inputLen, $outBuffer) = @_;
my ($i,$j,$t,$numBlocks,@block);
#
#
# /* check parameter consistency: */
# if (key == NULL ||
# key->direction != DIR_ENCRYPT ||
# (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) {
# return BAD_KEY_MAT;
# }
if (not defined $key or $key->{direction} != DIR_ENCRYPT or
($key->{keyLen} != 128 and $key->{keyLen} != 192 and $key->{keyLen} != 256)) {
die "BAD_KEY_MAT"
}
# if (cipher == NULL ||
# (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC && cipher->mode != MODE_CFB1) ||
# (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) {
# return BAD_CIPHER_STATE;
# }
if (not defined $cipher or ($cipher->{mode} != MODE_ECB and $cipher->{mode} != MODE_CBC and $cipher->{mode} != MODE_CFB1) or
($cipher->{blockLen} != 128 and $cipher->{blockLen} != 192 and $cipher->{blockLen} != 256)) {
die "BAD_CIPHER_STATE";
}
#
#
# numBlocks = inputLen/cipher->blockLen;
$numBlocks = $inputLen/$cipher->{blockLen};
#
# switch (cipher->mode) {
# case MODE_ECB:
# for (i = 0; i < numBlocks; i++) {
# for (j = 0; j < cipher->blockLen/32; j++) {
# for(t = 0; t < 4; t++)
# /* parse input stream into rectangular array */
# block[t][j] = input[4*j+t] & 0xFF;
# }
# rijndaelEncrypt (block, key->keyLen, cipher->blockLen, key->keySched);
# for (j = 0; j < cipher->blockLen/32; j++) {
# /* parse rectangular array into output ciphertext bytes */
# for(t = 0; t < 4; t++)
# outBuffer[4*j+t] = (BYTE) block[t][j];
# }
# }
# break;
if ($cipher->{mode} == MODE_ECB) {
for $i (0..$numBlocks-1) {
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$block[$t][$j] = $input->[4*$j+$t] & 0xFF;
}
}
rijndaelEncrypt(@block, $key->{keyLen}, $cipher->{blockLen}, $key->{keySched});
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$outBuffer->[4*$j+$t] = $block[$t][$j];
}
}
}
}
#
# case MODE_CBC:
# for (j = 0; j < cipher->blockLen/32; j++) {
# for(t = 0; t < 4; t++)
# /* parse initial value into rectangular array */
# block[t][j] = cipher->IV[t+4*j] & 0xFF;
# }
# for (i = 0; i < numBlocks; i++) {
# for (j = 0; j < cipher->blockLen/32; j++) {
# for(t = 0; t < 4; t++)
# /* parse input stream into rectangular array and exor with
# IV or the previous ciphertext */
# block[t][j] ^= input[4*j+t] & 0xFF;
# }
# rijndaelEncrypt (block, key->keyLen, cipher->blockLen, key->keySched);
# for (j = 0; j < cipher->blockLen/32; j++) {
# /* parse rectangular array into output ciphertext bytes */
# for(t = 0; t < 4; t++)
# outBuffer[4*j+t] = (BYTE) block[t][j];
# }
# }
# break;
elsif ($cipher->{mode} == MODE_CBC) {
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$block[$t][$j] = $cipher->{IV}[$t+4*$j] & 0xFF
}
}
for $i (0..$numBlocks-1) {
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$block[$t][$j] ^= $input->[4*$j+$t] & 0xFF;
}
}
rijndaelEncrypt(@block,$key->{keyLen},$cipher->{blockLen}, $key->{keySched});
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$outBuffer->[4*$j+$t] = $block[$t][$j];
}
}
}
}
#
# default: return BAD_CIPHER_STATE;
# }
else { die "BAD_CIPHER_STATE" }
#
# return numBlocks*cipher->blockLen;
#}
# @_ = ($cipher, $key, $input, $inputLen, $outBuffer);
$_[4] = $outBuffer;
return $numBlocks * $cipher->{blockLen};
}
#int blockDecrypt(cipherInstance *cipher,
# keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer)
#{
# int i, j, t, numBlocks;
# word8 block[4][MAXBC];
sub blockDecrypt($$$$$) {
my ($cipher, $key, $input, $inputLen, $outBuffer) = @_;
my ($i,$j,$t,$numBlocks,@block);
#
# if (cipher == NULL ||
# key == NULL ||
# key->direction == DIR_ENCRYPT ||
# cipher->blockLen != key->blockLen) {
# return BAD_CIPHER_STATE;
# }
if (not defined $cipher or not defined $key or $key->{direction} == DIR_ENCRYPT or $cipher->{blockLen} != $key->{blockLen}) {
die "BAD_CIPHER_STATE";
}
#
# /* check parameter consistency: */
# if (key == NULL ||
# key->direction != DIR_DECRYPT ||
# (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) {
# return BAD_KEY_MAT;
# }
if (not defined $key or $key->{direction} != DIR_DECRYPT or
($key->{keyLen} != 128 and $key->{keyLen} != 192 and $key->{keyLen} != 256)) {
die "BAD_KEY_MAT";
}
# if (cipher == NULL ||
# (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC && cipher->mode != MODE_CFB1) ||
# (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) {
# return BAD_CIPHER_STATE;
# }
if (not defined $cipher or ($cipher->{mode} != MODE_ECB and $cipher->{mode} != MODE_CBC and $cipher->{mode} != MODE_CFB1) or
($cipher->{blockLen} != 128 and $cipher->{blockLen} != 192 and $cipher->{blockLen} != 256)) {
die "BAD_CIPHER_STATE";
}
#
#
# numBlocks = inputLen/cipher->blockLen;
$numBlocks = $inputLen / $cipher->{blockLen};
#
# switch (cipher->mode) {
# case MODE_ECB:
# for (i = 0; i < numBlocks; i++) {
# for (j = 0; j < cipher->blockLen/32; j++) {
# for(t = 0; t < 4; t++)
# /* parse input stream into rectangular array */
# block[t][j] = input[4*j+t] & 0xFF;
# }
# rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched);
# for (j = 0; j < cipher->blockLen/32; j++) {
# /* parse rectangular array into output ciphertext bytes */
# for(t = 0; t < 4; t++)
# outBuffer[4*j+t] = (BYTE) block[t][j];
# }
# }
# break;
if ($cipher->{mode} == MODE_ECB) {
for $i (0..$numBlocks-1) {
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$block[$t][$j] = $input->[4*$j+$t] & 0xFF;
}
}
rijndaelDecrypt(@block, $key->{keyLen}, $cipher->{blockLen}, $key->{keySched});
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$outBuffer->[4*$j+$t] = $block[$t][$j];
}
}
}
}
#
# case MODE_CBC:
# /* first block */
# for (j = 0; j < cipher->blockLen/32; j++) {
# for(t = 0; t < 4; t++)
# /* parse input stream into rectangular array */
# block[t][j] = input[4*j+t] & 0xFF;
# }
elsif ($cipher->{mode} == MODE_CBC) {
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$block[$t][$j] = $input->[$t+4*$j] & 0xFF
}
}
# rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched);
rijndaelDecrypt(@block, $key->{keyLen}, $cipher->{blockLen}, $key->{keySched});
#
# for (j = 0; j < cipher->blockLen/32; j++) {
# /* exor the IV and parse rectangular array into output ciphertext bytes */
# for(t = 0; t < 4; t++)
# outBuffer[4*j+t] = (BYTE) (block[t][j] ^ cipher->IV[t+4*j]);
# }
for $j (0.. $cipher->{blockLen}/32-1) {
for $t (0..3) {
$outBuffer->[4*$j+$t] = $block[$t][$j] ^ $cipher->{IV}[$t+4*$j]
}
}
#
# /* next blocks */
# for (i = 1; i < numBlocks; i++) {
# for (j = 0; j < cipher->blockLen/32; j++) {
# for(t = 0; t < 4; t++)
# /* parse input stream into rectangular array */
# block[t][j] = input[cipher->blockLen/8+4*j+t] & 0xFF;
# }
# rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched);
#
# for (j = 0; j < cipher->blockLen/32; j++) {
# /* exor previous ciphertext block and parse rectangular array
# into output ciphertext bytes */
# for(t = 0; t < 4; t++)
# outBuffer[cipher->blockLen/8+4*j+t] = (BYTE) (block[t][j] ^
# input[4*j+t-4*cipher->blockLen/32]);
# }
# }
# break;
for $i (1..$numBlocks-1) {
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$block[$t][$j] ^= $input->[$cipher->{blockLen}/8+4*$j+$t] & 0xFF;
}
}
rijndaelDecrypt(@block,$key->{keyLen},$cipher->{blockLen}, $key->{keySched});
for $j (0..$cipher->{blockLen}/32-1) {
for $t (0..3) {
$outBuffer->[$cipher->{blockLen}/8+4*$j+$t] =
$block[$t][$j] ^ $input->[4*$j+$t-4*$cipher->{blockLen}/32];
}
}
}
}
Rijndael_PP.pm view on Meta::CPAN
eval {
my $res = blockEncrypt($cipherInst, $keyInst, \@block, $blocksize, $tmp);
};
die $@ if $@;
$out .= pack 'C'x($blocksize/8), @$tmp;
}
return unless defined $out;
$out;
}
sub rijndael_decrypt($$$;$$) {
my ($key, $mode, $data, $keysize, $blocksize) = @_;
$keysize = 128 unless defined $keysize;
$blocksize = 128 unless defined $blocksize;
my $keyInst = { blockLen => $blocksize };
if (length $key < ($keysize/4)) {
$key .= "0" x ($keysize/4 - length $key);
warn "rijndael_decrypt: padded key to keysize ($keysize)\n";
} elsif (length $key > $keysize/4) {
$key = substr $key, 0, $keysize/4;
warn "rijndael_decrypt: truncate key to keysize ($keysize)\n";
}
my $res;
eval { makeKey($keyInst, DIR_DECRYPT, $keysize, $key) };
die $@ if $@;
my $cipherInst = { blockLen => $blocksize };
my $IV = "\0" x ($blocksize/8);
eval { cipherInit($cipherInst, $mode, $IV) };
die $@ if $@;
my $out;
my $i;
for ($i=0; $i < length($data) / ($blocksize/8); $i++) {
my $tmp = [];
my @block = unpack 'C'x($blocksize/8), substr($data,$i*$blocksize/8,$blocksize/8);
eval {
blockDecrypt($cipherInst, $keyInst, \@block, $blocksize, $tmp)
};
die $@ if $@;
$out .= pack 'C'x($blocksize/8), @$tmp;
}
return unless defined $out;
$out;
}
####################################################
#
# Interface for Crypt::CBC
#
####################################################
# return keysize in bytes
sub keysize {
my $self = shift;
if (defined $self and ref $self and defined $self->{keysize}) {
return $self->{keysize}/8
}
return $DEFAULT_KEYSIZE/8
}
# return blocksize in bytes
sub blocksize {
my $self = shift;
if (defined $self and ref $self and defined $self->{blocksize}) {
return $self->{blocksize}/8
}
return $DEFAULT_BLOCKSIZE/8
}
1; # make require happy :-)
__END__
=head1 NAME
Crypt::Rijndael_PP - Perl implementation of Rijndael
=head1 DISCLAIMER
This is a pure perl implementation of the new AES Rijndael.
You want to use C<Crypt::Rijndael> where available. This implementation
is really slow, but I am working on it.
=head1 SYNOPSIS
# Functional style
use Crypt::Rijndael_PP ':all';
$key = '1234567890ABCDEF' x 4; # 256bit hex number
# keysize = 256bit, blocksize = 128bit
$c_txt = rijndael_encrypt($key, MODE_CBC, $data, 256, 128);
$p_txt = rijndael_decrypt($key, MODE_CBC, $c_txt, 256, 128);
# OO style
# same interface as Crypt::Rijndael
use Crypt::Rijndael_PP;
$cipher = Crypt::Rijndael_PP->new( pack('H*', $key), MODE_CBC );
$c_txt = $cipher->encrypt($data);
$p_txt = $cipher->decrypt($c_txt);
=head1 DESCRIPTION
This modules shares the OO style interface with C<Crypt::Rijndael>
from Rafael R. Sevilla.
=over 4
=item
Supported modes: Electronic CodeBook (MODE_ECB) and Cipher Block Chaining
(MODE_CBC). Please use C<Crypt::CBC> for CBC-Mode, as my CBC is not compatible
with neither C<Crypt::CBC> nor C<Crypt::Rijndael> and it is subject to change
in the near future. When using C<Crypt::CBC> this module is 100% compatible to
C<Crypt::Rijndael> and you can decrypt and encrypt your data with both modules!
=item
Supported keysizes: 128, 192 and 256 (default)
=item
Supported blocksizes: 128 (default), 192 and 256
=back
If the size of the key does not match the given
keysize then the key is padded with "0" (hex) or
truncated to the right size.
The last data block is padded with "\0" if it does not match
a multiple of the blocksize.
Warnings a raised in both cases.
=head1 EXAMPLES
Using C<Crypt::CBC>
use Crypt::CBC;
my $key = 'my secret key';
my $input = 'The answer is 42.';
my $cipher = new Crypt::CBC($key,'Rijndael_PP');
my $ciphertext = $cipher->encrypt($input);
my $plaintext = $cipher->decrypt($ciphertext);
# - or -
#!/usr/local/bin/perl -w
#
# Usage: r.pl e "my secret key" < in > out
#
use strict;
use Crypt::CBC;
die "Usage: $0 mode([ed]) key\n" unless @ARGV == 2;
my $cipher = new Crypt::CBC($ARGV[1],'Rijndael_PP');
$cipher->start($ARGV[0]);
my $buffer;
while( read(STDIN, $buffer, 1024) ) {
print $cipher->crypt($buffer);
}
print $cipher->finish;
=head1 LIMITATIONS
This implementation is really slow. I'm trying to tweak the
performance in coming releases.
CBC-Mode is not yet compatible to C<Crypt::Rijndael>. But you are
advised to use C<Crypt::CBC> for this mode anyway.
=head1 SEE ALSO
L<Crypt::Rijndael>
L<Crypt::CBC>
L<http://csrc.nist.gov/encryption/aes/>
=head1 COPYRIGHT
This library is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
Copyright 2001 Christian Lackas
Copyright 2000 Vincent Rijmen and Joan Daemen
=head1 AUTHORS
The original algorithm was developed by Vincent Rijmen and Joan Daemen.
This release was made by Christian Lackas <delta@lackas.net>.
http://www.lackas.net/. It is based on the reference implementation
for the AES contest. At present I am working on a faster version.
=cut
( run in 0.468 second using v1.01-cache-2.11-cpan-e1769b4cff6 )