Crypt-Loki97
view release on metacpan or search on metacpan
XSLoader::load('Crypt::Loki97', $VERSION);
# Preloaded methods go here.
1;
__END__
=head1 NAME
Crypt::Loki97 - Crypt::CBC compliant block cipher
=head1 SYNOPSIS
use Crypt::Loki97;
$cipher = new Crypt::Loki97 $key;
$ciphertext = $cipher->encrypt($plaintext);
$plaintext = $cipher->decrypt($ciphertext);
=head1 DESCRIPTION
Loki97 is 128-bit block cipher that accepts a variable-length key. It
was designed by Lawrie Brown, Josef Pieprzyk, and Jennifer Seberry.
The default key length in this implementation is 128 bits.
Loki97 was one of the 15 candidates for the AES.
This module supports the Crypt::CBC interface, with the following
functions.
=head2 Functions
=over
=item B<blocksize>
Returns the size (in bytes) of the block (16, in this case).
print "Decryption OK\n" if ($plaintext1 eq $plaintext2);
=head1 EXAMPLE 2
#!/usr/local/bin/perl
use diagnostics;
use strict;
use warnings;
use Crypt::CBC; # CBC automatically loads Loki97 for us
# when using Crypt::CBC, key may be of ANY length
my $key = "0123456789abcdef";
# IV must be exactly 16 bytes long
my $IV = pack "H32", 0;
my $cipher = Crypt::CBC->new({'key' => $key,
'cipher' => 'Loki97',
'iv' => $IV,
'regenerate_key' => 1,
'padding' => 'standard',
'prepend_iv' => 0
});
# when using Crypt::CBC, plaintext may be of ANY length
my $plaintext1 = "This is a test";
my $ciphertext = $cipher->encrypt($plaintext1);
my $plaintext2 = $cipher->decrypt($ciphertext);
print "Decryption OK\n" if ($plaintext1 eq $plaintext2);
=head1 MORE EXAMPLES
See B<Crypt::CBC> for more examples using CBC mode. See also the
"examples" and "t" directories for some more examples.
=head1 SEE ALSO
B<Crypt::Khazad>, B<Crypt::Misty1>, B<Crypt::Anubis>,
B<Crypt::Noekeon>, B<Crypt::Skipjack>, B<Crypt::Camellia>,
B<Crypt::Square>, B<Crypt::Rainbow>, and B<Crypt::Shark>.
=head1 COPYRIGHT AND LICENSE
/* Includes: Standard include files */
#include <stdio.h>
#include <string.h>
/* Defines: AES */
#define DIR_ENCRYPT 0 /* Are we encrypting? */
#define DIR_DECRYPT 1 /* Are we decrypting? */
#define MODE_ECB 1 /* Are we ciphering in ECB mode? */
#define MODE_CBC 2 /* Are we ciphering in CBC mode? */
#define MODE_CFB1 3 /* Are we ciphering in 1-bit CFB mode? */
#define S_TRUE 1
#define S_FALSE 0
/* 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 */
BYTE direction; /* Key used for encrypting or decrypting? */
int keyLen; /* Length of the key */
unsigned char keyMaterial[MAX_KEY_SIZE+1]; /* Raw key data in ASCII,
e.g., user input or KAT values */
/* The following parameters are algorithm dependent */
ULONG64 SK[NUM_SUBKEYS]; /* LOKI97 subkeys for this key */
} keyInstance;
/* The structure for cipher information */
typedef struct cipherInstance {
BYTE mode; /* MODE_ECB, MODE_CBC, or MODE_CFB1 */
BYTE IV[MAX_IV_SIZE]; /* A possible Initialization Vector for
ciphering */
/* Add any algorithm specific parameters needed here */
ULONG64 IVL, IVR; /* IV packed into 64-bit L & R halves */
int blockSize; /* Sample: Handles non-128 bit block sizes
(if available) */
} cipherInstance;
/* Function protoypes */
* value of P is a 64-bit wide (long) mask of the permuted input value.
*/
static ULONG64 P[0x100];
/* Flag specifying whether once-off init of S1, S2 and P has been done */
static int init_done = S_FALSE;
/* prototypes for local utility functions */
static int enECB(cipherInstance *cipher, keyInstance *key, BYTE *input,
int inputLen, BYTE *outBuffer);
static int enCBC(cipherInstance *cipher, keyInstance *key, BYTE *input,
int inputLen, BYTE *outBuffer);
static int enCFB1(cipherInstance *cipher, keyInstance *key, BYTE *input,
int inputLen, BYTE *outBuffer);
static int deECB(cipherInstance *cipher, keyInstance *key, BYTE *input,
int inputLen, BYTE *outBuffer);
static int deCBC(cipherInstance *cipher, keyInstance *key, BYTE *input,
int inputLen, BYTE *outBuffer);
static int deCFB1(cipherInstance *cipher, keyInstance *key, BYTE *input,
int inputLen, BYTE *outBuffer);
static ULONG64 f (ULONG64 A, ULONG64 B) ;
static ULONG64 add64(ULONG64 a, ULONG64 b) ;
static ULONG64 sub64(ULONG64 a, ULONG64 b) ;
static int exp3 (int b, int g, int n) ;
static int mult (int a, int b, int g, int n) ;
static ULONG64 byteToULONG64(BYTE *inp) ;
static BYTE *ULONG64ToBYTE(BYTE *buf, ULONG64 I) ;
input = cipher->IV;
cipher->IVL = byteToULONG64(input); input += 8;
cipher->IVR = byteToULONG64(input); input += 8;
} else { /* no IV, so set to 0 */
memset(cipher->IV,0,sizeof(cipher->IV));
cipher->IVL.l = cipher->IVL.r = cipher->IVR.l = cipher->IVR.r = 0L;
}
cipher->blockSize = BLOCK_SIZE*8; /* BLOCK_SIZE in bits */
/* decide correct return value */
if ((mode == MODE_ECB)||(mode == MODE_CBC)||(mode == MODE_CFB1))
return S_TRUE;
else
return BAD_CIPHER_MODE;
}
/*
* Returns residue of base b to power 3 mod g in GF(2^n).
*
{
/* do some basic sanity checks on params */
if (!init_done) return BAD_CIPHER_STATE;
if (cipher == NULL) return BAD_CIPHER_STATE;
if (key == NULL) return BAD_KEY_INSTANCE;
if (key->direction != DIR_ENCRYPT) return BAD_KEY_DIR;
/* now call appropriate mode encrypt routine */
if (cipher->mode == MODE_ECB)
return enECB(cipher, key, input, inputLen, outBuffer);
else if (cipher->mode == MODE_CBC)
return enCBC(cipher, key, input, inputLen, outBuffer);
else if (cipher->mode == MODE_CFB1)
return enCFB1(cipher, key, input, inputLen, outBuffer);
else
return BAD_CIPHER_MODE;
}
/*
* encrypt blocks in ECB mode
*/
/* unpack resulting L & R into output - undoing last swap */
ULONG64ToBYTE(outBuffer, R); outBuffer += 8;
ULONG64ToBYTE(outBuffer, L); outBuffer += 8;
}
return S_TRUE;
}
/*
* encrypt blocks in CBC mode
*/
static int enCBC(cipherInstance *cipher, keyInstance *key, BYTE *input,
int inputLen, BYTE *outBuffer)
{
int i,j,k; /* assorted loop counters */
int blocks = inputLen / (BLOCK_SIZE*8); /* compute # input blocks */
ULONG64 L, R; /* left and right data blocks */
ULONG64 nR, f_out;
/* do some basic sanity checks on params */
if (inputLen % (BLOCK_SIZE*8) != 0) return BAD_CIPHER_INPUT;
for (j = 0; j < blocks; j++) {
/* pack input block into L and R */
L = byteToULONG64(input); input += 8;
R = byteToULONG64(input); input += 8;
/* XOR with IV value */
L.l ^= cipher->IVL.l; L.r ^= cipher->IVL.r;
R.l ^= cipher->IVR.l; R.r ^= cipher->IVR.r;
if (debuglevel) fprintf(stderr,"%s: enCBC(%08lx%08lx%08lx%08lx) ", NAME, L.l, L.r, R.l, R.r);
if (debuglevel > 1) fprintf(stderr,"\n");
/* compute all rounds for this 1 block */
k = 0;
for (i = 0; i < ROUNDS; i++) {
nR = add64(R, key->SK[k++]); /* nR = R+SK(k) */
f_out = f(nR, key->SK[k++]); /* f = f(nR,SK(k+1)) */
nR = add64(nR, key->SK[k++]); /* nR = nR+SK(k+2) */
R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */
L = nR; /* L = nR */
{
/* do some basic sanity checks on params */
if (!init_done) return BAD_CIPHER_STATE;
if (cipher == NULL) return BAD_CIPHER_STATE;
if (key == NULL) return BAD_KEY_INSTANCE;
if (key->direction != DIR_DECRYPT) return BAD_KEY_DIR;
/* now call appropriate mode decrypt routine */
if (cipher->mode == MODE_ECB)
return deECB(cipher, key, input, inputLen, outBuffer);
else if (cipher->mode == MODE_CBC)
return deCBC(cipher, key, input, inputLen, outBuffer);
else if (cipher->mode == MODE_CFB1)
return deCFB1(cipher, key, input, inputLen, outBuffer);
else
return BAD_CIPHER_MODE;
}
/*
* decrypt blocks in ECB mode
*/
/* unpack resulting L & R into output - undoing last swap */
ULONG64ToBYTE(outBuffer, R); outBuffer += 8;
ULONG64ToBYTE(outBuffer, L); outBuffer += 8;
}
return S_TRUE;
}
/*
* Dncrypt blocks in CBC mode
*/
static int deCBC(cipherInstance *cipher, keyInstance *key, BYTE *input,
int inputLen, BYTE *outBuffer)
{
int i,j,k; /* assorted loop counters */
int blocks = inputLen / (BLOCK_SIZE*8); /* compute # input blocks */
ULONG64 L, R; /* left and right data blocks */
ULONG64 newIVL, newIVR; /* next IV L & R halves */
ULONG64 nR, f_out;
/* do some basic sanity checks on params */
if (inputLen % (BLOCK_SIZE*8) != 0) return BAD_CIPHER_INPUT;
/* now loop over all blocks of input */
for (j = 0; j < blocks; j++) {
/* pack input block into L and R */
L = byteToULONG64(input); input += 8;
R = byteToULONG64(input); input += 8;
/* save new IV value */
newIVL = L; newIVR = R;
if (debuglevel) fprintf(stderr,"%s: deCBC(%08lx%08lx%08lx%08lx) ", NAME, L.l, L.r, R.l, R.r);
if (debuglevel > 1) fprintf(stderr,"\n");
/* compute all rounds for this 1 block */
k = NUM_SUBKEYS - 1;
for (i = 0; i < ROUNDS; i++) {
nR = sub64(R, key->SK[k--]); /* nR = R+SK(k) */
f_out = f(nR, key->SK[k--]); /* f = f(nR,SK(k+1)) */
nR = sub64(nR, key->SK[k--]); /* nR = nR+SK(k+2) */
R.l = L.l ^ f_out.l; R.r = L.r ^ f_out.r; /* R = L XOR f */
L = nR; /* L = nR */
examples/cbc-mode view on Meta::CPAN
#!/usr/local/bin/perl
use diagnostics;
use strict;
use warnings;
use Crypt::CBC; # CBC automatically loads Loki97 for us
my $key = pack "H32", "00112233445566778899aabbccddeeff";
my $IV = pack "H32", "00112233445566778899aabbccddeeff";
my $cipher = Crypt::CBC->new({'key' => $key,
'cipher' => 'Loki97',
'iv' => $IV,
'regenerate_key' => 1,
'padding' => 'standard',
'prepend_iv' => 0
});
my $plaintext1 = pack "H32", "0123456789abcdeffedcba9876543210";
print "plaintext1 : ", unpack("H*", $plaintext1), "\n";
examples/fileenc view on Meta::CPAN
#!/usr/local/bin/perl
use diagnostics;
use strict;
use warnings;
use Getopt::Long;
use Crypt::CBC; # CBC automatically loads Loki97 for us
my ($encrypt, $decrypt, $help);
GetOptions("encrypt" => \$encrypt, "decrypt" => \$decrypt,
"help" => \$help);
sub usage
{
print "USAGE:\n";
print " $0 --encrypt file1 > outputfile\n";
print " $0 --decrypt file1 > outputfile\n\n";
examples/fileenc view on Meta::CPAN
&usage() if (!$encrypt and !$decrypt);
&usage() if ($help);
my $key = &get_input("password");
# For better security, IV must be randomly
# generated AND must be used ONLY ONCE!
# So, this example is *very* weak!
my $IV = pack "H32", "000102030405060708090a0b0c0d0e0f";
my $cipher = Crypt::CBC->new({'key' => $key,
'cipher' => 'Loki97',
'iv' => $IV,
'regenerate_key' => 1,
'padding' => 'standard',
'prepend_iv' => 0
});
local $/ = undef; # slurp whole file
chomp $ARGV[0];
open INFILE, $ARGV[0];
examples/pin-generator view on Meta::CPAN
#!/usr/local/bin/perl
use diagnostics;
use strict;
use warnings;
use Crypt::CBC;
use MIME::Base64;
sub get_input
{
my ($message) = @_;
local $| = 1;
local *TTY;
open TTY,"/dev/tty";
my ($tkey1, $tkey2);
system "stty -echo </dev/tty";
examples/pin-generator view on Meta::CPAN
} until $tkey1 eq $tkey2;
system "stty echo </dev/tty";
close TTY;
return $tkey1;
}
my $key = &get_input("username");
my $IV = pack "H32", "000102030405060708090a0b0c0d0e0f";
my $cipher = Crypt::CBC->new({'key' => $key,
'cipher' => 'Loki97',
'iv' => $IV,
'regenerate_key' => 1,
'padding' => 'standard',
'prepend_iv' => 0
});
my $ciphertext = $cipher->encrypt($key);
print "Your password is\n", encode_base64($ciphertext, ""), "\n";
( run in 1.587 second using v1.01-cache-2.11-cpan-e1769b4cff6 )