当前位置: 首页>编程语言>正文

matlab aes matlab aesencrypt函数

基于matlab2019b的mlapp



实验题目:AES

班级: 学号: 姓名:

一、实验目的

实验环境: Windows 11操作系统;Matlab2019b

实现目标:实现AES加解密;

实现加密解密交互界面;

实现加密解密关键步骤信息输出。

二、方案设计

AES加密密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_Powered by 金山文档,第1张

实验中采用128bit的AES加密算法,加密轮数10次

加密过程

  1. AES的处理单位是字节,128位的输入明文分组P和输入密钥K都被分成16个字节,分别记为P = P0 P1 … P15 和 K = K0 K1 … K15。
  2. AES的整体结构如下图所示,其中的W[0,3]是指W[0]、W[1]、W[2]和W[3]串联组成的128位密钥。加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_02,第2张

  1. 字节代换
  • 字节代换操作

AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒。矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。

  • 逆字节代换

逆字节代换也就是查逆S盒来变换,其变换方式同上

  1. 行位移
  • 行位移操作:行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节,以此类推
  • 逆行位移操作:行移位的逆变换是将状态矩阵中的每一行执行相反的移位操作,例如AES-128中,状态矩阵的第0行右移0字节,第1行右移1字节,第2行右移2字节,第3行右移3字节

  1. 列混合
  • 列混合操作:列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_03,第3张

  • 逆列混合操作:逆向列混合变换可由下图的矩阵乘法定义

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_04,第4张

  1. 轮密钥加:轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作,如下图所示(轮密钥加的逆运算同正向的轮密钥加运算完全一致,这是因为异或的逆操作是其自身)

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_05,第5张

  1. 密钥扩展:AES首先将初始密钥输入到一个44的状态矩阵中,如下图所示

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_06,第6张

解密过程

AES与DES一样,是一种对称加密体制,因此解密过程与加密过程高度对称。关键步骤已经在加密过程中解释,以下是解密流程:

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_Powered by 金山文档_07,第7张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_数组_08,第8张

3. 信息输出

  1. 设置两个信息输出函数,分别实现加密界面和解密界面的信息输出

4. 交互界面

  1. 基于Matlab2019b中的mlapp编程实现

三、方案实现

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开发环境

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_09,第9张

四、数据测试与分析

1. 数据测试

明文:177724136080E631CF4FB08FA77C00CE

密钥:000102030405060708090a0b0c0d0e0f

密文:0A3B2018250C1DF9FAD456A2E3503EE5

加密过程

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_10,第10张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_11,第11张

解密过程

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_12,第12张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_数组_13,第13张

加解密演示

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_14,第14张

2. 分析

AES加密算法也属于对称密码体系,加解密双方共享同一个密钥。在AES加密体系中,可以采用三种长度的密钥,本次实验中采用了128bit的密钥长度,对应的在加密过程中需要循环10次。加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作。这其中,字节代换、行位移、列混合、轮密钥加是循环加密过程中最为核心的部分。AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒。矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节,以此类推。行位移的逆操作相反。列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵。而轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作。经过10轮的循环加密后,便得到了最终的密文。对于解密操作,整体上是对称的。每轮解密操作中分别是逆字节代换、逆行位移、逆列混合、轮密钥加。但是需要注意,在第10轮解密操作中,不存在逆列混合操作。经过10轮的循环解密后,便得到最终的明文。

五、总结

  1. AES提出适用于代替已经不安全的DES算法的,二者均属于对称密码体制
  2. 在AES加密与解密操作中,每轮操作中涉及到关键的几个步骤。在加密步骤中,分别为:字节代换、行位移、列混合、轮密钥加。解密操作中,分别为:逆字节代换、逆行位移、逆列混合、轮密钥加。
  3. 需要格外注意的是,加密与解密操作中,第10轮加密或者解密中,不涉及到列混合或者逆列混合
  4. 此外,在AES中,列混合时看上去是矩阵乘法运算,但是实际上,这是一种特殊的运算,运算规则如下



matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_15,第15张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_16,第16张

  1. AES加密算法中,存在3中长度的密钥,分别是128位、192位或256位。密钥的长度不同,推荐加密轮数也不同。本次实验中选择使用了128bit的密钥,因此加密轮数为10轮
  2. 实验过程中,将S盒,逆S盒,密钥加,多项式矩阵的初始化全部编写在了函数中,供加密以及解密过程调用
  3. AES加密与解密过程比较复杂,涉及到了非常多的函数。在mlapp中,函数内部如果调用了全局函数的话,依旧使用app.前缀或是在参数中加入app来调用


基于matlab2019b的mlapp



实验题目:AES

班级: 学号: 姓名:

一、实验目的

实验环境: Windows 11操作系统;Matlab2019b

实现目标:实现AES加解密;

实现加密解密交互界面;

实现加密解密关键步骤信息输出。

二、方案设计

AES加密密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_Powered by 金山文档,第1张

实验中采用128bit的AES加密算法,加密轮数10次

加密过程

  1. AES的处理单位是字节,128位的输入明文分组P和输入密钥K都被分成16个字节,分别记为P = P0 P1 … P15 和 K = K0 K1 … K15。
  2. AES的整体结构如下图所示,其中的W[0,3]是指W[0]、W[1]、W[2]和W[3]串联组成的128位密钥。加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_02,第2张

  1. 字节代换
  • 字节代换操作

AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒。矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。

  • 逆字节代换

逆字节代换也就是查逆S盒来变换,其变换方式同上

  1. 行位移
  • 行位移操作:行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节,以此类推
  • 逆行位移操作:行移位的逆变换是将状态矩阵中的每一行执行相反的移位操作,例如AES-128中,状态矩阵的第0行右移0字节,第1行右移1字节,第2行右移2字节,第3行右移3字节

  1. 列混合
  • 列混合操作:列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_03,第3张

  • 逆列混合操作:逆向列混合变换可由下图的矩阵乘法定义

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_04,第4张

  1. 轮密钥加:轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作,如下图所示(轮密钥加的逆运算同正向的轮密钥加运算完全一致,这是因为异或的逆操作是其自身)

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_05,第5张

  1. 密钥扩展:AES首先将初始密钥输入到一个44的状态矩阵中,如下图所示

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_06,第6张

解密过程

AES与DES一样,是一种对称加密体制,因此解密过程与加密过程高度对称。关键步骤已经在加密过程中解释,以下是解密流程:

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_Powered by 金山文档_07,第7张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_数组_08,第8张

3. 信息输出

  1. 设置两个信息输出函数,分别实现加密界面和解密界面的信息输出

4. 交互界面

  1. 基于Matlab2019b中的mlapp编程实现

三、方案实现

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开发环境

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_09,第9张

四、数据测试与分析

1. 数据测试

明文:177724136080E631CF4FB08FA77C00CE

密钥:000102030405060708090a0b0c0d0e0f

密文:0A3B2018250C1DF9FAD456A2E3503EE5

加密过程

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_10,第10张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_11,第11张

解密过程

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_12,第12张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_数组_13,第13张

加解密演示

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_14,第14张

2. 分析

AES加密算法也属于对称密码体系,加解密双方共享同一个密钥。在AES加密体系中,可以采用三种长度的密钥,本次实验中采用了128bit的密钥长度,对应的在加密过程中需要循环10次。加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作。这其中,字节代换、行位移、列混合、轮密钥加是循环加密过程中最为核心的部分。AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒。矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节,以此类推。行位移的逆操作相反。列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵。而轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作。经过10轮的循环加密后,便得到了最终的密文。对于解密操作,整体上是对称的。每轮解密操作中分别是逆字节代换、逆行位移、逆列混合、轮密钥加。但是需要注意,在第10轮解密操作中,不存在逆列混合操作。经过10轮的循环解密后,便得到最终的明文。

五、总结

  1. AES提出适用于代替已经不安全的DES算法的,二者均属于对称密码体制
  2. 在AES加密与解密操作中,每轮操作中涉及到关键的几个步骤。在加密步骤中,分别为:字节代换、行位移、列混合、轮密钥加。解密操作中,分别为:逆字节代换、逆行位移、逆列混合、轮密钥加。
  3. 需要格外注意的是,加密与解密操作中,第10轮加密或者解密中,不涉及到列混合或者逆列混合
  4. 此外,在AES中,列混合时看上去是矩阵乘法运算,但是实际上,这是一种特殊的运算,运算规则如下



matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_15,第15张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_16,第16张

  1. AES加密算法中,存在3中长度的密钥,分别是128位、192位或256位。密钥的长度不同,推荐加密轮数也不同。本次实验中选择使用了128bit的密钥,因此加密轮数为10轮
  2. 实验过程中,将S盒,逆S盒,密钥加,多项式矩阵的初始化全部编写在了函数中,供加密以及解密过程调用
  3. AES加密与解密过程比较复杂,涉及到了非常多的函数。在mlapp中,函数内部如果调用了全局函数的话,依旧使用app.前缀或是在参数中加入app来调用


基于matlab2019b的mlapp



实验题目:AES

班级: 学号: 姓名:

一、实验目的

实验环境: Windows 11操作系统;Matlab2019b

实现目标:实现AES加解密;

实现加密解密交互界面;

实现加密解密关键步骤信息输出。

二、方案设计

AES加密密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_Powered by 金山文档,第1张

实验中采用128bit的AES加密算法,加密轮数10次

加密过程

  1. AES的处理单位是字节,128位的输入明文分组P和输入密钥K都被分成16个字节,分别记为P = P0 P1 … P15 和 K = K0 K1 … K15。
  2. AES的整体结构如下图所示,其中的W[0,3]是指W[0]、W[1]、W[2]和W[3]串联组成的128位密钥。加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_02,第2张

  1. 字节代换
  • 字节代换操作

AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒。矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。

  • 逆字节代换

逆字节代换也就是查逆S盒来变换,其变换方式同上

  1. 行位移
  • 行位移操作:行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节,以此类推
  • 逆行位移操作:行移位的逆变换是将状态矩阵中的每一行执行相反的移位操作,例如AES-128中,状态矩阵的第0行右移0字节,第1行右移1字节,第2行右移2字节,第3行右移3字节

  1. 列混合
  • 列混合操作:列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_03,第3张

  • 逆列混合操作:逆向列混合变换可由下图的矩阵乘法定义

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_04,第4张

  1. 轮密钥加:轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作,如下图所示(轮密钥加的逆运算同正向的轮密钥加运算完全一致,这是因为异或的逆操作是其自身)

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_05,第5张

  1. 密钥扩展:AES首先将初始密钥输入到一个44的状态矩阵中,如下图所示

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_06,第6张

解密过程

AES与DES一样,是一种对称加密体制,因此解密过程与加密过程高度对称。关键步骤已经在加密过程中解释,以下是解密流程:

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_Powered by 金山文档_07,第7张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_数组_08,第8张

3. 信息输出

  1. 设置两个信息输出函数,分别实现加密界面和解密界面的信息输出

4. 交互界面

  1. 基于Matlab2019b中的mlapp编程实现

三、方案实现

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开发环境

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_09,第9张

四、数据测试与分析

1. 数据测试

明文:177724136080E631CF4FB08FA77C00CE

密钥:000102030405060708090a0b0c0d0e0f

密文:0A3B2018250C1DF9FAD456A2E3503EE5

加密过程

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_10,第10张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_11,第11张

解密过程

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab_12,第12张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_数组_13,第13张

加解密演示

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_14,第14张

2. 分析

AES加密算法也属于对称密码体系,加解密双方共享同一个密钥。在AES加密体系中,可以采用三种长度的密钥,本次实验中采用了128bit的密钥长度,对应的在加密过程中需要循环10次。加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作。这其中,字节代换、行位移、列混合、轮密钥加是循环加密过程中最为核心的部分。AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒。矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节,以此类推。行位移的逆操作相反。列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵。而轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作。经过10轮的循环加密后,便得到了最终的密文。对于解密操作,整体上是对称的。每轮解密操作中分别是逆字节代换、逆行位移、逆列混合、轮密钥加。但是需要注意,在第10轮解密操作中,不存在逆列混合操作。经过10轮的循环解密后,便得到最终的明文。

五、总结

  1. AES提出适用于代替已经不安全的DES算法的,二者均属于对称密码体制
  2. 在AES加密与解密操作中,每轮操作中涉及到关键的几个步骤。在加密步骤中,分别为:字节代换、行位移、列混合、轮密钥加。解密操作中,分别为:逆字节代换、逆行位移、逆列混合、轮密钥加。
  3. 需要格外注意的是,加密与解密操作中,第10轮加密或者解密中,不涉及到列混合或者逆列混合
  4. 此外,在AES中,列混合时看上去是矩阵乘法运算,但是实际上,这是一种特殊的运算,运算规则如下



matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_matlab aes_15,第15张

matlab aes matlab aesencrypt函数,matlab aes matlab aesencrypt函数_ci_16,第16张

  1. AES加密算法中,存在3中长度的密钥,分别是128位、192位或256位。密钥的长度不同,推荐加密轮数也不同。本次实验中选择使用了128bit的密钥,因此加密轮数为10轮
  2. 实验过程中,将S盒,逆S盒,密钥加,多项式矩阵的初始化全部编写在了函数中,供加密以及解密过程调用
  3. AES加密与解密过程比较复杂,涉及到了非常多的函数。在mlapp中,函数内部如果调用了全局函数的话,依旧使用app.前缀或是在参数中加入app来调用



https://www.xamrdz.com/lan/5d71924458.html

相关文章: