来自信息安全的作业。
使用说明:运行时只需要输入密钥,加密文本以 txt 形式存储当前文件夹的 world.txt(用户自己创建,内容尽量为英文字母)
结果都保存在了 key 类里面,为了简化问题,字母都转换为了大写的。
运行结果示意:
生成的密钥矩阵:
填充后的原文与密文的对比
% 2019-4-30
clear all;
key.K=input('密钥输入:');
if sum(isletter(key.K))~=length(key.K) % 先对输入密钥合法性进行判断
error('输入应为字母!');
end
key.info=textread('world.txt','%s','delimiter','\n');
changed1=88;% 将 X 替换掉相同的字符
changed2=90; % 替换的备选 Z 字符
key.len=length(key.info);
key.serial=[]; % 记录要加密的文本信息
count=1;
for i=1:key.len % 先将文本里的所有字母检索出来,保存的是ascii码
row=char(key.info(i));% 读出来的是double 类型的数据
for j=1:length(row)
if isletter(row(j))
key.serial(count)=(row(j));
count=count+1;
end
end
end
% 编码组的改变,将所有的字母改变为大写
key.K=upper(char(key.K));
key.serial=upper(char(key.serial));
% 剔除K里面的重复字符
key.single=[];
index=1;
len=26;
ascii_begin=64;
list=1:len;
list=[list;zeros(1,len)];
key.Klen=length(key.K);
key.strlen=length(key.serial);
% 去掉密钥中的重复字符串
for i=1:key.Klen
if list(2,double(key.K(i))-ascii_begin)==0
list(2,double(key.K(i))-ascii_begin)=1;
key.single(index)=key.K(i); % 保存的是ASCII码
index=index+1;
elseif list(2,double(key.K(i))-ascii_begin)==1
continue;
end
end
key.siglen=index-1; % 密钥不重复的索引
% 生成m密钥字典
key.matrix=[[1:9],[11:26]]+ascii_begin; % 将i j视为一个
matrixside=5;
matrixlen=25;
unit_J=74;
unit_I=73;
% key.matrix=reshape([1:25]+ascii_begin,5,5)'
for i=1:key.siglen % 检索合并后的密钥,去除掉重复性的字符
unit=key.single(i);
if unit==unit_J % 将中间的 i 与 j 合并起来
unit=unit_I;
end
n=find(unit==key.matrix);
key.matrix(i+1:n)=key.matrix(i:n-1);% 排序直接位移
key.matrix(i)=unit;
end
% 利用密钥字典完成对文章的加密;
key.matrix=reshape(key.matrix,matrixside,matrixside)';
key.demo=[];
index=1;i=1;
while (i<=key.strlen) % 完成字符的预分配
if i==key.strlen
key.demo(index)=key.serial(i);
break;
end
if (i<key.strlen)
if (key.serial(i)==key.serial(i+1))
key.demo(index)=key.serial(i);
index=index+1;
if key.serial(i)~= changed1
key.demo(index)=changed1;
index=index+1;
else
key.demo(index)=changed2; % 解码复杂
index=index+1;
end
else
key.demo(index)=key.serial(i);
index=index+1;
key.demo(index)=key.serial(i+1);
index=index+1;
i=i+1;
end
end
i=i+1;
end
% 补齐长度 将源信息进行保留,操作复制的信息
key.copy=double(key.demo);
key.strlen=length(key.demo);
key.coding=[];% 记录加密结果
index=1;
if mod(key.strlen,2)==1 % 使整个序列为偶数
key.strlen=key.strlen+1;
key.copy=[key.copy,changed1];
end
% 密码加密
for j=1:2:key.strlen
if key.copy(j)==unit_J % 先完成i j的判断
key.copy(j)=unit_I;
end
if key.copy(j+1)==unit_J
key.copy(j+1)=unit_I;
end
% if (key.copy(j)==key.copy(j+1))&(key.copy(j)~=changed1)
% key.copy(j+1)=changed1;
% elseif (key.copy(j)==key.copy(j+1))&(key.copy(j)==changed1)
% % 如果出现重复字符与X 相同使用备选方案
% key.copy(j+1)=changed2;
% end
[row1,column1]=find(key.copy(j)==key.matrix);
[row2,column2]=find(key.copy(j+1)==key.matrix); % mod(5,5)=0 !!! bug
if (row1==row2) & (column1~=column2) % 只位于同行,取右边的序列
if column1+1==matrixside
key.coding(index)=key.matrix(row1,matrixside);
index=index+1;
key.coding(index)=key.matrix(row1,mod(column2+1,matrixside));
index=index+1;
elseif column2+1==matrixside
key.coding(index)=key.matrix(row1,mod(column1+1,matrixside));
index=index+1;
key.coding(index)=key.matrix(row1,matrixside);
index=index+1;
else % 只有一个属性相同
key.coding(index)=key.matrix(row1,mod(column1+1,matrixside));
index=index+1;
key.coding(index)=key.matrix(row1,mod(column2+1,matrixside));
index=index+1;
end
elseif (column1==column2) &(row1~=row2) % 只位于同列,取下边的序列
if row1+1==matrixside
key.coding(index)=key.matrix(matrixside,column1);
index=index+1;
key.coding(index)=key.matrix(mod(row2+1,matrixside),column1);
index=index+1;
elseif row2+1==matrixside
key.coding(index)=key.matrix(mod(row1+1,matrixside),column1);
index=index+1;
key.coding(index)=key.matrix(matrixside,column1);
index=index+1;
else % 只有一个属性相同
key.coding(index)=key.matrix(mod(row1+1,matrixside),column1);
index=index+1;
key.coding(index)=key.matrix(mod(row2+1,matrixside),column1);
index=index+1;
end
else % 完全不同的现象
key.coding(index)=key.matrix(row1,column2);
index=index+1;
key.coding(index)=key.matrix(row2,column1);
index=index+1;
end
end
key.chmatrix=char(key.matrix);
key.match=[char(key.copy);char(key.coding)];
key.rematch=[char(regexp(key.match(1,:),'\w{0,2}','match')),char(ones(key.strlen/2,1)*60),...
char(ones(key.strlen/2,1)*61),char(ones(key.strlen/2,1)*62),...
char(regexp(key.match(2,:),'\w{0,2}','match'))];
key.decoding=[];
index=1;
for j=1:2:key.strlen % 就是对上述过程的一个反变换,注意边界与顺序,解密过程
[row1,column1]=find(key.coding(j)==key.matrix);
[row2,column2]=find(key.coding(j+1)==key.matrix);
if (row1==row2) & (column1~=column2) % 只位于同行,取右边的序列
if column1-1==0
key.decoding(index)=key.matrix(row1,matrixside);
index=index+1;
key.decoding(index)=key.matrix(row1,mod(column2-1,matrixside));
index=index+1;
elseif column2-1==0
key.decoding(index)=key.matrix(row1,mod(column1-1,matrixside));
index=index+1;
key.decoding(index)=key.matrix(row1,matrixside);
index=index+1;
else % 只有一个属性相同
key.decoding(index)=key.matrix(row1,mod(column1-1,matrixside));
index=index+1;
key.decoding(index)=key.matrix(row1,mod(column2-1,matrixside));
index=index+1;
end
elseif (column1==column2) &(row1~=row2) % 只位于同列,取下边的序列
if row1-1==0
key.decoding(index)=key.matrix(matrixside,column1);
index=index+1;
key.decoding(index)=key.matrix(mod(row2-1,matrixside),column1);
index=index+1;
elseif row2-1==0
key.decoding(index)=key.matrix(mod(row1-1,matrixside),column1);
index=index+1;
key.decoding(index)=key.matrix(matrixside,column1);
index=index+1;
else % 只有一个属性相同
key.decoding(index)=key.matrix(mod(row1-1,matrixside),column1);
index=index+1;
key.decoding(index)=key.matrix(mod(row2-1,matrixside),column1);
index=index+1;
end
else % 完全不同的现象
key.decoding(index)=key.matrix(row1,column2);
index=index+1;
key.decoding(index)=key.matrix(row2,column1);
index=index+1;
end
end
key.decoded=[];
index=1;
delete=[];
for i=2:key.strlen-1 % 只完成了对于插入X的信息判断,对于重复性的东西,没弄
if key.decoding(i)==changed1 && (key.decoding(i-1)==key.decoding(i+1))
delete(index)=i;
index=index+1;
end
end
if (key.decoding(key.strlen)==changed1)
delete(index)=key.strlen;
end
copy=key.decoding;
copy(delete)=[];
key.decoded=char(copy);