三、方案实现
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)~= 16error('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:9waitbar(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) ~= 16error ('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 : 1count=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);endfunction 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_arrayif i == 1line = string;elseline = empty_string;end% 遍历数组的每一列for j = 1 : m_hex_arrayline = [line, lower(dec2hex(hex_array(i,j),2)), ' '];end% 显示disp (line)end% 显示空(分隔)行disp (' ')endfunction state_out = inv_shift_rows (app,state_in)% inv_shift_rows 循环移动(回)状态矩阵的行% 调用函数cycle来执行实际的右移state_out = app.cycle (state_in, 'right');endfunction w = key_expansion (app,key, s_box, rcon)fbar=waitbar(0,'密钥初始化中');pause(0.03);%KEY_EXPANSION 扩展16位的密钥if iscell (key) || numel (key) ~= 16error ('Key has to be a vector (not a cell array) with 16 elements.')endif any (key < 0 | key > 255)error ('Elements of key vector have to be bytes (0 <= key(i) <= 255).')endw = (reshape (key, 4, 4))';for i = 5 : 44waitbar(i/44,fbar,'扩展中');pause(0.1);temp = w(i - 1, :);if mod (i, 4) == 1temp = app.rot_word (temp);temp = app.sub_bytes (temp, s_box);r = rcon ((i - 1)/4, :);temp = bitxor (temp, r);endw(i, :) = bitxor (w(i - 4, :), temp);endwaitbar(1,fbar,'密钥初始化完毕');pause(0.03);close(fbar);endfunction state_out = mix_columns (app,state_in, poly_mat)% mix_columns 转换状态矩阵的每一列% author:woha% GF(2^8)域上的不可约多项式 x^8 + x^4 + x^3 + x + 1mod_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;endendendfunction [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);endfunction ab = poly_mult (~,a, b, mod_pol)%POLY_MULT GF(2^8)的多项式模乘法ab = 0;for i_bit = 1 : 8if bitget (a, i_bit)b_shift = bitshift (b, i_bit - 1);ab = bitxor (ab, b_shift);endendfor i_bit = 16 : -1 : 9if bitget (ab, i_bit)mod_pol_shift = bitshift (mod_pol, i_bit - 9);ab = bitxor (ab, mod_pol_shift);endendendfunction rcon = rcon_gen (app)% GF(2^8)第一轮常量的第一个字节是“1” 域上的不可约多项式 x^8 + x^4 + x^3 + x + 1mod_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)];endfunction w_out = rot_word (~,w_in)% rot_word 旋转四个元素向量的元素w_out = w_in([2 3 4 1]);endfunction [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:255prod = app.poly_mult (i, j, mod_pol);if prod == 1inverse(i + 1) = j;breakendendendfbar=waitbar(0,'S(逆)盒生成中');pause(0.02);%% -----2、仿射变换for i = 1 : 256waitbar(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);endwaitbar(1,fbar,'S盒生成完毕');pause(0.02);% 通过取s盒中元素的值作为索引来创建逆s盒for i = 1 : 256waitbar(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;endwaitbar(1,fbar,'逆S盒生成完毕');pause(0.02);close(fbar);endfunction state_out = shift_rows (app,state_in)% shift_rows 循环移动状态矩阵的行% 调用函数循环来执行实际的左移state_out = app.cycle (state_in, 'left');endfunction 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,'请输入明文');returnendifstrcmp(app.KeyWord.Value,'')logRefresh_func_En(app,'请输入密钥');returnendif length(app.Plaintext_En.Value)~=32logRefresh_func_En(app,'请输入32位明文字符(16进制)');returnendif length(app.KeyWord.Value)~=32logRefresh_func_En(app,'请输入32位密钥字符(16进制)');returnend%处理明文177724136080E631CF4FB08FA77C00CEplainText=app.Plaintext_En.Value;plaintext_hex={};for i=1:16plaintext_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:16key_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:16C=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,'请输入密文');returnendifstrcmp(app.KeyWord_De.Value,'')logRefresh_func_De(app,'请输入密钥');returnendif length(app.Crypt_De.Value)~=32logRefresh_func_De(app,'请输入32位密文字符(16进制)');returnendif length(app.KeyWord_De.Value)~=32logRefresh_func_De(app,'请输入32位密钥字符(16进制)');returnend%处理密钥% 定义一个十六进制(字符串)表示的任意16字节密钥% 以下两个特定的密钥在aes -规范(草案)中用作示例Key=app.KeyWord_De.Value;key_hex={};for i=1:16key_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:16P=strcat(P,re_plaintext(i,:));endapp.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开发环境
|