密码学基础(二):对称加密
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了密码学基础(二):对称加密相关的知识,希望对你有一定的参考价值。
参考技术A加密和解密使用相同的秘钥称为对称加密。
DES:已经淘汰
3DES:相对于DES有所加强,但是仍然存在较大风险
AES:全新的对称加密算法。
特点决定使用场景,对称加密拥有如下特点:
速度快,可用于频率很高的加密场景。
使用同一个秘钥进行加密和解密。
可选按照128、192、256位为一组的加密方式,加密后的输出值为所选分组位数的倍数。密钥的长度不同,推荐加密轮数也不同,加密强度也更强。
例如:
AES加密结果的长度由原字符串长度决定:一个字符为1byte=4bit,一个字符串为n+1byte,因为最后一位为\'\\0\',所以当字符串长度小于等于15时,AES128得到的16进制结果为32位,也就是32 4=128byte,当长度超过15时,就是64位为128 2byte。
因为对称加密速度快的特点,对称加密被广泛运用在各种加密场所中。但是因为其需要传递秘钥,一旦秘钥被截获或者泄露,其加密就会玩完全破解,所以AES一般和RSA一起使用。
因为RSA不用传递秘钥,加密速度慢,所以一般使用RSA加密AES中锁使用的秘钥后,再传递秘钥,保证秘钥的安全。秘钥安全传递成功后,一直使用AES对会话中的信息进行加密,以此来解决AES和RSA的缺点并完美发挥两者的优点,其中相对经典的例子就是HTTPS加密,后文会专门研究。
本文针对ECB模式下的AES算法进行大概讲解,针对每一步的详细算法不再该文讨论范围内。
128位的明文被分成16个字节的明文矩阵,然后将明文矩阵转化成状态矩阵,以“abcdefghijklmnop”的明文为例:
同样的,128位密钥被分成16组的状态矩阵。与明文不同的是,密文会以列为单位,生成最初的4x8x4=128的秘钥,也就是一个组中有4个元素,每个元素由每列中的4个秘钥叠加而成,其中矩阵中的每个秘钥为1个字节也就是8位。
生成初始的w[0]、w[1]、w[2]、w[3]原始密钥之后,通过密钥编排函数,该密钥矩阵被扩展成一个44个组成的序列W[0],W[1], … ,W[43]。该序列的前4个元素W[0],W[1],W[2],W[3]是原始密钥,用于加密运算中的初始密钥加,后面40个字分为10组,每组4个32位的字段组成,总共为128位,分别用于10轮加密运算中的轮密钥加密,如下图所示:
之所以把这一步单独提出来,是因为ECB和CBC模式中主要的区别就在这一步。
ECB模式中,初始秘钥扩展后生成秘钥组后(w0-w43),明文根据当前轮数取出w[i,i+3]进行加密操作。
CBC模式中,则使用前一轮的密文(明文加密之后的值)和当前的明文进行异或操作之后再进行加密操作。如图所示:
根据不同位数分组,官方推荐的加密轮数:
轮操作加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。
当第一组加密完成时,后面的组循环进行加密操作知道所有的组都完成加密操作。
一般会将结果转化成base64位,此时在ios中应该使用base64编码的方式进行解码操作,而不是UTF-8。
base64是一种编码方式,常用语传输8bit字节码。其编码原理如下所示:
将原数据按照3个字节取为一组,即为3x8=24位
将3x8=24的数据分为4x6=24的数据,也就是分为了4组
将4个组中的数据分别在高位补上2个0,也就成了8x4=32,所以原数据增大了三分之一。
根据base64编码表对数据进行转换,如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办,Base64用\\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。
举个栗子:Man最后的结果就是TWFu。
计算机中所有的数据都是以0和1的二进制来存储,而所有的文字都是通过ascii表转化而来进而显示成对应的语言。但是ascii表中存在许多不可见字符,这些不可见字符在数据传输时,有可能经过不同硬件上各种类型的路由,在转义时容易发生错误,所以规定了64个可见字符(a-z、A-Z、0-9、+、/),通过base64转码之后,所有的二进制数据都是可见的。
ECB和CBC是两种加密工作模式。其相同点都是在开始轮加密之前,将明文和密文按照128/192/256进行分组。以128位为例,明文和密文都分为16组,每组1个字节为8位。
ECB工作模式中,每一组的明文和密文相互独立,每一组的明文通过对应该组的密文加密后生成密文,不影响其他组。
CBC工作模式中,后一组的明文在加密之前先使用前一组的密文进行异或运算后再和对应该组的密文进行加密操作生成密文。
为简单的分组加密。将明文和密文分成若干组后,使用密文对明文进行加密生成密文
CBC
加密:
解密:
密码学基础(对称加密和非对称加密)
密码学基础
分类
一般分为:
- 对称加密
- 非对称加密
对称加密
加密和解密使用的是同一个密钥或者,两者可以互相推导得出,则认为是对称加密,如DES,AES,3DES
在传输数据时用密钥将数据加密,然后将密文发给接收方,接收方再使用该密钥解密数据。这样就要求接收方需要知道密钥,如果接收方需要接受1万个用户的数据的话就需要知道1万个密钥,并且密钥容易泄漏。
非对称加密
加密和解密的密钥不同,且知道其中一个密钥不能得知另一个密钥,一般用来加密的密钥称作公钥,用来解密的密钥称作私钥,如RSA,ECC
在需要传输数据给某用户时,就使用该用户的公钥对数据加密得到密文发给用户,用户用自己的私钥来解密密文得到数据 。
两类加密的特点
- 对称加密安全性差,但是效率高
- 非对称加密安全性好,但是加密效率低
结合使用
在传输一个比较大的数据时,可以先用对称加密来加密数据,对称加密的密钥假如为X,再用非对称加密将X加密。
举例
凯撒密码
凯撒密码是对称密码,其密钥是0-26的一个整数key,加密是将每个字母往后推移key个字母
比如密钥为3,明文为a,则密文就是d
代码实现-加密
//加密
public static String encryption(String txt,int key)
if (key<0||key>26)
return null;
char[] result=txt.toCharArray();
int intA=65;
int inta=97;
for (int i=0;i<result.length;i++)
if (result[i]>'A'&&result[i]<'Z')
result[i] =(char)(((int)result[i]+key-intA)%26+intA);
else if (result[i]>'a'&&result[i]<'z')
result[i] =(char)(((int)result[i]+key-inta)%26+inta);
else;
return new String(result);
代码实现-解密
//解密,调用加密的函数
public static String decrypting(String txt,int key)
if (key<0||key>26)
return null;
return encryption(txt,26-key);
main函数及文件加密
public static void main(String[] args)
Scanner scanner=new Scanner(System.in);
int choose=0;
System.out.println("加密输入1,解密输入2:");
choose=scanner.nextInt();
if (choose==1)
System.out.println("输入密钥(0-26):");
int key=scanner.nextInt();
String pathname="/new/IdeaProjects/StudyTest/test.txt";
String oriText=getFileText(pathname);
String ciphertext=encryption(oriText,key);
System.out.println(pathname+"加密完成!");
System.out.println("使用密钥:"+key+"加密后得到密文为:");
System.out.println(ciphertext);
String pathname2="/new/IdeaProjects/StudyTest/ciphertext.txt";
if (printToFile(ciphertext,pathname2))
System.out.println("密文保存在:"+pathname2);
return;
else
System.out.println("密文保存失败!");
return;
else if (choose==2)
System.out.println("输入密钥(0-26):");
int key=scanner.nextInt();
String pathname2="/new/IdeaProjects/StudyTest/ciphertext.txt";
String cipherText=getFileText(pathname2);
String oriText=decrypting(cipherText,key);
System.out.println("使用密钥:"+key+"解密完成,明文为:");
System.out.println(oriText);
else
return;
//读文件
public static String getFileText(String pathname)
File file=new File(pathname);
String str="";
try
Scanner scanner = new Scanner(file);
while(scanner.hasNext())
str=str+" "+scanner.next();
scanner.close();
catch (FileNotFoundException e)
System.out.println("file not found.");
return str;
//写文件
public static boolean printToFile(String str,String pathname)
File file = new File(pathname);// 要写入的文件路径
if (!file.exists()) // 判断文件是否存在
try
file.createNewFile();// 如果文件不存在创建文件
System.out.println("文件"+file.getName()+"已为您创建!");
catch (IOException e)
System.out.println("创建文件异常!");
e.printStackTrace();
return false;
else
System.out.println("文件"+file.getName()+"已存在!");
FileOutputStream fos = null;
PrintStream ps = null;
try
fos = new FileOutputStream(file,true);// 文件输出流 追加
ps = new PrintStream(fos);
catch (FileNotFoundException e)
e.printStackTrace();
String string = str + "\\r\\n";// +换行
ps.print(string); // 执行写操作
ps.close(); // 关闭流
return true;
以上是关于密码学基础(二):对称加密的主要内容,如果未能解决你的问题,请参考以下文章