基于 AES 算法的 CTR 工作模式演示程序实现
基本要求:
1、如图 4 可视化实现 CBC 工作模式。图 4 的分组加密和分组解密可以直接
调用编程语言 DES 算法实现提供的接口函数实现,不需要自行编写密码算法。
但不能直接选择调用编程语言 DES-CBC 模式的接口直接实现。
2、图形化界面设计要求:
(1)采用图形化界面演示 CBC 模式的加密和解密运行演示过程(参考图 5
所示。还可以更加详细,比如输出界面中初始向量和明文分组对应字符的 16 进
制数值,以及异或之后的结果),至少加密和解密 4 组明文,若最后 1 组不够分
组长度,尾部需要自行进行填充,填充方法可参考密码学教材选择相关填充方法。
(2)加密算法密钥和初始变量 IV 的输入界面.
说明:选择其他分组密码算法和密码工作模式要求类似,比如 3DES、AES
算法;密码工作模式除了 CBC 模式外,还可以选择 OFB,CFB,CRT 其他 3 种
工作模式,其他工作模式的加密和解密流程可以参考相关教材。具体功能实现要
求类似基于 DES 算法的 CBC 演示程序实现要求和界面设计。
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。本文将介绍AES的具体流程,以及c++实现,并且实现了CBC和CTR模式的解密函数。
1.关于AES(高级加密标准):在这里一个分组为128bit(16byte),密钥也是128bit(16byte),密钥要先通过密钥扩展,具体过程如图:
#include <stdio.h>
#include <stdlib.h>
#include "AES.h"
Byte *keyExpansion(Byte *cipherKey) {
Byte *expandedKey = (Byte *)malloc(sizeof(Byte) * BYTES_IN_EXPANDED_KEY);
// get the key of the first round
for(int i = 0; i < BYTES_IN_ROUND; i++)
expandedKey[i] = cipherKey[i];
// get the key of other rounds
Byte *temporary_word = (Byte *)malloc(sizeof(Byte) * BYTES_IN_WORD);
for(int i = 1; i <= NUM_OF_ROUNDS; i++) {
// calculate the temporary word
for(int j = 0; j < BYTES_IN_WORD; j++)
temporary_word[j] = expandedKey[i * BYTES_IN_ROUND - BYTES_IN_WORD + j];
rotateWord(temporary_word, 1);
substitutionWord(temporary_word);
temporary_word[0] = (temporary_word[0] ^ roundConstant[i - 1]);
// get the key of this round
for(int j = 0; j < BYTES_IN_WORD; j++)
expandedKey[i * BYTES_IN_ROUND + j] = temporary_word[j]
^ expandedKey[(i - 1) * BYTES_IN_ROUND + j];
for(int j = 1; j < WORD_IN_ROUND; j++) {
for(int k = 0; k < BYTES_IN_WORD; k++) {
expandedKey[i * BYTES_IN_ROUND + j * BYTES_IN_WORD + k] =
expandedKey[i * BYTES_IN_ROUND + (j - 1) * BYTES_IN_WORD + k] ^
expandedKey[(i - 1) * BYTES_IN_ROUND + j * BYTES_IN_WORD + k];
}
}
}
free(temporary_word);
return expandedKey;
}
void AES_Encryption(Byte state[][BYTES_IN_WORD], Byte* key) {
// Round 0: addRoundKey
addRoundKey(state, key, 0);
// Round 1~9: substitutionWord + shiftRow + mixColumn + addRoundKey
for(int i = 1; i < 10; i++) {
substitutionWord(state);
shiftRow(state);
mixColumn(state);
addRoundKey(state, key, i);
}
// Round 10: substitutionWord + shiftRow + addRoundKey
substitutionWord(state);
shiftRow(state);
addRoundKey(state, key, 10);
}
void AES_Decryption(Byte state[][BYTES_IN_WORD], Byte* key) {
// Inv round 10: addRoundKey + shiftRowInv + substitutionWordInv
addRoundKey(state, key, 10);
shiftRowInv(state);
substitutionWordInv(state);
// Inv round 9~1: addRoundKey + mixColumnInv + shiftRowInv + substitutionWordInv
for(int i = 9; i > 0; i--) {
addRoundKey(state, key, i);
mixColumnInv(state);
shiftRowInv(state);
substitutionWordInv(state);
}
// Inv round 0: addRoundKey
addRoundKey(state, key, 0);
}
void rotateWord(Byte *word, int offset) {
Byte *temp = (Byte *)malloc(sizeof(Byte) * BYTES_IN_WORD);
for(int i = 0; i < BYTES_IN_WORD; i++)
temp[(i + BYTES_IN_WORD - offset) % 4] = word[i];
for(int i = 0; i < BYTES_IN_WORD; i++)
word[i] = temp[i];
free(temp);
}
void substitutionWord(Byte *word) {
for(int i = 0; i < BYTES_IN_WORD; i++)
word[i] = sBox[word[i] / 16][word[i] % 16];
}
void substitutionWord(Byte state[][BYTES_IN_WORD]) {
for(int i = 0; i < BYTES_IN_WORD; i++)
for(int j = 0; j < BYTES_IN_WORD; j++)
state[i][j] = sBox[state[i][j] / 16][state[i][j] % 16];
}
void substitutionWordInv(Byte state[][BYTES_IN_WORD]) {
for(int i = 0; i < BYTES_IN_WORD; i++)
for(int j = 0; j < BYTES_IN_WORD; j++)
state[i][j] = sBoxInv[state[i][j] / 16][state[i][j] % 16];
}
void shiftRow(Byte state[][BYTES_IN_WORD]) {
for(int i = 0; i < BYTES_IN_WORD; i++)
rotateWord(state[i], i);
}
void shiftRowInv(Byte state[][BYTES_IN_WORD]) {
for(int i = 1; i < BYTES_IN_WORD; i++)
rotateWord(state[i], 4 - i);
}
void mixColumn(Byte state[][BYTES_IN_WORD]) {
Byte *temp = (Byte *)malloc(sizeof(Byte) * BYTES_IN_WORD);
for(int i = 0; i < BYTES_IN_WORD; i++) {
for(int j = 0; j < BYTES_IN_WORD; j++)
temp[j] = state[j][i];
for(int j = 0; j < BYTES_IN_WORD; j++) {
state[j][i] = 0;
for(int k = 0; k < BYTES_IN_WORD; k++)
state[j][i] = (state[j][i] ^ GF_Multiplication(constantMatrix[j][k], temp[k]));
}
}
free(temp);
}
void mixColumnInv(Byte state[][BYTES_IN_WORD]) {
Byte *temp = (Byte *)malloc(sizeof(Byte) * BYTES_IN_WORD);
for(int i = 0; i < BYTES_IN_WORD; i++) {
for(int j = 0; j < BYTES_IN_WORD; j++)
temp[j] = state[j][i];
for(int j = 0; j < BYTES_IN_WORD; j++) {
state[j][i] = 0;
for(int k = 0; k < BYTES_IN_WORD; k++)
state[j][i] = (state[j][i] ^ GF_Multiplication(constantMatrixInv[j][k], temp[k]));
}
}
free(temp);
}
Byte GF_Multiplication(Byte a, Byte b) {
bool *temp = (bool *)malloc(sizeof(bool) * BIT_IN_BYTE * 2);
for(int i = 0; i < BIT_IN_BYTE; i++) {
temp[i] = b % 2;
b /= 2;
}
short result = 0;
for(int i = 0; i < BIT_IN_BYTE; i++) {
result = result ^ ((temp[i] * a) << i);
}
int count = 0;
int temp_result = result;
for(int i = 0; i < BIT_IN_BYTE * 2; i++) {
temp[count++] = temp_result % 2;
temp_result /= 2;
}
for(int i = BIT_IN_BYTE; i < BIT_IN_BYTE * 2; i++)
if(temp[i] == 1)
result = result ^ GF_constant[i - BIT_IN_BYTE];
free(temp);
return (Byte)result;
}
void addRoundKey(Byte state[][BYTES_IN_WORD], Byte* key, int round) {
for(int i = 0; i < BYTES_IN_WORD; i++)
for(int j = 0; j < BYTES_IN_WORD; j++)
state[j][i] = (state[j][i] ^ key[round * BYTES_IN_ROUND + i * 4 + j]);
}
void printState(Byte state[][BYTES_IN_WORD]) {
for(int i = 0; i < BYTES_IN_WORD; i++) {
for(int j = 0; j < BYTES_IN_WORD; j++)
printf("%02X ", state[i][j]);
printf("\n");
}
printf("\n");
}
来源:
Fancy_ruanruan