实 验 报 告
学号:姓名:专业: 班级: 第 10 周
课程
实验课时
2
密码学与网络安全
名称
实验
AES加密算法 实验时间
项目
实验
完成 AES加密算法,实现图片加密与解密,并将加密后的结果以图片格式保存。
目的
实验
环境
PC机, Windows7操作系统, Visual C++
实验
内容
(算
法、
程 序、步骤和方
法)
一、 简介
美国国家标准技术研究所在 2001 年发布了高级加密标准( AES)。
AES是一个对称加密算法,旨在取代 DES成为广泛使用的标准。
AES中的所有运算都是在 8 为的字节上运行的。特别饿,加减乘除算术都是在有限域 GF(28) 上运行的。
二、 程序特点
本次试验中要求对图片进行加密与解密,并将加密结果以图片格式进行保存。因此为了实现对图片的调度及保存,使用头文件进行对图片的操作,实现对图片的像素读取,图片的保存。
在程序运行读取需要加密的图片时, 需要进行图片的选取, 本次实验中使用在弹窗中选取文件的方式,使用头文件来实现在文件夹中选择需要的文件的选
取。
三、 加密算法流程
AES加密算法流程如下
字节代替:用一个 S 盒完成分组的字节到字节的代替;
行移位:进行一次行上的置换;
列混合:利用有限域 GF(28) 上的运算特性的一个代替;
轮密钥加:当前分组和扩展密钥的一部分进行按位异或。
四、 代码实现
#include <string>
#include <iostream>
class plaintext
{
public :
plaintext();
static void createplaintext( unsigned char a[]);
static
void
SubBytes( unsigned char p[16]);
static
void
inSubBytes(
unsigned
char p[16]);
static
void
ShiftRows(
unsigned
char e[]);
static
void
inShiftRows(
unsigned
char e[]);
static
void
MatrixToByte(
unsigned
char e[]);
static
void
inMatrixToByte(
unsigned
char
e[]);
static
unsigned char FFmul( unsigned
char
a,
unsigned
char b);
static
void
KeyAdding(
unsigned
char state[16],
unsigned char k[][4]);
static
void
KeyExpansion(
unsigned
char * key,
unsigned
char w[][4][4]);
~plaintext();
private :
};
#include ""
using namespacestd;
static unsigned char sBox[] = {};
unsigned char insBox[256] ={};
plaintext ::plaintext()
{
}
void plaintext ::createplaintext(
{
/ 定义加密 S盒/
// 定义解密 S盒
unsigned char a[]) // 创建明文
int i = 0;
unsigned
int
p[16];
for
( int
j = 0; j<200; j++)
{
if
{
( a[j] == 0)
break ;
}
}
for (; i<16; i++)
{
p[i] =
a[i] =
a[i];
a[i + 16];
}
}
void plaintext
{
::SubBytes( unsigned char p[16]) // 字节变换函数
unsigned char b[16];
for ( int i = 0; i<16; i++)
{
b[i] = sBox[(
int ) p[i]];
}
}
void plaintext
::inSubBytes(
unsigned char p[16]) // 逆字节变换函数
{
unsigned char b[16];
for ( int i = 0; i<16; i++)
{
b[i] = insBox[(
int ) p[i]];
}
}
void plaintext
::ShiftRows(
unsigned char e[]) // 行移位变换函数
{
unsigned char t[4];
for ( int i = 1; i<4; i++)
{
for ( int x = 0; x<4; x++)
t[x] = e[x + i * 4];
for ( int y = 0; y<4; y++)
e[(y + 4 - i) % 4 + i * 4] = t[y];
}
}
void plaintext ::inShiftRows( unsigned char e[]) // 逆行移位变换函数
{
unsigned char t[4];
for ( int i = 1; i<4; i++)
{
for ( int x = 0; x<4; x++)
t[x] = e[x + i * 4];
for ( int y = 0; y<4; y++)
e[(y + i) % 4 + i * 4] = t[y];
}
}
void plaintext ::MatrixToByte( unsigned char e[]) // 列混合变换函数
{
unsigned char t[4];
int r, c;
for (c = 0; c< 4; c++)
{
for (r = 0; r<4; r++)
{
t[r] = e[r * 4 + c];
}
for (r = 0; r<4; r++)
{
e[r * 4 + c] = FFmul(0x02, t[r])
FFmul(0x03, t[(r + 1) % 4])
FFmul(0x01, t[(r + 2) % 4])
FFmul(0x01, t[(r + 3) % 4]);
}
}
}
void plaintext ::inMatrixToByte( unsigned char e[]) // 逆列混合变换函数
{
unsigned char t[4];
int r, c;
for (c = 0; c< 4; c++)
{
for (r = 0; r<4; r++)
{
t[r] = e[r * 4 + c];
}
for (r = 0; r<4; r++)
{
e[r * 4 + c] = FFmul(0x0e, t[r])
FFmul(0x0b, t[(r + 1) % 4])
FFmul(0x0d, t[(r + 2) % 4])
FFmul(0x09, t[(r + 3) % 4]);
}
}
}
unsigned char plaintext ::FFmul( unsigned char a, unsigned char b)
{
unsigned
char bw[4];
unsigned
char res = 0;
int
i;
bw[0] =
b;
for
(i = 1; i<4; i++)
{
bw[i] = bw[i - 1] << 1;
if (bw[i - 1] & 0x80)
{
bw[i] ^= 0x1b;
}
}
for (i = 0; i<4; i++)
{
if (( a >> i) & 0x01)
{
res ^= bw[i];
}
}
return
res;
}
void
plaintext
::KeyAdding( unsigned char state [16],
unsigned char k [][4])
// 轮密钥加
{
int r, c;
for (c = 0; c<4; c++)
{
for (r = 0; r<4; r++)
{
state [r + c * 4] ^= k[r][c];
}
}
}
void plaintext ::KeyExpansion( unsigned char * key, unsigned char w[][4][4]) // 密钥扩展
{
int i, j, r, c;
unsigned char rc[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; for (r = 0; r<4; r++)
{
for (c = 0; c<4; c++)
{
w[0][r][c] = key [r + c * 4];
}
}
for (i = 1; i <= 10; i++)
{
for (j = 0; j<4; j++)
{
unsigned char t[4];
for (r = 0; r<4; r++)
{
t[r] = j ? w[i][r][j - 1] : w[i - 1][r][3];
}
if (j == 0)
{
unsigned char temp = t[0];
for (r = 0; r<3; r++)
{
t[r] = sBox[t[(r + 1) % 4]];
}
t[3] = sBox[temp];
t[0] ^= rc[i - 1];
}
for (r = 0; r<4; r++)
{
w[i][r][j] = w[i - 1][r][j] ^ t[r];
}
}
}
}
plaintext ::~plaintext()
{
}
#include <iostream>
#include <>
#include <>// 使用文件选取功能
#include ""
using namespacestd;
unsigned char w[11][4][4] = { 0 };
int len = 0; // 图片每行需要加密的长度
void Cipher(); // 加密图片
void inCipher(); // 解密图片
void Cipher( unsigned char a[])
{
unsigned char b[16];
for ( int i = 0; i < (len / 16); i++)
{
for ( int j = 0; j<16; j++)
b[j] = a[j + i * 16];
plaintext ::KeyAdding(b, w[0]);
for ( int n = 1; n <= 10; n++)
{
plaintext ::SubBytes(b);
plaintext ::ShiftRows(b);
if (n != 10) plaintext ::MatrixToByte(b);
plaintext ::KeyAdding(b, w[n]);
}
for ( int m = 0; m<16; m++)
a[m + i * 16] = b[m];
}
}
void inCipher( unsigned char a[]){
unsigned char b[16];
for ( int i = 0; i < (len / 16) ; i++)
{
for ( int j = 0; j<16; j++)
{
b[j] =
a[j + i * 16];
}
plaintext ::KeyAdding(b, w[10]);
for ( int n = 9; n >= 0; n--)
{
plaintext ::inShiftRows(b);
plaintext ::inSubBytes(b);
plaintext ::KeyAdding(b, w[n]);
if (n) plaintext ::inMatrixToByte(b);
}
for ( int m = 0; m<16; m++)
a[m + i * 16] = b[m];
}
}
bool ImageCopy( const CImage & srcImage , CImage &destImage )
{
int i, j;
if ())
// 循环变量
return
FALSE;
源图像参数
BYTE* srcPtr = ( BYTE*)();
int srcBitsCount = ();
int srcWidth = ();
int srcHeight = ();
int srcPitch = ();
销毁原有图像
if (!())
{
();
}
// 创建新图像
if (srcBitsCount == 32)
{
// 支持 alpha 通道
(srcWidth, srcHeight, srcBitsCount, 1);
}
else
{
(srcWidth, srcHeight, srcBitsCount, 0);
}
BYTE*destPtr = ( BYTE*)();
int destPitch = ();
len=abs(srcPitch);
for ( int i = 0; i<srcHeight; i++)
Cipher(srcPtr + i*srcPitch);
复制图像数据
for (i = 0; i<srcHeight; i++)
{
memcpy(destPtr + i*destPitch, srcPtr + i*srcPitch, abs(srcPitch));
}
return TRUE;
}
bool inImageCopy( const CImage &srcImage , CImage &destImage )
{
int
if
i, j;
())
// 循环变量
return
FALSE;
源图像参数
BYTE* srcPtr = ( BYTE*)();
int srcBitsCount = ();
int srcWidth = ();
int srcHeight = ();
int srcPitch = ();
销毁原有图像
if (!())
{
();
}
// 创建新图像
if (srcBitsCount == 32)
{
// 支持 alpha 通道
(srcWidth, srcHeight, srcBitsCount, 1);
}
else
{
(srcWidth, srcHeight, srcBitsCount, 0);
}
BYTE*destPtr = ( BYTE*)();
int destPitch = ();
len = abs(srcPitch);
for ( int i = 0; i<srcHeight; i++)
inCipher(srcPtr + i*srcPitch);
复制图像数据
for (i = 0; i<srcHeight; i++)
{
memcpy(destPtr + i*destPitch, srcPtr + i*srcPitch, abs(srcPitch));
}
return TRUE;
}
int
{
main()
unsigned char key[16] = { 0x77, 0x59, 0xc5, 0xa4, 0x55, 0x90, 0xa4, 0xa3, 0xb2, 0xcc, 0x01, 0xa9, 0xcb, 0xac, 0x77, 0x23 };
// 固定密钥
plaintext
::KeyExpansion(key, w);
TCHARszBuffer[ MAX_PATH] = { 0 }; // 使用文件选取功能
OPENFILENAMEofn = { 0 };
sizeof (ofn);
= m_hWnd;
_T( "" ); // 要选择的文件后缀
_T( "D:\\" ); // 默认的文件路径
szBuffer; // 存放文件的缓冲区
= sizeof (szBuffer) / sizeof (*szBuffer);
0;
OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST| OFN_EXPLORER; // 标志如果是多选要加上
OFN_ALLOWMULTISELECT
BOOLbSel = GetOpenFileName(&ofn);
CImage image, image2, image3; // 读取图片
(szBuffer);
ImageCopy(image, image2);
( "e:/" );
inImageCopy(image2, image3);
( "e:/" );
system( "pause" );
}
运行程序,出现选择图片界面
本数
据记
录
加密结束
和计
算
原图片
加密图片
解密图片
根据结果显示,程序成功的实现了对图片的加密,得到的加密后的结果仍然为图片,并成
结 功地的解密得到了正确的解密后的图片。
论
(结
果)
通过本次试验,成功的完成了对 AES密码算法的初步编写,了解了 AES算法的工作原理。
对于图片加密方面,掌握了新的调用图片的方法
,使用头文件大大简化了
c++中对图片调
小 用的难度。
结
同时在文件读取方面使用了头文件,使得程序在使用上更加方便。
指导
老师
评
议
成绩评定: 指导教师签名:
- 下载文档
- 收藏
- 0
推荐访问:实验报告 加密算法 实验 计划 AES加密算法实验报告总结计划