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

📄 aesexam.cpp

📁 AES加密算法源代码
💻 CPP
字号:

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

#include "aes.h"

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

#ifdef LINUX
#define file_len(x) (unsigned long)x.__pos
#else
#define file_len(x) (unsigned long)x
#endif

//  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, len, rlen;
    // set a random IV
    fillrand(dbuf, BLOCK_LEN);
    // find the file length
    fseek(fin, 0, SEEK_END);
    fgetpos(fin, &flen); 
    rlen = file_len(flen);
    // reset to start
    fseek(fin, 0, SEEK_SET);
    if(rlen <= BLOCK_LEN)               
    {   // if the file length is less than or equal to 16 bytes
        // read the bytes of the file into the buffer and verify length
        len = (unsigned long) fread(dbuf + BLOCK_LEN, 1, BLOCK_LEN, fin);
        rlen -= len;        
        if(rlen > 0) 
            return READ_ERROR;
        // pad the file bytes with zeroes
        for(i = len; i < BLOCK_LEN; ++i)
            dbuf[i + BLOCK_LEN] = 0;
        // xor the file bytes with the IV bytes
        for(i = 0; i < BLOCK_LEN; ++i)
            dbuf[i + BLOCK_LEN] ^= dbuf[i];
        // encrypt the top 16 bytes of the buffer
        aes_enc_blk(dbuf + BLOCK_LEN, dbuf + len, ctx);
        len += BLOCK_LEN;
        // write the IV and the encrypted file bytes
        if(fwrite(dbuf, 1, len, fout) != len)
            return WRITE_ERROR;
    }
    else
    {   // if the file length is more 16 bytes
        // write the IV
        if(fwrite(dbuf, 1, BLOCK_LEN, fout) != BLOCK_LEN)
            return WRITE_ERROR;
        // read the file a block at a time 
        while(rlen > 0 && !feof(fin))
        {  
            // read a block and reduce the remaining byte count
            len = (unsigned long)fread(buf, 1, BLOCK_LEN, fin);
            rlen -= len;
            // verify length of block 
            if(len != BLOCK_LEN) 
                return READ_ERROR;
            // do CBC chaining prior to encryption
            for(i = 0; i < BLOCK_LEN; ++i)
                buf[i] ^= dbuf[i];
            // encrypt the block
            aes_enc_blk(buf, dbuf, ctx);
            // if there is only one more block do ciphertext stealing
            if(rlen > 0 && rlen < BLOCK_LEN)
            {
                // move the previous ciphertext to top half of double buffer
                // since rlen bytes of this are output last
                for(i = 0; i < BLOCK_LEN; ++i)
                    dbuf[i + BLOCK_LEN] = dbuf[i];
                // read last part of plaintext into bottom half of buffer
                if(fread(dbuf, 1, rlen, fin) != rlen)
                    return READ_ERROR;
                // clear the remainder of the bottom half of buffer
                for(i = 0; i < BLOCK_LEN - rlen; ++i)
                    dbuf[rlen + i] = 0;
                // do CBC chaining from previous ciphertext
                for(i = 0; i < BLOCK_LEN; ++i)
                    dbuf[i] ^= dbuf[i + BLOCK_LEN];
                // encrypt the final block
                aes_enc_blk(dbuf, dbuf, ctx);
                // set the length of the final write
                len = rlen + BLOCK_LEN; rlen = 0;
            }
            // write the encrypted block
            if(fwrite(dbuf, 1, len, fout) != len)
                return WRITE_ERROR;
        }
    }
    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, len, rlen;
    // find the file length
    fseek(fin, 0, SEEK_END);
    fgetpos(fin, &flen); 
    rlen = file_len(flen);
    // reset to start
    fseek(fin, 0, SEEK_SET);
    if(rlen <= 2 * BLOCK_LEN)
    {   // if the original file length is less than or equal to 16 bytes
        // read the bytes of the file and verify length
        len = (unsigned long)fread(dbuf, 1, 2 * BLOCK_LEN, fin);
        rlen -= len;
        if(rlen > 0)
            return READ_ERROR;
        // set the original file length
        len -= BLOCK_LEN;
        // decrypt from position len to position len + BLOCK_LEN
        aes_dec_blk(dbuf + len, dbuf + BLOCK_LEN, ctx);
        // undo CBC chaining
        for(i = 0; i < len; ++i)
            dbuf[i] ^= dbuf[i + BLOCK_LEN];
        // output decrypted bytes
        if(fwrite(dbuf, 1, len, fout) != len)
            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;

        // input the IV
        if(fread(b1, 1, BLOCK_LEN, fin) != BLOCK_LEN)
            return READ_ERROR;
        // read the encrypted file a block at a time
        while(rlen > 0 && !feof(fin))
        {
            // input a block and reduce the remaining byte count
            len = (unsigned long)fread(b2, 1, BLOCK_LEN, fin);
            rlen -= len;

            // verify the length of the read operation
            if(len != BLOCK_LEN)
                return READ_ERROR;

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

            // if there is only one more block do ciphertext stealing
            if(rlen > 0 && rlen < BLOCK_LEN)
            {
                // read last ciphertext block
                if(fread(b2, 1, rlen, fin) != rlen)
                    return READ_ERROR;

                // append high part of last decrypted block
                for(i = rlen; i < BLOCK_LEN; ++i)
                    b2[i] = dbuf[i];

                // decrypt last block of plaintext
                for(i = 0; i < rlen; ++i)
                    dbuf[i + BLOCK_LEN] = dbuf[i] ^ b2[i];

                // decrypt last but one block of plaintext
                aes_dec_blk(b2, dbuf, ctx);

                // adjust length of last output block
                len = rlen + BLOCK_LEN; rlen = 0;
            }
            // unchain CBC using the last ciphertext block
            for(i = 0; i < BLOCK_LEN; ++i)
                dbuf[i] ^= b1[i];
            // write decrypted block
            if(fwrite(dbuf, 1, len, fout) != len)
                return WRITE_ERROR;
            // swap the buffer pointers
            bt = b1, b1 = b2, b2 = bt;
        }
    }
    return 0;
}

// typedef struct                    /* the AES context for encryption   */
//{   aes_32t    k_sch[KS_LENGTH];   /* the encryption key schedule      */
//    aes_32t    n_rnd;              /* the number of cipher rounds      */
//    aes_32t    n_blk;              /* the number of bytes in the state */
//} aes_ctx;  // f_ctx alg;
// unsigned int  aes_32t;
// #define KS_LENGTH   128

int main(void)
{   
	FILE  *fin = 0, *fout = 0;
    char  ed, key[32],infile[12],outfile[12],key1[33];
    int   i, key_len, err = 0;
    aes_ctx  ctx[1];
	printf("\t 请输入密约(长度为16,24或32字节)!\n");
	scanf("%s",key1);
	printf("\t 加密输入E \n\t 解密输入D\n\t请输入选择!\n");
	scanf("%c",&ed);
	if (ed='\n') scanf("%c",&ed);
	ed=toupper(ed);
	if (ed=='E')
	{
		printf("\t 请输入待加密的文件名!\n");
		scanf("%s",infile);
		printf("\t 请输入加密结果文件名!\n");
		scanf("%s",outfile);
	}
	else if (ed=='D')
	{
		printf("\t 请输入待解密的文件名!\n ");
		scanf("%s",infile);
		printf("\t 请输入解密结果文件名!\n");
		scanf("%s",outfile);
	}
	else { err++; goto exit; }
    ctx->n_rnd = 0; // ensure all flags are initially set to zero
    ctx->n_blk = 0;
    i = 0;          // this is a count for the input digits processed
	while (key1[i]) key[i]=key1[i++];
	key_len = strlen(key);
    if(!(fin = fopen(infile, "rb")))
    {
        printf("The input file: %s could not be opened\n", infile);
        err = -5; goto exit;
    }
   if(!(fout = fopen(outfile, "wb")))    
	{
        printf("The output file: %s could not be opened\n", outfile);
        err = -6; goto exit;
    }
    if(ed == 'E') // encryption in Cipher Block Chaining mode
    {
        aes_enc_key(key, key_len, ctx);
        err = encfile(fin, fout, ctx, infile, outfile);
    }
    else                         // decryption in Cipher Block Chaining mode
    {
        aes_dec_key(key, key_len, ctx);
        err = decfile(fin, fout, ctx, infile, outfile);
    }
exit:
    if(err == READ_ERROR)
        printf("Error reading from input file: %s\n", infile);
    if(err == WRITE_ERROR)
        printf("Error writing to output file: %s\n", outfile);
    if(fout)  fclose(fout);
    if(fin)   fclose(fin);
    return err;
}

⌨️ 快捷键说明

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