三、方案实现 1. 全局函数 介绍:aes_encrypt()函数 function ciphertext = aes_encrypt (app,plaintext, w, s_box, poly_mat)
fbar=waitbar(0,'加密中');
pause(0.02);
% 判断输入的参数是否符合AES的要求
% 如果输入向量是单元格数组或没有16个元素
ifiscell(plaintext)|| numel(plaintext)~= 16
error('Plaintext has to be a vector (not a cell array) with 16 elements.')
end
% 如果输入向量中的任何元素不能用8位表示
ifany(plaintext< 0 |plaintext> 255)
error('Elements of plaintext vector have to be bytes (0 <= plaintext(i) <= 255).')
end
% 如果展开的密钥数组是单元格数组或没有正确的大小
ifiscell(w)||any(size(w)~=[44, 4])
error('w has to be an array (not a cell array) with [44 x 4] elements.')
end
% 如果扩展的密钥数组中的任何元素不能用8位表示
ifany(w< 0 |w> 255)
error('Elements of key array w have to be bytes (0 <= w(i,j) <= 255).')
end
%
waitbar(1,fbar,'明文预处理完毕');
pause(0.02);
% 复制输入向量的16个元素 逐列化为4 × 4状态矩阵
state=reshape(plaintext,4, 4);
% 复制扩展密钥的前4行(4 x 4个元素) 放入当前圆密钥
% 转置使这个列对齐
round_key=(w(1:4,:))';
% 将当前的密钥加(矩阵)添加到状态(矩阵)
state=app.add_round_key(state,round_key);
% 循环9轮
fori_round=1:9
waitbar(i_round/9,fbar,'循环处理中');
pause(0.005);
% 把状态矩阵的所有16个元素都放到s盒中
state=app.sub_bytes(state,s_box);
% 循环移动状态矩阵的最后三行
state=app.shift_rows(state);
% 用一个四项多项式变换状态矩阵的列
state=app.mix_columns(state,poly_mat);
% 从扩展赞密钥中提取当前的圆密钥(4 × 4矩阵)
round_key=(w((1:4) + 4*i_round,:))';
% 将当前的元密钥(矩阵)添加到状态(矩阵)
state=app.add_round_key(state,round_key);
end
% 把状态矩阵的所有16个元素都放到s盒中
state=app.sub_bytes(state,s_box);
% 循环移动状态矩阵的最后三行
state=app.shift_rows(state);
% 从扩展赞密钥中提取当前的圆密钥(4 × 4矩阵)
round_key=(w(41:44,:))';
% 将当前的元密钥(矩阵)添加到状态(矩阵)
state=app.add_round_key(state,round_key);
% 将4 x 4状态矩阵重塑为16个元素的行向量
ciphertext=reshape(state,1, 16);
waitbar(1,fbar,'加密成功');
pause(0.01);
close(fbar);
end
介绍:aes_decrypt()函数 function plaintext = aes_decrypt (app,ciphertext, w, inv_s_box, inv_poly_mat)
fbar=waitbar(0,'解密中');
pause(0.02);
% 如果输入向量是单元格数组或没有16个元素
if iscell (ciphertext) || numel (ciphertext) ~= 16
error ('Ciphertext has to be a vector (not a cell array) with 16 elements.')
end
% 如果输入向量中的任何元素不能用8位表示
if any (ciphertext < 0 | ciphertext > 255)
error ('Elements of ciphertext vector have to be bytes (0 <= ciphertext(i) <= 255).')
end
% 如果展开的密钥数组是单元格数组或没有正确的大小
if iscell (w) || any (size (w) ~= [44, 4])
error ('w has to be an array (not a cell array) with [44 x 4] elements.')
end
% 如果扩展的密钥数组中的任何元素不能用8位表示
if any (w < 0 | w > 255)
error ('Elements of key array w have to be bytes (0 <= w(i,j) <= 255).')
end
%
% 复制输入向量的16个元素 逐列化为4 × 4状态矩阵
state = reshape (ciphertext, 4, 4);
round_key = (w(41:44, :))';
waitbar(1,fbar,'密文预处理完毕');
pause(0.02);
% % 将当前的密钥加(矩阵)添加到状态(矩阵)
state = app.add_round_key (state, round_key);
% 循环9轮
for i_round = 9 : -1 : 1
count=1;
waitbar(count/9,fbar,'循环处理中');
pause(0.005);
% 循环移动状态矩阵的最后三行
state = app.inv_shift_rows (state);
% 把状态矩阵的所有16个元素都放到s盒中
state = app.sub_bytes (state, inv_s_box);
% 从扩展赞密钥中提取当前的圆密钥(4 × 4矩阵)
round_key = (w((1:4) + 4*i_round, :))';
% % 将当前的密钥加(矩阵)添加到状态(矩阵)
state = app.add_round_key (state, round_key);
% 使用与密码中相同的函数(mix_columns),但使用逆多项式矩阵
state = app.mix_columns (state, inv_poly_mat);
count=count+1;
end
% 循环移动状态矩阵的最后三行
state = app.inv_shift_rows (state);
% 把状态矩阵的所有16个元素都放到s盒中
state = app.sub_bytes (state, inv_s_box);
% 从扩展赞密钥中提取当前的圆密钥(4 × 4矩阵)
round_key = (w(1:4, :))';
% 将当前的密钥加(矩阵)添加到状态(矩阵)
state = app.add_round_key (state, round_key);
% 将4 x 4状态矩阵重塑为16个元素的行向量
plaintext = reshape (state, 1, 16);
waitbar(1,fbar,'解密成功');
pause(0.02);
close(fbar);
end
介绍:初始化S盒,逆S盒,密钥加,多项式矩阵 function [s_box, inv_s_box, poly_mat, inv_poly_mat] = aes_initialisation(app)
% aes_initialisation.m 初始化AES,包括S盒,逆S盒,密钥加,多项式矩阵
% s_box S盒
% inv_s_box 逆S盒
% poly_mat 多项式矩阵
% inv_poly_mat 逆多项式矩阵
% 创建s盒和逆s盒
[s_box,inv_s_box] = app.s_box_gen ();
% 创建多项式变换矩阵和反多项式矩阵用于 MIX_COLUMNS 列混淆
[poly_mat, inv_poly_mat] = app.poly_mat_gen ();
end
介绍:其余辅助函数 function matrix_out = cycle (~,matrix_in, direction)
% cycle 循环移动状态矩阵的行
% 如果矩阵要向左移动
if strcmp (direction, 'left')
% 生成列向量[0 5 10 15]'
col = (0 : 5 : 15)';
% 如果矩阵要向右移动
else
% 生成列向量[16 13 10 7]'
col = (16 : -3 : 7)';
end
% 生成行向量 [0 4 8 12]
row = 0 : 4 : 12;
% 重复该列以创建矩阵
cols = repmat (col, 1, 4);
% 重复这一行来创建矩阵 [0 4 8 12]
rows = repmat (row, 4, 1);
% 将两个矩阵相加,折回0… 15域,加上1,因为Matlab的索引是从1开始的
ind_mat = mod (rows + cols, 16) + 1;
% 将刚刚创建的索引矩阵应用于输入矩阵
% 索引矩阵的元素是线性(按列排列)索引
matrix_out = matrix_in (ind_mat);
end
function disp_hex (~,string, hex_array)
% DISP_HEX 以十六进制形式显示数组
% 查找要显示的数组的行数和列数
[n_hex_array, m_hex_array] = size (hex_array);
% 找到标题字符串的长度
n_string = length (string);
% 创建一个标题字符串长度的空字符串
empty_string = ones (1, n_string)*' ';
% 遍历数组的每一行
for i = 1 : n_hex_array
if i == 1
line = string;
else
line = empty_string;
end
% 遍历数组的每一列
for j = 1 : m_hex_array
line = [line, lower(dec2hex(hex_array(i,j),2)), ' '];
end
% 显示
disp (line)
end
% 显示空(分隔)行
disp (' ')
end
function state_out = inv_shift_rows (app,state_in)
% inv_shift_rows 循环移动(回)状态矩阵的行
% 调用函数cycle来执行实际的右移
state_out = app.cycle (state_in, 'right');
end
function w = key_expansion (app,key, s_box, rcon)
fbar=waitbar(0,'密钥初始化中');
pause(0.03);
%KEY_EXPANSION 扩展16位的密钥
if iscell (key) || numel (key) ~= 16
error ('Key has to be a vector (not a cell array) with 16 elements.')
end
if any (key < 0 | key > 255)
error ('Elements of key vector have to be bytes (0 <= key(i) <= 255).')
end
w = (reshape (key, 4, 4))';
for i = 5 : 44
waitbar(i/44,fbar,'扩展中');
pause(0.1);
temp = w(i - 1, :);
if mod (i, 4) == 1
temp = app.rot_word (temp);
temp = app.sub_bytes (temp, s_box);
r = rcon ((i - 1)/4, :);
temp = bitxor (temp, r);
end
w(i, :) = bitxor (w(i - 4, :), temp);
end
waitbar(1,fbar,'密钥初始化完毕');
pause(0.03);
close(fbar);
end
function state_out = mix_columns (app,state_in, poly_mat)
% mix_columns 转换状态矩阵的每一列
% author:woha
% GF(2^8)域上的不可约多项式 x^8 + x^4 + x^3 + x + 1
mod_pol = bin2dec ('100011011');
% 变换循环遍历状态矩阵的所有列
for i_col_state = 1 : 4
% 变换循环遍历状态矩阵的所有行
for i_row_state = 1 : 4
% 初始化标量积累加器
temp_state = 0;
for i_inner = 1 : 4
% 乘法(GF(2^8)多项式乘法)
% poly_mat的当前行向量的当前元素
% 状态矩阵的当前列向量的当前元素
temp_prod = app.poly_mult (...
poly_mat(i_row_state, i_inner), ...
state_in(i_inner, i_col_state), ...
mod_pol);
% 将最近计算的乘积添加(XOR)到标量积累加器
temp_state = bitxor (temp_state, temp_prod);
end
%声明(保存并返回)最终的标量乘积累加器为当前状态矩阵元素
state_out(i_row_state, i_col_state) = temp_state;
end
end
end
function [poly_mat, inv_poly_mat] = poly_mat_gen (app)
fbar=waitbar(0,'(逆)多项式矩阵生成中');
pause(0.3);
% poly_mat_gen 创建多项式系数矩阵
%
% 在十六进制表示的MIX_COLUMNS中定义多项式系数矩阵的第一行
% 选择较小的值是为了计算速度的原因
row_hex = {'02' '03' '01' '01'};
% 将多项式系数转换为十进制“数”
% row = [2 3 1 1]
row = hex2dec (row_hex)';
% 构造一个有相同行的矩阵
% rows = [2 3 1 1]
% [2 3 1 1]
% [2 3 1 1]
% [2 3 1 1]
rows = repmat (row, 4, 1);
% 通过向右循环排列行来构造多项式矩阵
% poly_mat = [2 3 1 1]
% [1 2 3 1]
% [1 1 2 3]
% [3 1 1 2]
poly_mat = app.cycle (rows, 'right');
% 定义用十六进制表示的INV_MIX_COLUMNS中使用的逆多项式系数矩阵的第一行
inv_row_hex = {'0e' '0b' '0d' '09'};
% 将多项式系数转换为十进制“数”
inv_row = hex2dec (inv_row_hex)';
% 构造一个有相同行的矩阵
inv_rows = repmat (inv_row, 4, 1);
% 构造多项式矩阵
inv_poly_mat = app.cycle (inv_rows, 'right');
waitbar(1,fbar,'(逆)多项式矩阵生成完毕')
pause(0.02);
close(fbar);
end
function ab = poly_mult (~,a, b, mod_pol)
%POLY_MULT GF(2^8)的多项式模乘法
ab = 0;
for i_bit = 1 : 8
if bitget (a, i_bit)
b_shift = bitshift (b, i_bit - 1);
ab = bitxor (ab, b_shift);
end
end
for i_bit = 16 : -1 : 9
if bitget (ab, i_bit)
mod_pol_shift = bitshift (mod_pol, i_bit - 9);
ab = bitxor (ab, mod_pol_shift);
end
end
end
function rcon = rcon_gen (app)
% GF(2^8)第一轮常量的第一个字节是“1” 域上的不可约多项式 x^8 + x^4 + x^3 + x + 1
mod_pol = bin2dec ('100011011');
% 第一轮常量的第一个字节是“1”
rcon(1) = 1;
% 循环遍历圆形常量向量的其余元素
for i = 2 : 10
% 下一轮常数是前一轮的两倍; 模
rcon(i) = app.poly_mult (rcon(i-1), 2, mod_pol);
end
% 所有整数常量的另三个字节(LSB)是零
rcon = [rcon(:), zeros(10, 3)];
end
function w_out = rot_word (~,w_in)
% rot_word 旋转四个元素向量的元素
w_out = w_in([2 3 4 1]);
end
function [s_box, inv_s_box] = s_box_gen(app)
mod_pol = bin2dec ('100011011');
% 求乘法逆元
inverse(1) = 0; % 多项式00的乘法逆在这里被定义为零
% 遍历所有剩余的字节值 即i*inverse(i) = 1(mod mod_pol)
for i = 1 : 255
% 计算当前字节值相对于指定的模多项式的乘法逆
for j = 1:255
prod = app.poly_mult (i, j, mod_pol);
if prod == 1
inverse(i + 1) = j;
break
end
end
end
fbar=waitbar(0,'S(逆)盒生成中');
pause(0.02);
%% -----2、仿射变换
for i = 1 : 256
waitbar(i/256,fbar,'S盒生成中');
pause(0.005);
mod_pol = bin2dec ('100000001');
mult_pol = bin2dec ('00011111');
add_pol = bin2dec ('01100011');
temp = app.poly_mult (inverse(i), mult_pol, mod_pol);
% 加(异或)常数(加法多项式)
s_box(i) = bitxor (temp, add_pol);
end
waitbar(1,fbar,'S盒生成完毕');
pause(0.02);
% 通过取s盒中元素的值作为索引来创建逆s盒
for i = 1 : 256
waitbar(i/256,fbar,'逆S盒生成中');
pause(0.005);
% 例如:s_box(00hex) = 63hex ==>
% inv_s_box(63hex) = 00hex(除了Matlab矢量从1开始,…)
inv_s_box(s_box(i) + 1) = i - 1;
end
waitbar(1,fbar,'逆S盒生成完毕');
pause(0.02);
close(fbar);
end
function state_out = shift_rows (app,state_in)
% shift_rows 循环移动状态矩阵的行
% 调用函数循环来执行实际的左移
state_out = app.cycle (state_in, 'left');
end
function bytes_out = sub_bytes (~,bytes_in, s_box)
bytes_out = s_box (bytes_in + 1);
end
2. 加密过程 介绍:加密按钮EnButtom回调函数 function EnButtonPushed(app, event)
ifstrcmp(app.Plaintext_En.Value,'')
logRefresh_func_En(app,'请输入明文');
return
end
ifstrcmp(app.KeyWord.Value,'')
logRefresh_func_En(app,'请输入密钥');
return
end
if length(app.Plaintext_En.Value)~=32
logRefresh_func_En(app,'请输入32位明文字符(16进制)');
return
end
if length(app.KeyWord.Value)~=32
logRefresh_func_En(app,'请输入32位密钥字符(16进制)');
return
end
%处理明文177724136080E631CF4FB08FA77C00CE
plainText=app.Plaintext_En.Value;
plaintext_hex={};
for i=1:16
plaintext_hex{i}=plainText(2*i-1:2*i);
end
%初始化
[app.s_box,app.inv_s_box,app.poly_mat,app.inv_poly_mat]=app.aes_initialisation();
plaintext=hex2dec(plaintext_hex);
%处理密钥
% 定义一个十六进制(字符串)表示的任意16字节密钥
% 以下两个特定的密钥在aes -规范(草案)中用作示例
Key=app.KeyWord.Value;
key_hex={};
for i=1:16
key_hex{i}=Key(2*i-1:2*i);
end
% key_hex = {000102030405060708090a0b0c0d0e0f};
key=hex2dec(key_hex);
% 创建圆形常量数组
rcon=app.rcon_gen();
% 创建展开的密钥表
w=app.key_expansion(key,app.s_box,rcon);
% 使用扩展密钥、s盒和多项式变换矩阵将明文转换为密文
app.ciphertext=app.aes_encrypt(plaintext,w,app.s_box,app.poly_mat);
ciphertext_hex=dec2hex(app.ciphertext);
C='';
for i=1:16
C=strcat(C,ciphertext_hex(i,:));
end
% ciphertext_bin = dec2bin(ciphertext);
app.logRefresh_func_En('加密结束');
app.Crypt_En.Value=C;
app.Crypt_De.Value=C;
end
3. 解密过程 介绍:解密按钮DeButtom回调函数 function DeButtonPushed(app, event)
ifstrcmp(app.Crypt_De.Value,'')
logRefresh_func_De(app,'请输入密文');
return
end
ifstrcmp(app.KeyWord_De.Value,'')
logRefresh_func_De(app,'请输入密钥');
return
end
if length(app.Crypt_De.Value)~=32
logRefresh_func_De(app,'请输入32位密文字符(16进制)');
return
end
if length(app.KeyWord_De.Value)~=32
logRefresh_func_De(app,'请输入32位密钥字符(16进制)');
return
end
%处理密钥
% 定义一个十六进制(字符串)表示的任意16字节密钥
% 以下两个特定的密钥在aes -规范(草案)中用作示例
Key=app.KeyWord_De.Value;
key_hex={};
for i=1:16
key_hex{i}=Key(2*i-1:2*i);
end
% key_hex = {000102030405060708090a0b0c0d0e0f};
key=hex2dec(key_hex);
% 创建圆形常量数组
rcon=app.rcon_gen();
% 创建展开的密钥表
w=app.key_expansion(key,app.s_box,rcon);
re_plaintext=app.aes_decrypt(app.ciphertext,w,app.inv_s_box,app.inv_poly_mat);
re_plaintext=dec2hex(re_plaintext);
P='';
for i=1:16
P=strcat(P,re_plaintext(i,:));
end
app.logRefresh_func_De('解密结束');
app.Plaintext_De.Value=P;
end
4. 信息输出 介绍:加密界面信息输出函数logRefresh_func_En function logRefresh_func_En(app,StrArrayNew)
app.Ptime=datestr(now);
app.LOG=strcat('[',app.Ptime(end-7:end),']');
StrArrayNew=strcat(app.LOG,StrArrayNew);
app.StrArray_En=[app.StrArray_En,StrArrayNew,newline];
app.Process_En.Value=app.StrArray_En;
end
介绍:解密界面信息输出函数logRefresh_func_De function logRefresh_func_De(app,StrArrayNew)
app.Ptime=datestr(now);
app.LOG=strcat('[',app.Ptime(end-7:end),']');
StrArrayNew=strcat(app.LOG,StrArrayNew);
app.StrArray_De=[app.StrArray_De,StrArrayNew,newline];
app.Process_De.Value=app.StrArray_De;
end
5. 交互界面 Matlab2019b的mlapp开发环境
|