⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aesxam.c

📁 Arithmetic for integers of almost rijndael for C and C++. Developed for linux
💻 C
字号:
/*
 -------------------------------------------------------------------------
 Copyright (c) 2001, Dr Brian Gladman <brg@gladman.uk.net>, Worcester, UK.
 All rights reserved.

 LICENSE TERMS

 The free distribution and use of this software in both source and binary 
 form is allowed (with or without changes) provided that:

   1. distributions of this source code include the above copyright 
      notice, this list of conditions and the following disclaimer;

   2. distributions in binary form include the above copyright
      notice, this list of conditions and the following disclaimer
      in the documentation and/or other associated materials;

   3. the copyright holder's name is not used to endorse products 
      built using this software without specific written permission. 

 DISCLAIMER

 This software is provided 'as is' with no explcit or implied warranties
 in respect of any properties, including, but not limited to, correctness 
 and fitness for purpose.
 -------------------------------------------------------------------------
 Issue Date: 15/01/2002
*/

//  Example of the use of the AES (Rijndael) algorithm for file
//  encryption.  Note that this is an example application, it is
//  not intended for real use.  The Command line is:
//
//  aesxam input_file_name output_file_name [D|E] hexadecimalkey
//
//  where E gives encryption and D decryption of the input file
//  into the output file using the given hexadecimal key string
//  The later is a hexadecimal sequence of 32, 48 or 64 digits
//  Examples to encrypt or decrypt aes.c into aes.enc are:
//
//  aesxam file.c file.enc E 0123456789abcdeffedcba9876543210
//
//  aesxam file.enc file2.c D 0123456789abcdeffedcba9876543210
//
//  which should return a file 'file2.c' identical to 'file.c'

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <memory.h>

#include "aes.h"

#define BLOCK_LEN   16
#define READ_ERROR  -7
#define WRITE_ERROR -8

//  A Pseudo Random Number Generator (PRNG) used for the
//  Initialisation Vector. The PRNG is George Marsaglia's
//  Multiply-With-Carry (MWC) PRNG that concatenates two
//  16-bit MWC generators:
//      x(n)=36969 * x(n-1) + carry mod 2^16
//      y(n)=18000 * y(n-1) + carry mod 2^16
//  to produce a combined PRNG with a period of about 2^60.
//  The Pentium cycle counter is used to initialise it. This
//  is crude but the IV does not really need to be secret.

void cycles(volatile unsigned __int64 *rtn)    
{   
#if defined(_MSC_VER)
    __asm   // read the Pentium Time Stamp Counter
    {   cpuid
        rdtsc
        mov     ecx,rtn
        mov     [ecx],eax
        mov     [ecx+4],edx
        cpuid
    }
#else
#include <time.h>
  time_t tt;
  tt     = time(NULL);
  rtn[0] = tt;
  rtn[1] = tt & -36969l;
  return;
#endif
}

#define RAND(a,b) (((a = 36969 * (a & 65535) + (a >> 16)) << 16) + \
                    (b = 18000 * (b & 65535) + (b >> 16))  )

void fillrand(char *buf, const int len)
{   static unsigned long a[2], mt = 1, count = 4;
    static char          r[4];
    int                  i;

    if(mt) { mt = 0; cycles((unsigned __int64 *)a); }

    for(i = 0; i < len; ++i)
    {
        if(count == 4)
        {
            *(unsigned long*)r = RAND(a[0], a[1]);
            count = 0;
        }

        buf[i] = r[count++];
    }
}

int encfile(FILE *fin, FILE *fout, aes_ctx *ctx, const char* ifn, const char* ofn)
{   char            buf[BLOCK_LEN], dbuf[2 * BLOCK_LEN];
    fpos_t          flen;
    unsigned long   i, l, rlen;

    fillrand(dbuf, BLOCK_LEN);              // set a random IV
    fseek(fin, 0, SEEK_END);                // get the file length
#ifndef LINUX
    fgetpos(fin, &flen); rlen = (unsigned long)flen;
#else
    fgetpos(fin, &flen); rlen = (unsigned long)flen.__pos;
#endif
    fseek(fin, 0, SEEK_SET);                // reset to start

    if(rlen < BLOCK_LEN)                    // file length of less than one block
    {
        l = (unsigned long) fread(dbuf + BLOCK_LEN, 1, BLOCK_LEN, fin);
        rlen -= l;
        if(rlen)                            // read bytes and verify length
            return READ_ERROR;

        for(i = 0; i < l; ++i)              // xor file bytes with IV bytes
            dbuf[i + BLOCK_LEN] ^= dbuf[i];

        aes_enc_blk(dbuf, dbuf, ctx);   // encrypt lower half of buffer

        // encrypt bytes from position l to position l + BLOCK_LEN - the
        // file bytes plus a second encryption of some of the IV bytes

        aes_enc_blk(dbuf + l, dbuf + l, ctx);

        l += BLOCK_LEN;                     // write the encrypted bytes
        if(fwrite(dbuf, 1, l, fout) != l)   // (IV + file bytes)
            return WRITE_ERROR;
    }
    else
    {
        aes_enc_blk(dbuf, buf, ctx);    // encrypt and write IV block
        if(fwrite(buf, 1, BLOCK_LEN, fout) != BLOCK_LEN)
            return WRITE_ERROR;

        while(!feof(fin) && rlen)
        {                                   // read a block and reduce remaining
            l = (unsigned long)fread(buf, 1, BLOCK_LEN, fin);
            rlen -= l;                      // byte count

            if(l != BLOCK_LEN && rlen)      // verify length of read (only
                return READ_ERROR;          // last read can be part block)

            for(i = 0; i < BLOCK_LEN; ++i)  // do CBC chaining prior to
                buf[i] ^= dbuf[i];          // encryption

            aes_enc_blk(buf, dbuf, ctx);

            if(rlen < BLOCK_LEN)            // if only a part block remains
            {
                if(rlen && fread(dbuf + BLOCK_LEN, 1, BLOCK_LEN, fin) != rlen)
                    return READ_ERROR;      // read it into top half of dbuf[]

                // encrypt from position rlen to rlen + BLOCK_LEN - the last
                // file bytes plus a part of the last encrypted block - this
                // is called 'ciphertext stealing'

                for(i = 0; i < rlen; ++i)   // do CBC chaining prior to
                    dbuf[i + BLOCK_LEN] ^= dbuf[i];     // encryption

                aes_enc_blk(dbuf + rlen, dbuf + rlen, ctx);
                l = rlen + BLOCK_LEN;       // set final buffer length
            }

            if(fwrite(dbuf, 1, l, fout) != l)
                return WRITE_ERROR;         // write encrypted block
        }
    }

    return 0;
}

int decfile(FILE *fin, FILE *fout, aes_ctx *ctx, const char* ifn, const char* ofn)
{   char            buf1[BLOCK_LEN], buf2[BLOCK_LEN], dbuf[2 * BLOCK_LEN];
    char            *b1, *b2, *bt;
    fpos_t          flen;
    unsigned long   i, l, rlen;

    fseek(fin, 0, SEEK_END);
#ifndef LINUX
    fgetpos(fin, &flen); rlen = (unsigned long)flen;
#else
    fgetpos(fin, &flen); rlen = (unsigned long)flen.__pos;
#endif
    fseek(fin, 0, SEEK_SET);

    if(rlen < 2 * BLOCK_LEN)                // original length of less than one block
    {
        l = (unsigned long)fread(dbuf, 1, 2 * BLOCK_LEN, fin);
        rlen -= l;
        if(rlen)                            // read bytes in and verify length
            return READ_ERROR;              // (encrypted IV + file bytes)

        l -= BLOCK_LEN;                     // original file length

        // decrypt from position l to position l + BLOCK_LEN
        aes_dec_blk(dbuf + l, dbuf + l, ctx);
        aes_dec_blk(dbuf, dbuf, ctx);   // decrypt lower half of buffer

        for(i = 0; i < l; ++i)              // remove IV xor
            dbuf[i] ^= dbuf[i + BLOCK_LEN];

        if(fwrite(dbuf, 1, l, fout) != l)   // write out decrytped bytes
            return WRITE_ERROR;
    }
    else
    {   // we need two input buffers because we have to keep the previous
        // ciphertext block - the pointers b1 and b2 are swapped once per
        // loop so that b2 points to new ciphertext block and b1 to the
        // last ciphertext block

        rlen -= BLOCK_LEN; b1 = buf1; b2 = buf2;

        if(fread(b1, 1, BLOCK_LEN, fin) != BLOCK_LEN)
            return READ_ERROR;              // input the IV block

        aes_dec_blk(b1, b1, ctx);       // and decrypt it

        while(!feof(fin) && rlen)
        {                                   // read a block and reduce remaining
            l = (unsigned long)fread(b2, 1, BLOCK_LEN, fin);
            rlen -= l;                      // byte count

            if(l != BLOCK_LEN && rlen)      // verify length of read (only
                return READ_ERROR;          // last read can be part block)

            if(rlen < BLOCK_LEN)            // if only a part block remains
            {
                for(i = 0; i < BLOCK_LEN; ++i)  // move bytes from last but
                    dbuf[i] = b2[i];        // one block into lower half of dbuf

                if(rlen && fread(dbuf + BLOCK_LEN, 1, BLOCK_LEN, fin) != rlen)
                    return READ_ERROR;      // read remaining bytes into upper
                                            // half of dbuf

                // decrypt from position rlen to rlen + BLOCK_LEN - that is
                // the file bytes plus a part of the last but one encrypted
                // block

                aes_dec_blk(dbuf + rlen, dbuf + rlen, ctx);

                for(i = 0; i < rlen; ++i)   // unchain the CBC using the
                    dbuf[i + BLOCK_LEN] ^= dbuf[i];   // last ciphertext block

                // set output buffer and correct final length
                b2 = dbuf; l = rlen + BLOCK_LEN;
            }

            aes_dec_blk(b2, dbuf, ctx); // decrypt the input buffer

            for(i = 0; i < BLOCK_LEN; ++i)  // unchain the CBC using the
                dbuf[i] ^= b1[i];           // last ciphertext block

            if(fwrite(dbuf, 1, l, fout) != l)
                return WRITE_ERROR;         // and write the decrypted block

            bt = b1, b1 = b2, b2 = bt;      // swap the input buffer pointers
        }
    }

    return 0;
}

int main(int argc, char *argv[])
{   FILE        *fin = 0, *fout = 0;
    char        *cp, ch, key[32];
    int         i, by, key_len, err = 0;
    aes_ctx     ctx[1];

    if(argc != 5 || toupper(*argv[3]) != 'D' && toupper(*argv[3]) != 'E')
    {
        printf("usage: aesxam in_filename out_filename [d/e] key_in_hex\n");
        err = -1; goto exit;
    }

    ctx->n_rnd = 0; // ensure all flags are initially set to zero
    ctx->n_blk = 0;
    cp = argv[4];   // this is a pointer to the hexadecimal key digits
    i = 0;          // this is a count for the input digits processed

    while(i < 64 && *cp)        // the maximum key length is 32 bytes and
    {                           // hence at most 64 hexadecimal digits
        ch = toupper(*cp++);    // process a hexadecimal digit
        if(ch >= '0' && ch <= '9')
            by = (by << 4) + ch - '0';
        else if(ch >= 'A' && ch <= 'F')
            by = (by << 4) + ch - 'A' + 10;
        else                    // error if not hexadecimal
        {
            printf("key must be in hexadecimal notation\n");
            err = -2; goto exit;
        }

        // store a key byte for each pair of hexadecimal digits
        if(i++ & 1)
            key[i / 2 - 1] = by & 0xff;
    }

    if(*cp)
    {
        printf("The key value is too long\n");
        err = -3; goto exit;
    }
    else if(i < 32 || (i & 15))
    {
        printf("The key length must be 32, 48 or 64 hexadecimal digits\n");
        err = -4; goto exit;
    }

    key_len = i / 2;

    if(!(fin = fopen(argv[1], "rb")))   // try to open the input file
    {
        printf("The input file: %s could not be opened\n", argv[1]);
        err = -5; goto exit;
    }

    if(!(fout = fopen(argv[2], "wb")))  // try to open the output file
    {
        printf("The input file: %s could not be opened\n", argv[1]);
        err = -6; goto exit;
    }

    if(toupper(*argv[3]) == 'E') // encryption in Cipher Block Chaining mode
    {
        aes_enc_key(key, key_len, ctx);

        err = encfile(fin, fout, ctx, argv[1], argv[2]);
    }
    else                         // decryption in Cipher Block Chaining mode
    {
        aes_dec_key(key, key_len, ctx);

        err = decfile(fin, fout, ctx, argv[1], argv[2]);
    }
exit:
    if(err == READ_ERROR)
        printf("Error reading from input file: %s\n", argv[1]);

    if(err == WRITE_ERROR)
        printf("Error writing to output file: %s\n", argv[2]);

    if(fout)
        fclose(fout);

    if(fin)
        fclose(fin);

    return err;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -