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

📄 aes.cpp

📁 RC2算法源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************************
 *                                                              *
 *  This program is part of an implementation of the block      *
 *  cipher RC6(TM) that is being submitted to NIST as a         *
 *  candidate for the AES.                                      *
 *                                                              *
 *  Ronald L. Rivest and RSA Laboratories, the submitters of    *
 *  RC6, retain all rights to RC6 and to this code, except for  *
 *  those which NIST requires to be waived for submissions.     *
 *                                                              *
 *  Copyright (C) 1998 RSA Data Security, Inc.                  *
 *                                                              *
 ****************************************************************/

/* This file contains a reference implementation of RC6 in C. */

/*注:Rc6ComputeKeySchedule();Rc6EncryptBlock();Rc6DecryptBlock();
      这三个函数已经实现了RC6层密钥生成、加脱密的功能;*/

#include <string.h>
#include <ctype.h>

#include "aes.h"
/* The "magic constants" for RC6 with 32-bit wordsize */
#define P32 0xb7e15163
#define Q32 0x9e3779b9


/* Macro for left-rotating a 32-bit dword by some amount */
#define ROTL(W,c) (((W) << ((c) & 0x1f)) | ((W) >> (32-((c) & 0x1f))))

/* Macro for right-rotating a 32-bit dword by some amount */
#define ROTR(W,c) (((W) >> ((c) & 0x1f)) | ((W) << (32-((c) & 0x1f))))




/*
 * Here we implement a few general utility functions
 */

/*
 * Load an unsigned long as a little-endian sequence of 4 bytes
 */
static unsigned long LoadDword(BYTE* ptr)
{
  return (((unsigned long) *ptr)+
          (((unsigned long) *(ptr+1)) << 8)+
          (((unsigned long) *(ptr+2)) << 16)+
          (((unsigned long) *(ptr+3)) << 24));
}



/*
 * Store an unsigned long as a little-endian sequence of 4 bytes
 */
static void StoreDword(unsigned long dword, BYTE* ptr)
{
  *ptr = (BYTE) dword;
  *(ptr+1) = (BYTE) (dword >> 8);
  *(ptr+2) = (BYTE) (dword >> 16);
  *(ptr+3) = (BYTE) (dword >> 24);
}



/*
 * ConvertDigitToNumber() converts a single ASCII hexadecimal digit
 * to its numeric equivalent in the range 0x0-0xf.
 */
static BYTE ConvertDigitToNumber(char digit)
{
  if (isdigit(digit))
    return ((BYTE) (digit-'0'));

  if (islower(digit))
    return ((BYTE) (digit-'a'+0xa));

  /* Apparently, it's an uppercase letter */
  return ((BYTE) (digit-'A'+0xa));
}



/*
 * ConvertDigitsToBytes() converts a sequence of pairs of ASCII hex
 * digits into a sequence of bytes.  It takes an argument, n, which
 * specifies how many bytes will be produced: 2n hex digits get
 * converted to n bytes.
 */
static void ConvertDigitsToBytes(char* digits, BYTE* bytes, int n)
{
  int i;

  for (i = 0; i < n*2; i += 2) {
    BYTE msn = ConvertDigitToNumber(digits[i]);
    BYTE lsn = ConvertDigitToNumber(digits[i+1]);
    bytes[i/2] = (BYTE) ((msn << 4) | lsn);
  }
}




/*
 * The next three functions-- Rc6ComputeKeySchedule(), Rc6EncryptBlock(),
 * and Rc6DecryptBlock()-- form the bottom-level implementation of RC6.
 */



/*
 * Rc6ComputeKeySchedule() computes a key schedule from a variable-length
 * key.  It does *not* properly test the length of the key in advance, so
 * a key passed to it should not have an out-of-range length.  Valid key
 * lengths are 0-255 bytes.
 *
 * The key passed to RC6ComputeKeySchedule() is a sequence of bytes, NOT
 * an ASCII string.
 *
 * Rc6ComputeKeySchedule() places the schedule it computes in an array
 * of 2+2*ROUNDS+2 = 44 dwords specified by a pointer, S, that is input.
 */
static void Rc6ComputeKeySchedule(BYTE* key, int keyLengthInBytes,
                                  unsigned long* S)
{
  unsigned long L[(255+4-1)/4];
  const int t = 2+2*ROUNDS+2;
  int count;
  int u;
  int i,j;
  unsigned long A,B;
  int startOfExtraDword, numberOfExtraBytes;


  /* Compute number of dwords taken up by key */
  int c = (keyLengthInBytes+4-1)/4;

  /* Special case: if the key is 0 bytes, then we'll start out with a
   * single element with the value 0 in the array of key dwords */
  if (c == 0)c = 1;

  /* Zero out array of key dwords */
  for (count = 0; count < c; count++)
    L[count] = 0;


  /* Load all the key bytes into the array of key dwords, with the
   * possible exception of the final 1-3 bytes */
  for (count = 0; count < keyLengthInBytes/4; count++)
    L[count] = LoadDword(key+count*4);

  
  printf("**********************密钥扩展*********************\n");
  printf("L[],0--4\n");
  for(i=0;i<c;i++)printf("%08x ",L[i]);printf("\n\n");

  /* Load any extra key bytes at the end into the last dword */
  startOfExtraDword = keyLengthInBytes & 0xfffffffc;
  numberOfExtraBytes = keyLengthInBytes & 0x3;
  if (numberOfExtraBytes > 0) {
    L[c-1] = (unsigned long) key[startOfExtraDword];
    if (numberOfExtraBytes > 1) {
      L[c-1] |= (((unsigned long) key[startOfExtraDword+1]) << 8);
      if (numberOfExtraBytes > 2)
        L[c-1] |= (((unsigned long) key[startOfExtraDword+2]) << 16);
    }
  }

  /* Initialize key schedule array */
  S[0] = P32;
  for (count = 1; count < t; count++)
    S[count] = S[count-1]+Q32;

  printf("S[0]=Pw S[i]=S[i-1]+Qw\n");
  for(i=0;i<t;i++){printf("%08x ",S[i]);if(i%8==7)printf("\n");}printf("\n\n");
  /* The number of passes in the key schedule set-up algorithm is equal to
   * 3 times the size of whichever is larger: the array of key dwords, or
   * the array of key schedule dwords that we're computing. */
  u = 3*((c>t) ? c : t);

  i = j = 0;
  A = B = 0;

  /* Mix the key into the key schedule array over the course of u rounds */
  for (count = 1; count <= u; count++) {
    unsigned long sum;

    sum = A+B;
    S[i] += sum;
    A = S[i] = ROTL(S[i], 3);

    sum = A+B;
    L[j] += sum;
    B = L[j] = ROTL(L[j], sum);

    i = (i+1) % t;
    j = (j+1) % c;
  }
  printf("经最终变换后的加密密钥\n");
  for(i=0;i<t;i++){printf("%08x ",S[i]);if(i%8==7)printf("\n");}printf("\n\n");

}



/*
 * Rc6EncryptBlock() encrypts a single [16-byte] block of plaintext.
 * The key schedule to be used is passed in as a pointer, S, to the
 * array of 44 dwords of which the key schedule is comprised.
 */
static void Rc6EncryptBlock(unsigned long* S,
                            BYTE* plaintext, BYTE* ciphertext)
{
  int i;

  /* Load A, B, C, and D registers from plaintext */
  unsigned long A = LoadDword(plaintext);
  unsigned long B = LoadDword(plaintext+4);
  unsigned long C = LoadDword(plaintext+8);
  unsigned long D = LoadDword(plaintext+12);


  printf("***********************Encrypt start********************\n");
  printf("A=%08x B=%08x C=%08x D=%08x \n",A,B,C,D);
  /* Do pseudo-round #0: pre-whitening of B and D */
  B += S[0];
  D += S[1];


  /* Perform round #1, #2, ..., #ROUNDS of encryption */
  for (i = 1; i <= ROUNDS; i++) 
  {
    unsigned long t, u;

    t = B*(2*B+1);
    t = ROTL(t, 5);

    u = D*(2*D+1);
    u = ROTL(u, 5);

    A ^= t;
    A = ROTL(A, u);
    A += S[2*i];

    C ^= u;
    C = ROTL(C, t);
    C += S[2*i+1];

	printf("t=%08x u=%08x A=%08x C=%08x \n",t,u,A,C);

    {
      unsigned long temp = A;
      A = B;
      B = C;
      C = D;
      D = temp;
    }
    printf("A=%08x B=%08x C=%08x D=%08x \n",A,B,C,D);printf("\n");

  }


  /* Do pseudo-round #(ROUNDS+1): post-whitening of A and C */
  A += S[2*ROUNDS+2];
  C += S[2*ROUNDS+3];


  /* Store A, B, C, and D registers to ciphertext */
  StoreDword(A, ciphertext);
  StoreDword(B, ciphertext+4);
  StoreDword(C, ciphertext+8);
  StoreDword(D, ciphertext+12);
}



/*
 * Rc6DecryptBlock() decrypts a single [16-byte] block of ciphertext.
 * The key schedule to be used is passed in as a pointer ("S") to the
 * array of 44 dwords of which the key schedule is comprised.
 */
static void Rc6DecryptBlock(unsigned long* S,
                            BYTE* ciphertext, BYTE* plaintext)
{
  int i;

  /* Load A, B, C, and D registers from ciphertext */
  unsigned long A = LoadDword(ciphertext);
  unsigned long B = LoadDword(ciphertext+4);
  unsigned long C = LoadDword(ciphertext+8);
  unsigned long D = LoadDword(ciphertext+12);


  /* Undo pseudo-round #(ROUNDS+1): post-whitening of A and C */
  C -= S[2*ROUNDS+3];
  A -= S[2*ROUNDS+2];


  /* Undo round #ROUNDS, ..., #2, #1 of encryption */
  for (i = ROUNDS; i >= 1; i--) {
    unsigned long t, u;

    {
      unsigned long temp = D;
      D = C;
      C = B;
      B = A;
      A = temp;
    }

    t = B*(2*B+1);
    t = ROTL(t, 5);

    u = D*(2*D+1);
    u = ROTL(u, 5);

    C -= S[2*i+1];
    C = ROTR(C, t);
    C ^= u;

    A -= S[2*i];
    A = ROTR(A, u);
    A ^= t;
  }


  /* Undo pseudo-round #0: pre-whitening of B and D */
  D -= S[1];
  B -= S[0];


  /* Store A, B, C, and D registers to plaintext */
  StoreDword(A, plaintext);
  StoreDword(B, plaintext+4);
  StoreDword(C, plaintext+8);
  StoreDword(D, plaintext+12);
}




/*
 * The six functions below add modes (ECB, CBC, and 1-bit CFB) to the
 * simple block cipher functionality implemented above.
 */



/*
 * Rc6EncryptEcb() encrypts a specified number of blocks in ECB mode.
 */
static void Rc6EncryptEcb(unsigned long* S, int numberOfBlocks,
                          BYTE* plaintext, BYTE* ciphertext)
{
  for ( ; numberOfBlocks-- > 0; plaintext += 16, ciphertext += 16)
    /* Encrypt block */
    Rc6EncryptBlock(S, plaintext, ciphertext);
}



/*
 * Rc6DecryptEcb() decrypts a specified number of blocks in ECB mode.
 */
static void Rc6DecryptEcb(unsigned long* S, int numberOfBlocks,
                          BYTE* ciphertext, BYTE* plaintext)
{
  for ( ; numberOfBlocks-- > 0; ciphertext += 16, plaintext += 16)
    /* Decrypt block */
    Rc6DecryptBlock(S, ciphertext, plaintext);
}



/*
 * Rc6EncryptCbc() encrypts a specified number of blocks in CBC mode.

⌨️ 快捷键说明

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