Crypt-Loki97

 view release on metacpan or  search on metacpan

Loki97.pm  view on Meta::CPAN

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).

Loki97.pm  view on Meta::CPAN


    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

_loki97.c  view on Meta::CPAN


/* 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 */

_loki97.c  view on Meta::CPAN

      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  */

_loki97.c  view on Meta::CPAN

 *     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) ;

_loki97.c  view on Meta::CPAN

	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).
 *

_loki97.c  view on Meta::CPAN

{
    /*  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
 */

_loki97.c  view on Meta::CPAN


        /*  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;

_loki97.c  view on Meta::CPAN

    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 */

_loki97.c  view on Meta::CPAN

{
    /*  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
 */

_loki97.c  view on Meta::CPAN


        /*  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;

_loki97.c  view on Meta::CPAN

    /* 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 0.612 second using v1.01-cache-2.11-cpan-e1769b4cff6 )