懂了!国际算法体系对称算法DES原理
概念
加密领域主要有国际算法和国密算法两种体系。国密算法是国家密码局认定的国产密码算法。国际算法是由美国安全局发布的算法。由于国密算法安全性高等一系列原因。国内的银行和支付机构都推荐使用国密算法。

从上图可知,对称加密算法在算法体系里占了半壁江山。因为国际和国密算法的过程差异并不大。只是应用的数学公式和秘钥位数不同。DES在里面算是基础,所以今天主要介绍一下DES的原理。
原理
密码
咱们从加密的原理说起。举个最简单的加密:
我有一段明文:520
我的秘钥是:221
我的加密算法是:加法
加密后的密文就是:741
如果这个密文被截获了,接受者看到的信息是:741(气死你),和原来明文520是完全不同的,不能知道信息原有的意思。
从这个简单的例子可知:加密是包含:明文、秘钥、加密算法和密文四个要素的。加密算法可公开可不公开,常见的算法有:位移、循环位移、异或、置换、数学函数。
凯撒密码
加密技术从古罗马凯撒时候就在用:凯撒密码

凯撒密码是古罗马时期凯撒大帝和他的将军们通信时使用的加密方式:
明文:由26个字母组成
秘钥:1到25之间的任意数字
加密算法:循环位移
密文:举例明文为eat 秘钥为2,对照上面图片的凯撒密码盘可以得到密文是gcv。
咱们来动手写个凯撒密码(代码已经上传github:
(https://github.com/xiexiaojing/yuna):
@Test
public void caesarCipher() {
String text = "love was growing in eyes"; //明文
int key = 3; //秘钥
String cipher = encryptCaesarCipher(text, key); //密文
System.out.println(cipher);
}
//凯撒密码加密算法
private String encryptCaesarCipher(String text, int key) {
char[] chars = text.toCharArray();
for(int i=0; i<chars.length; i++) {
if(chars[i] != ' ') {
chars[i] = (char)(chars[i]+key);
}
//如果超过了26个字母,则减去26
if(chars[i]>122) {
chars[i] = (char)(chars[i]-26);
}
}
return new String(chars);
}
运行得到密文:oryh zdv jurzlqj lq hbhv
凯撒密码连小朋友都能破解。一旦被人知道用的凯撒密码,算法是已知的。要破解秘钥拿个明文和密文试试就知道了。就是平时说的暴力破解法可以很容易破解。对于这种全是英文字符的也可以使用频率分析法。频率分析法可以理解为基于大数据的方法,因为26个字母中,e的使用频率高。如果比如一篇文章,单词足够多的话,出现频率最高的字母xxx就是e。xxx的char值e的char值就是秘钥了。

DES
概述
DES全称为Data Encryption Standard,即数据加密标准,是一种分组加密算法。其分组长度为64bit,密钥长度为64bit,其中8bit为校验位,所以实际长度为56bit。
先介绍一下校验位。举个例子,咱们的身份证号码都是18位。这18位包含:

其中最后一位就是校验位,原理是利用将前面部分利用某种算法计算得到一个数。如果校验位与算法得到的不一致,则数据是有问题的。所以身份证本身是有不通过查库就可以简单验证有效性功能的。
回到DES算法。DES算法的秘钥必须是64位,参与加密计算的是56位。这是原始秘钥。这个原始秘钥会用一个函数转换成16个64位秘钥。
加密过程
DES的加密过程:
明文64位->初始IP置换->16轮加密变换->逆初始IP置换->密文
DES算法的这个过程又被称为Feistel网络。
简单解释下:
明文我们自己想写多长写多长。但是加
密的时候每次以64bit作为一个分组。最后将密文拼接起来。
然后执行一个IP置换(初始置换)操作。IP置换就是按位置换。举例来说64bit就是64个0和1。把第40个位置上的数换成第50个位置上的数就是置换了。
置换好的64个bit会分成两个32bit。然后用相同的加密算法每次传不同的转换后秘钥做16轮。
然后将两组32bit拼接起来再进行一次IP置换(终结置换)变成密文
分组组合
刚才介绍的加密过程是把明文的一块怎么加密成密文。DES密码块与密码块连接方式遵循对称加密的方式。
对称加密有两种方式,一种是分组加密,一种是序列加密。
分组加密,也叫块加密(block cyphers),一次加密明文中的一个块。是将明文按一定的位长分组,明文组经过加密运算得到密文组,密文组经过解密运算(加密运算的逆运算),还原成明文组。
序列加密,也叫流加密(stream cyphers),一次加密明文中的一个位。是指利用少量的密钥通过某种复杂的运算(密码算法)产生大量的伪随机位流,用于对明文位流的加密。
分组加密算法中,分组密码的设计基本遵循混淆原则和扩散原则。有ECB,CBC,CFB,OFB这4种算法模式。DES有ECB和CBC两种实现。
ECB模式
ECB模式就是每组明文分别加密后拼接起来。

CBC模式
CBC即密码分组链接(Cipher-block chaining)的简称。在CBC模式中,每个明文块先与前一个密文块进行异或后,再进行加密。在这种方法中,每个密文块都依赖于它前面的所有明文块。同时,为了保证每条消息的唯一性,在第一个块中需要使用初始化向量。在DES中,初始化向量就是秘钥。

程序实现
我们用程序来实现一下DES加密算法
@Test
public void desCiper() throws Exception{
String key = "12345678";
String text = "我知道我是任性很任性,伤透了你的心"; //明文
String cipher = encryptDesCipher(text, key); //密文
System.out.println(cipher);
text = decryptDesCipher(cipher, key); //明文
System.out.println(text);
}
//DES加密算法
private String encryptDesCipher(String text, String origKey) throws Exception{
Key key = new SecretKeySpec(origKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
return Base64.encode(cipher.doFinal(text.getBytes()));
}
//DES加密算法
private String decryptDesCipher(String text, String origKey) throws Exception{
Key key = new SecretKeySpec(origKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(Base64.decode(text)));
}
运行结果:
xo6mmVe8j1/d60cAAiFz1HAXxihi2FH5d0zMWILvEYISWR52lguy2TbMZQ4vuulCdO8WvxMRuXE=
我知道我是任性很任性,伤透了你的心
3DES
3DES即3重加密算法,是对每个数据块应用三次DES算法。这是为了应对计算机计算能力增强,DES变的容易破解而产生的。
主要方法就是DES秘钥64位,3DES秘钥64*3=192位,分成个三个秘钥,进行2轮DES加密,1轮DES解密。最终得到结果。

AES
AES全称是高级加密标准(Advanced Encryption Standard)。是用来替代DES/3DES的。主要过程如下,这里不过多介绍。

应用
我们来回顾下https的SSL握手过程:

SSL握手的最后,双方会用非对称秘钥协商出一个对称秘钥。用对称秘钥来加密传输的数据。之所以这样做是因为非对称加密安全性高但是效率低,对称秘钥正好相反。对称秘钥可以被暴力破解,破解需要时间。如果破解出来时就过期了,再通信就用另外的秘钥就能保证信息安全。
我们来模拟一下已经协商好的秘钥之后http客户端与服务器端的通信。(代码已经上传github:(https://github.com/xiexiaojing/yuna):
@Test
public void client() throws Exception {
int i = 1;
while (i <= 2) {
Socket socket = new Socket("127.0.0.1", 520);
//向服务器端第一次发送字符串
OutputStream netOut = socket.getOutputStream();
InputStream io = socket.getInputStream();
String msg = i == 1 ? "客户端:我知道我是任性太任性,伤透了你的心。我是追梦的人,追一生的缘分。":
"客户端:我愿意嫁给你,你却不能答应我。";
System.out.println(msg);
netOut.write(encryptDesCipher(msg.getBytes(), "12345678"));
netOut.flush();
byte[] bytes = new byte[i==1?104:64];
io.read(bytes);
String response = new String(decryptDesCipher(bytes,"12345678"));
System.out.println(response);
netOut.close();
io.close();
socket.close();
i++;
}
}
@Test
public void server() throws Exception {
ServerSocket serverSocket = new ServerSocket(520);
int i = 1;
while (i <= 2) {
String msg = i == 1 ? "服务端:我知道你是任性太任性,伤透了我的心。同是追梦的人,难舍难分。" :
"服务端:你愿意嫁给我,我却不能向你承诺。";
Socket socket = serverSocket.accept();
InputStream io = socket.getInputStream();
byte[] bytes = new byte[i==1?112:64];
io.read(bytes);
System.out.println(new String(decryptDesCipher(bytes,"12345678")));
OutputStream os = socket.getOutputStream();
System.out.println(msg);
byte[] outBytes = encryptDesCipher(msg.getBytes(), "12345678");
os.write(outBytes);
os.flush();
os.close();
io.close();
i++;
}
}
//DES加密算法
private byte[] encryptDesCipher(byte[] text, String origKey) throws Exception {
Key key = new SecretKeySpec(origKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(text);
}
//DES加密算法
private byte[] decryptDesCipher(byte[] text, String origKey) throws Exception {
Key key = new SecretKeySpec(origKey.getBytes(), "DES");
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(text);
}
运行结果
客户端:我知道我是任性太任性,伤透了你的心。我是追梦的人,追一生的缘分。
服务端:我知道你是任性太任性,伤透了我的心。同是追梦的人,难舍难分。
客户端:我愿意嫁给你,你却不能答应我。
服务端:你愿意嫁给我,我却不能向你承诺。
这个程序实现了简单的客户端和服务器端的DES加密方式通信。稍加改造可以实现一个信息加密的聊天小程序。
总结
本文使用概念、原理、应用的传统型逻辑架构来对DES做系统梳理。里面涉及到的一些基本知识限于篇幅省略了一些。
比如Base64编码。它是加密时常用的编码方式,我们平时所看到的密钥都是base64后的结果。可以简单理解为对2的6次方进行64进制运算,可防止乱码丢失字节。
再比如填充字节这部分也没有介绍,有兴趣可以自己查阅下。
加解密很多人工作中或多或少都有涉及。我个人认为只要涉及的地方至少要了解到原理和架构层面,才能避免遇到问题时【拿着锤子找钉子】找不到真正问题的窘境。而只有动手实践才能避免当时了解了,过后又忘了需要再看一遍而产生重复工作的问题。
懂了!国际算法体系对称算法DES原理的更多相关文章
- Asp.Net 常用工具类之加密——对称加密DES算法(2)
又到周末,下午博客园看了两篇文章,关于老跳和老赵的程序员生涯,不禁感叹漫漫程序路,何去何从兮! 转眼毕业的第三个年头,去过苏州,跑过上海,从一开始的凌云壮志,去年背起行囊默默回到了长沙准备买房,也想有 ...
- AES算法,DES算法,RSA算法JAVA实现
1 AES算法 1.1 算法描述 1.1.1 设计思想 Rijndael密码的设计力求满足以下3条标准: ① 抵抗所有已知的攻击. ② 在多个平台上速度快,编码紧凑. ③ 设计 ...
- 重新想象 Windows 8 Store Apps (31) - 加密解密: 哈希算法, 对称算法
原文:重新想象 Windows 8 Store Apps (31) - 加密解密: 哈希算法, 对称算法 [源码下载] 重新想象 Windows 8 Store Apps (31) - 加密解密: 哈 ...
- 常见的哈希Hash算法 & MD5 & 对称非对称加密 & 海明码
参考 Link 另外,这篇文章也提到了利用Hash碰撞而产生DOS攻击的案例: http://www.cnblogs.com/charlesblc/p/5990475.html DJB的算法实现核心是 ...
- 【Java-加密算法】对称加密、非对称加密、单向散列(转)
一提到加密,就会联想到数字签名,这两个经常被混淆的概念到底是什么呢? 加密:加密是一种以密码方式发送信息的方法.只有拥有正确密钥的人才能解开这个信息的密码.对于其他人来说,这个信息看起来就像是一系列随 ...
- 国密SM4对称算法实现说明(原SMS4无线局域网算法标准)
国密SM4对称算法实现说明(原SMS4无线局域网算法标准) SM4分组密码算法,原名SMS4,国家密码管理局于2012年3月21日发布:http://www.oscca.gov.cn/News/201 ...
- ACS蚁群算法求解对称TSP旅行商问题的JavaScript实现
本来以为在了解蚁群算法的基础上实现这道奇怪的算法题并不难,结果实际上大相径庭啊.做了近三天时间,才改成现在这能勉强拿的出手的模样.由于公式都是图片,暂且以截图代替那部分内容吧,mark一记. 1 蚁群 ...
- OpenCV 视频监控(Video Surveilance)的算法体系
如前面说到的,OpenCV VS提供了6组算法的接口,分别是:前景检测.新目标检测.目标跟踪.轨迹生成.跟踪后处理.轨迹分析,除了轨迹生成用于轨迹数据的保存以外,其他5个部分都是标准的视频监控算法体系 ...
- php算法题---对称的二叉树
php算法题---对称的二叉树 一.总结 一句话总结: 可以在isSymmetrical()的基础上再加一个函数comRoot,函数comRoot来做树的递归判断 /*思路:首先根节点以及其左右子树, ...
随机推荐
- RHSA-2017:1931-中危: bash 安全和BUG修复更新(代码执行)
[root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 修复命令: 使用root账号登陆She ...
- intellij idea如何解决javax.servlet.http不存在
正确的解决方法是:对项目名右键,选中Open Mudule Settings--选择左侧的Modules,选择右边的Dependencies--然后点击右侧边栏的绿色"+"号,点击 ...
- protoc-c 阅读笔记
以前和山哥做过类似的,最近想起来,抽空又看了下 protoc-c. 山哥做的报文流向: rpc -> lydtree -> motree -> struct 涉及的细节很多 1) l ...
- unix中的线程池技术详解
•线程池就是有一堆已经创建好了的线程,当有新的任务需要处理的时候,就从这个池子里面取一个空闲等待的线程来处理该任务,当处理完成了就再次把该线程放回池中,以供后面的任务使用,当池子里的线程全都处理忙碌状 ...
- Git hub加载慢?下载慢?浏览慢?几个小技巧让你一键起飞!
记得,那是一个风和日丽,艳阳高照的夜晚,只因为当初的一次回眸,于是便决然走向了程序员的道路,从此,CV大法心中记,代码伴我身. 这一天,正当我打开电脑准备开开心心的使用CV大法完成任务的时候,却恼人的 ...
- 从Linux源码看Socket(TCP)的bind
从Linux源码看Socket(TCP)的bind 前言 笔者一直觉得如果能知道从应用到框架再到操作系统的每一处代码,是一件Exciting的事情. 今天笔者就来从Linux源码的角度看下Server ...
- 【C语言入门学习笔记】如何把C语言程序变成可执行文件!
环境 在ANSI的任何一种实现中,存在两种不同的环境. 翻译环境:在这个环境里,源代码被转换为可执行的机器指令. 执行环境:用于实际执行代码. 翻译环境 组成一个程序的每个源文件通过编译过程分别转成目 ...
- go ioutial 读取写入文件
package main import ( "fmt" "io/ioutil" "os" ) func main() { // 读取文件 / ...
- css变量复用 全局变量-局部变量
前言 简单使用场景:同一套后台系统有多套主题的情况下,主题色作为一个最常用到的可复用的颜色,非常有必要像js的全局变量一样存在全局变量中以作复用,之前我第一个想到的是sass的变量声明,未曾想到css ...
- C# 创建text文本并写入数据
/// <summary> /// 创建TXT文本并往里面写入数据 /// </summary> /// <param name="FileName" ...