我必须使用AES256加密和解密图像。我正在研究下面的程序,它加密明文。
AES是一种具有128位固定长度输入的算法。它每轮都有四个不同的步骤; AES256有14轮,因为程序显示了不同类型的算法。
我正在寻找适用于任何长度大于128位的图像的主程序。我应该将它分成多个具有相同大小的块,还是有其他建议?
function [output] = aes(s, oper, mode, input, iv, sbit)
% AES Encrypt/decrypt array of bytes by AES.
% output = aes(s, oper, mode, input, iv, sbit)
% Encrypt/decrypt array of bytes by AES-128, AES-192, AES-256.
% All NIST SP800-38A cipher modes supported (e.g. ECB, CBC, OFB, CFB, CTR).
% Usage example: out = aesdecrypt(s, 'dec', 'ecb', data)
% s: AES structure (generated by aesinit)
% oper: operation:
% 'e', 'enc', 'encrypt', 'E',... = encrypt
% 'd', 'dec', 'decrypt', 'D',... = decrypt
% mode: operation mode
% 'ecb' = Electronic Codebook Mode
% 'cbc' = Cipher Block Chaining Mode
% 'cfb' = Cipher Feedback Mode
% 'ofb' = Output Feedback Mode
% 'ctr' = Counter Mode
% For counter mode you need external AES_GET_COUNTER()
% counter function.
% input: plaintext/ciphertext byte-vector with length
% multiple of 16
% iv: initialize vector - some modes need it
% ending initialize vector is stored in s.iv, so you
% can use aes() repetitively to encode/decode
% large vector:
% out = aes(s, 'enc', 'cbc', input1, iv);
% out = [out aes(s, 'enc', 'cbc', input1, s.iv)];
% ...
% sbit: bit-width parameter for CFB mode
% output: ciphertext/plaintext byte-vector
%
% See
% Morris Dworkin, Recommendation for Block Cipher Modes of Operation
% Methods and Techniques
% NIST Special Publication 800-38A, 2001 Edition
% for details.
error(nargchk(4, 6, nargin));
validateattributes(s, {'struct'}, {});
validateattributes(oper, {'char'}, {});
validateattributes(mode, {'char'}, {});
validateattributes(input, {'numeric'}, {'real', 'vector', '>=', 0, '<', 256});
if (nargin >= 5)
validateattributes(iv, {'numeric'}, {'real', 'vector', '>=', 0, '<', 256});
if (length(iv) ~= 16)
error('Length of ''iv'' must be 16.');
end
end
if (nargin >= 6)
validateattributes(sbit, {'numeric'}, {'real', 'scalar', '>=', 1, '<=', 128});
end
if (mod(length(input), 16))
error('Length of ''input'' must be multiple of 16.');
end
switch lower(oper)
case {'encrypt', 'enc', 'e'}
oper = 0;
case {'decrypt', 'dec', 'd'}
oper = 1;
otherwise
error('Bad ''oper'' parameter.');
end
blocks = length(input)/16;
input = input(:);
switch lower(mode)
case {'ecb'}
% Electronic Codebook Mode
% ------------------------
output = zeros(1,length(input));
idx = 1:16;
for i = 1:blocks
if (oper)
% decrypt
output(idx) = aesdecrypt(s,input(idx));
else
% encrypt
output(idx) = aesencrypt(s,input(idx));
end
idx = idx + 16;
end
case {'cbc'}
% Cipher Block Chaining Mode
% --------------------------
if (nargin < 5)
error('Missing initialization vector ''iv''.');
end
output = zeros(1,length(input));
ob = iv;
idx = 1:16;
for i = 1:blocks
if (oper)
% decrypt
in = input(idx);
output(idx) = bitxor(ob(:), aesdecrypt(s,in)');
ob = in;
else
% encrypt
ob = bitxor(ob(:), input(idx));
ob = aesencrypt(s, ob);
output(idx) = ob;
end
idx = idx + 16;
end
% store iv for block passing
s.iv = ob;
case {'cfb'}
% Cipher Feedback Mode
% --------------------
% Special mode with bit manipulations
% sbit = 1..128
if (nargin < 6)
error('Missing ''sbit'' parameter.');
end
% get number of bits
bitlen = 8*length(input);
% loop counter
rounds = round(bitlen/sbit);
% check
if (rem(bitlen, sbit))
error('Message length in bits is not multiple of ''sbit''.');
end
% convert input to bitstream
inputb = reshape(de2bi(input,8,2,'left-msb')',1,bitlen);
% preset init. vector
ib = iv;
ibb = reshape(de2bi(ib,8,2,'left-msb')',1,128);
% preset output binary stream
outputb = zeros(size(inputb));
for i = 1:rounds
iba = aesencrypt(s, ib);
% convert to bit, MSB first
ibab = reshape(de2bi(iba,8,2,'left-msb')',1,128);
% strip only sbit MSB bits
% this goes to xor
ibab = ibab(1:sbit);
% strip bits from input
inpb = inputb((i - 1)*sbit + (1:sbit));
% make xor
outb = bitxor(ibab, inpb);
% write to output
outputb((i - 1)*sbit + (1:sbit)) = outb;
if (oper)
% decrypt
% prepare new iv - bit shift
ibb = [ibb((1 + sbit):end) inpb];
else
% encrypt
% prepare new iv - bit shift
ibb = [ibb((1 + sbit):end) outb];
end
% back to byte ary
ib = bi2de(vec2mat(ibb,8),'left-msb');
% loop
end
output = bi2de(vec2mat(outputb,8),'left-msb');
% store iv for block passing
s.iv = ib;
case {'ofb'}
% Output Feedback Mode
% --------------------
if (nargin < 5)
error('Missing initialization vector ''iv''.');
end
output = zeros(1,length(input));
ib = iv;
idx = 1:16;
for i = 1:blocks
% encrypt, decrypt
ib = aesencrypt(s, ib);
output(idx) = bitxor(ib(:), input(idx));
idx = idx + 16;
end
% store iv for block passing
s.iv = ib;
case {'ctr'}
% Counter Mode
% ------------
if (nargin < 5)
iv = 1;
end
output = zeros(1,length(input));
idx = 1:16;
for i = (iv):(iv + blocks - 1)
ib = AES_GET_COUNTER(i);
ib = aesencrypt(s, ib);
output(idx) = bitxor(ib(:), input(idx));
idx = idx + 16;
end
s.iv = iv + blocks;
otherwise
error('Bad ''oper'' parameter.');
end
aesencrypt功能:
function [out] = aesencrypt(s, in)
% AESENCRYPT Encrypt 16-bytes vector.
% Usage: out = aesencrypt(s, in)
% s: AES structure
% in: input 16-bytes vector (plaintext)
% out: output 16-bytes vector (ciphertext)
if (nargin ~= 2)
error('Bad number of input arguments.');
end
validateattributes(s, {'struct'}, {});
validateattributes(in, {'numeric'}, {'real','uint8'});
% copy input to local
% 16 -> 4 x 4
state = reshape(in, 4, 4);
% Initial round
% AddRoundKey keyexp(1:4)
state = bitxor(state, (s.keyexp(1:4, :))');
% Loop over (s.rounds - 1) rounds
for i = 1:(s.rounds - 1)
% SubBytes - lookup table
state = s.s_box(state + 1);
% ShiftRows
state = shift_rows(state, 0);
% MixColumns
state = mix_columns(state, s);
% AddRoundKey keyexp(i*4 + (1:4))
state = bitxor(state, (s.keyexp((1:4) + 4*i, :))');
end
% Final round
% SubBytes - lookup table
state = s.s_box(state + 1);
% ShiftRows
state = shift_rows(state, 0);
% AddRoundKey keyexp(4*s.rounds + (1:4))
state = bitxor(state, (s.keyexp(4*s.rounds + (1:4), :))');
% copy local to output
% 4 x 4 -> 16
out = reshape(state, 1, 16);
功能aesinit:
function s = aesinit(key)
% AESINIT Generate structure with s-boxes, expanded key, etc.
% Usage: s = aesinit([23 34 168 ... 39])
% key: 16 (AES-128), 24 (AES-192), and 32 (AES-256)
% items array with bytes of key
% s: AES structure for AES parameters and tables
% Stepan Matejka, 2011, matejka[at]feld.cvut.cz
% $Revision: 1.1.0 $ $Date: 2011/10/12 $
validateattributes(key,...
{'numeric'},...
{'real', 'vector', '>=', 0, '<=', 255});
key = key(:);
lengthkey = length(key);
switch (lengthkey)
case 16
rounds = 10;
case 24
rounds = 12;
case 32
rounds = 14;
otherwise
error('Only AES-128, AES-192, and AES-256 are supported.');
end
% fill s structure
s = {};
s.key = key;
s.bytes = lengthkey;
s.length = lengthkey * 8;
s.rounds = rounds;
% irreducible polynomial for multiplication in a finite field 0x11b
% bin2dec('100011011');
s.mod_pol = 283;
% s-box method 1 (slow)
% ---------------------
% % multiplicative inverse table
% % first is zero, calculate rest
% inverse = zeros(1,256);
% for i = 2:256
% inverse(i) = find_inverse(i - 1, s.mod_pol);
% end
%
% % generate s-box
% s_box = zeros(1,256);
% for i = 1:256
% % affine transformation
% s_box(i) = aff_trans(inverse(i));
% end
% s.s_box = s_box;
%
% % generate inverse s-box
% inv_s_box(s_box(1:256) + 1) = (1:256) - 1;
% s.inv_s_box = inv_s_box;
% s-box method 2 (faster)
% -----------------------
% first build logarithm lookup table and it's inverse
aes_logt = zeros(1,256);
aes_ilogt = zeros(1,256);
gen = 1;
for i = 0:255
aes_logt(gen + 1) = i;
aes_ilogt(i + 1) = gen;
gen = poly_mult(gen, 3, s.mod_pol);
end
% store log tables
s.aes_logt = aes_logt;
s.aes_ilogt = aes_ilogt;
% build s-box and it's inverse
s_box = zeros(1,256);
loctable = [1 2 4 8 16 32 64 128 1 2 4 8 16 32 64 128];
for i = 0:255
if (i == 0)
inv = 0;
else
inv = aes_ilogt(255 - aes_logt(i + 1) + 1);
end
temp = 0;
for bi = 0:7
temp2 = sign(bitand(inv, loctable(bi + 1)));
temp2 = temp2 + sign(bitand(inv, loctable(bi + 4 + 1)));
temp2 = temp2 + sign(bitand(inv, loctable(bi + 5 + 1)));
temp2 = temp2 + sign(bitand(inv, loctable(bi + 6 + 1)));
temp2 = temp2 + sign(bitand(inv, loctable(bi + 7 + 1)));
temp2 = temp2 + sign(bitand(99, loctable(bi + 1)));
if (rem(temp2,2))
temp = bitor(temp, loctable(bi + 1));
end
end
s_box(i + 1) = temp;
end
inv_s_box(s_box(1:256) + 1) = (0:255);
% table correction (must be)
s_box(1 + 1) = 124;
inv_s_box(124 + 1) = 1;
inv_s_box(99 + 1) = 0;
s.s_box = s_box;
s.inv_s_box = inv_s_box;
% tables for fast MixColumns
mix_col2 = zeros(1,256);
mix_col3 = mix_col2;
mix_col9 = mix_col2;
mix_col11 = mix_col2;
mix_col13 = mix_col2;
mix_col14 = mix_col2;
for i = 1:256
mix_col2(i) = poly_mult(2, i - 1, s.mod_pol);
mix_col3(i) = poly_mult(3, i - 1, s.mod_pol);
mix_col9(i) = poly_mult(9, i - 1, s.mod_pol);
mix_col11(i) = poly_mult(11, i - 1, s.mod_pol);
mix_col13(i) = poly_mult(13, i - 1, s.mod_pol);
mix_col14(i) = poly_mult(14, i - 1, s.mod_pol);
end
s.mix_col2 = mix_col2;
s.mix_col3 = mix_col3;
s.mix_col9 = mix_col9;
s.mix_col11 = mix_col11;
s.mix_col13 = mix_col13;
s.mix_col14 = mix_col14;
% expanded key
s.keyexp = key_expansion(s.key, s.s_box, s.rounds, s.mod_pol, s.aes_logt, s.aes_ilogt);
% poly & invpoly
s.poly_mat = [...
2 3 1 1;...
1 2 3 1;...
1 1 2 3;...
3 1 1 2];
s.inv_poly_mat =[...
14 11 13 9;...
9 14 11 13;...
13 9 14 11;...
11 13 9 14];
% end of aesinit.m
% ------------------------------------------------------------------------
function p = poly_mult(a, b, mod_pol)
% Multiplication in a finite field
% For loop multiplication - slower than log/ilog tables
% but must be used for log/ilog tables generation
p = 0;
for counter = 1 : 8
if (rem(b, 2))
p = bitxor(p, a);
b = (b - 1)/2;
else
b = b/2;
end
a = 2*a;
if (a > 255)
a = bitxor(a, mod_pol);
end
end
% ------------------------------------------------------------------------
function inv = find_inverse(in, mod_pol)
% Multiplicative inverse for an element a of a finite field
% very bad calculate & test method
% Not used in faster version
% loop over all possible bytes
for inv = 1 : 255
% calculate polynomial multiplication and test to be 1
if (1 == poly_mult(in, inv, mod_pol))
% we find it
break
end
end
inv = 0;
% ------------------------------------------------------------------------
function out = aff_trans(in)
% Affine transformation over GF(2^8)
% Not used for faster s-box generation
% modulo polynomial for multiplication in a finite field
% bin2dec('100000001');
mod_pol = 257;
% multiplication polynomial
% bin2dec('00011111');
mult_pol = 31;
% addition polynomial
% bin2dec('01100011');
add_pol = 99;
% polynomial multiplication
temp = poly_mult(in, mult_pol, mod_pol);
% xor with addition polynomial
out = bitxor(temp, add_pol);
% ------------------------------------------------------------------------
function expkey = key_expansion(key, s_box, rounds, mod_pol, aes_logt, aes_ilogt)
% Expansion of key
% This is old version for AES-128 (192?, 256? not tested):
% rcon = ones(1,rounds);
% for i = 2:rounds
% rcon(i) = poly_mult(rcon(i - 1), 2, mod_pol);
% end
% % fill bytes 2, 3, and 4 by 0
% rcon = [rcon(:), zeros(rounds, 3)];
%
% kcol = length(key)/4;
% expkey = (reshape(key, kcol, 4))';
% for i = (kcol + 1):(4*rounds + 4)
% % copy the previous row of the expanded key into a buffer
% temp = expkey(i - 1, :);
% % each fourth row
% if (mod(i, 4) == 1)
% % shift temp
% temp = temp([2 3 4 1]);
% % s-box transform
% temp = s_box(temp + 1);
% % compute the current round constant
% r = rcon((i - 1)/4, :);
% % xor
% temp = bitxor(temp, r);
% else
% if ((kcol > 6) && (mod(i, kcol) == 0))
% temp = s_box(temp);
% end
% end
% % generate new row of the expanded key
% expkey(i, :) = bitxor(expkey(i - 4, :), temp);
% end
% This is new faster version for all AES:
rcon = 1;
kcol = length(key)/4;
expkey = (reshape(key,4,kcol))';
% traverse for all rounds
for i = kcol:(4*(rounds + 1) - 1)
% copy the previous row of the expanded key into a buffer
temp = expkey(i, :);
% each kcol row
if (mod(i, kcol) == 0)
% rotate word
temp = temp([2 3 4 1]);
% s-box transform
temp = s_box(temp + 1);
% xor
temp(1) = bitxor(temp(1), rcon);
% new rcon
% 1. classic poly_mult
% rcon = poly_mult(rcon, 2, mod_pol);
% 2. or faster version with log/ilog tables
% note rcon is never zero here
% rcon = aes_ilogt(mod((aes_logt(rcon + 1) + aes_logt(2 + 1)), 255) + 1);
rcon = aes_ilogt(mod((aes_logt(rcon + 1) + 25), 255) + 1);
else
if ((kcol > 6) && (mod(i, kcol) == 4))
temp = s_box(temp + 1);
end
end
% generate new row of the expanded key
expkey(i + 1, :) = bitxor(expkey(i - kcol + 1, :), temp);
end
答案 0 :(得分:1)
由于您尝试使用aesencrypt
,one of the low level functions which work on 4x4 blocks加密,因此限制为128位。如果你改为使用aes
函数,你可以编码长度为16&#34;的任何&#34;字节向量。它将为您重复调用aesenrypt
,直到处理完所有4x4块。