程序猿成长之路之密码学篇-DES算法详解
DES的算法实现原理详情请见
https://blog.csdn.net/qq_31236027/article/details/128209185
DES算法密钥获取详情请见
https://blog.csdn.net/qq_31236027/article/details/129224730
编码工具类获取详见
https://blog.csdn.net/qq_31236027/article/details/128579451
DES算法实现思路:
- 进行编码工具类的设计,主要设计以下几个方法:
- 字符串转二进制,用于明文加密
- 二进制转字符串,用于对解密二进制流与文本的转换
- 二进制转十六进制字符串,用于对加密后的文本进行传输和保存,防止出现乱码
- 十六进制转二进制,用于对加密后的文本进行解密
- 其他有需要的方法(如s盒的二进制转十进制)
- 进行密钥获取工具类的设计
- 进行des算法工具类的设计
密钥获取工具类的设计:
- 设计一个初始化方法和两个数组,用于密钥第一次选择置换和接收左右半部分的32位二进制结果。
- 初始化后进行16轮密钥的获取,最好能够存储在一个私有全局变量里,然后通过一个接口方法对外发布。(我这步没有做)
DES算法工具类的设计:
注意点:
- 将获取的16轮密钥保存在一个全局变量,解密需要使用(只需要逆置即可)
- 注意分组问题
- !!很重要的一点!!在加密后要将所有的十六进制流小写,大写的话会解密出现乱码。
最后上DES算法工具类实现代码:
package des;import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;import common.EncodeUtil;
import common.IEncrytion;
import common.EncodeUtil.EncodeRadix;/*** des加解密工具类* @author zygswo**/
public class DesUtil implements IEncrytion{/*** 加密轮数*/public static final int ROUND_NB = 16;/*** 字符串长度*/public static final int CHAR_LEN = 16;/*** 分组长度*/public static final int DIV_LEN = 64 / CHAR_LEN;/*** 密钥对象*/private KeyUtil subKeyObj = new KeyUtil().init(); public List<String> subKeys = Collections.synchronizedList(new ArrayList<>());/*** 初始置换PC表*/private static int[][] transferTable = {{58,50,42,34,26,18,10,2},{60,52,44,36,28,20,12,4},{62,54,46,38,30,22,14,6},{64,56,48,40,32,24,16,8},{57,49,41,33,25,17,9,1},{59,51,43,35,27,19,11,3},{61,53,45,37,29,21,13,5},{63,55,47,39,31,23,15,7}};/*** 扩展置换PC表*/private static int[][] transferExtendTable = {{32,1,2,3,4,5},{4,5,6,7,8,9},{8,9,10,11,12,13},{12,13,14,15,16,17},{16,17,18,19,20,21},{20,21,22,23,24,25},{24,25,26,27,28,29},{28,29,30,31,32,1}};/*** p盒置换表*/private static int[][] pTransferTable = {{16,7,20,21},{29,12,28,17},{1,15,23,26},{5,18,31,10},{2,8,24,14},{32,27,3,9},{19,13,30,6},{22,11,4,25}};/*** 逆初始置换PC-1表*/private static int[][] transferReverseTable = {{40,8,48,16,56,24,64,32},{39,7,47,15,55,23,63,31},{38,6,46,14,54,22,62,30},{37,5,45,13,53,21,61,29},{36,4,44,12,52,20,60,28},{35,3,43,11,51,19,59,27}, {34,2,42,10,50,18,58,26},{33,1,41,9,49,17,57,25}};/*** s盒置换表*/private static int[][][] sBox = {{{14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},{0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},{4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},{15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}},{{15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},{3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},{0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},{13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}},{{10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},{13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},{13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},{1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}},{{7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},{13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},{10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},{3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}},{{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},{14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},{4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},{11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}},{{12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},{10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},{9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},{4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}},{{4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},{13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},{1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},{6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}},{{13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},{1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},{7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},{2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}}};/*** 解密* @param encrytedText 密文* @return 明文*/@Overridepublic String decrypt(String encrytedText) {StringBuilder sb = new StringBuilder();// CHAR_LEN = divLeng * 4 (16进制4位,转16位需要4个16进制位)int divLeng = 16;int length = encrytedText.length()% divLeng == 0 ? encrytedText.length()/divLeng : (encrytedText.length()/divLeng + 1);for (int i = 0; i<length; i++) {int startIndex = i * divLeng;int endIndex = (startIndex + divLeng) > encrytedText.length() ? encrytedText.length() : (startIndex + divLeng);String str1 = encrytedText.substring(startIndex, endIndex);sb.append(baseDecrypt(EncodeUtil.toBinary(str1,EncodeRadix.HEX)));}return sb.toString().trim();}/*** 解密(64位一组)* @param encrytedText 密文* @return*/private String baseDecrypt(String encrytedText) {//1.初始置换//获取16组密钥List<String> reversedSubkeys = new ArrayList<>();for (int i = subKeys.size() -1; i >=0 ;i--) {reversedSubkeys.add(subKeys.get(i));}//16次循环加密return EncodeUtil.binaryToStr(loops(encrytedText, reversedSubkeys,false),CHAR_LEN).trim();}/*** 分组加密* @param text 明文* @return 密文*/@Overridepublic String encrypt(String text) {StringBuilder sb = new StringBuilder();// DIV_LEN * CHAR_LEN = 64 // 根据DIV_LEN进行分组,如CHAR_LEN=16位,那么就每4个字符一组int length = text.length()% DIV_LEN == 0 ? text.length()/DIV_LEN : (text.length()/DIV_LEN + 1);for (int i = 0; i<length; i++) {int startIndex = i * DIV_LEN;int endIndex = (startIndex + DIV_LEN) > text.length() ? text.length() : (startIndex + DIV_LEN);String str1 = text.substring(startIndex, endIndex);//尾部填充while (str1.length() < DIV_LEN) {str1 += " ";}sb.append(baseEncrypt(str1));}return sb.toString().toLowerCase().trim(); //注意,加密后一定要为小写,大写后会出错}/*** 加密(每个密文都是64位)* @param text* @return*/private String baseEncrypt(String text) {//获取16组密钥if (subKeys == null || subKeys.isEmpty()) {subKeys = subKeyObj.generateKey();}//16次循环加密return EncodeUtil.binaryToHexStr(loops(text, subKeys, true)).trim();}/*** 16轮循环加密* @param step1Result 初始置换后的结果* @param subKeys 16组子密钥* @param isEncrypt 是否加密* @return 循环加密结果*/private String loops(String text, List<String> subKeys, boolean isEncrypt) {//1.初始置换String str64bit = text;if (isEncrypt) {str64bit = EncodeUtil.strtoBinary(text,CHAR_LEN);}str64bit = swap(str64bit, transferTable);if (str64bit.length() != 64) {throw new IllegalArgumentException("初始置换后的结果不为64位");}if (subKeys.size() != 16) {throw new IllegalArgumentException("加密密钥组数不为16组");}//主体部分String leftPart = str64bit.substring(0,32); //高位String rightPart = str64bit.substring(32); //低位for (String subKey: subKeys) {//右半边参与f函数运算String temp = rightPart;//获取f函数结果String fResult = fFunction(rightPart,subKey);//f函数结果与左半部分进行异或运算rightPart = xor(fResult, leftPart);//左右交换leftPart = temp;}//逆初始置换return swap(rightPart+leftPart, transferReverseTable);}/*** f函数* @param str32Bit 右半部分* @param subKey 子密钥* @return f函数结果*/private String fFunction(String str32Bit, String subKey) {//1. 扩展运算,将rightPart32位转成48位String str48Bit = swap(str32Bit, transferExtendTable);//2. 与密钥进行异或运算String result = xor(str48Bit, subKey);char[] res = result.toCharArray();//3. s盒运算String[] sBoxTmp = new String[8];StringBuilder sBoxResult = new StringBuilder(); //p盒运算用for(int i=0; i<sBoxTmp.length; i++) {//每6位为一组输入(首位和末尾位为行索引,中间四位为列索引)int rowNb = Integer.valueOf(EncodeUtil.binaryToDec(res[i*6] + "" + res[i*6 + 5]));int colNb = Integer.valueOf(EncodeUtil.binaryToDec(res[i*6 + 1] + "" + res[i*6 + 2]+ res[i*6 + 3]+ res[i*6 + 4]));sBoxTmp[i] = EncodeUtil.decToBinary(sBox[i][rowNb][colNb]+"",4);}for(String res1: sBoxTmp) {sBoxResult.append(res1);}//4. p盒置换运算return swap(sBoxResult.toString().trim(),pTransferTable);}/*** 异或运算* @param text1 text1 * @param text2 text2* @return*/private String xor(String text1, String text2) {if (text1 == null || text2 == null || text1.length() != text2.length()) {throw new IllegalArgumentException("异或运算失败");}StringBuilder sb = new StringBuilder();for (int i = 0; i < text1.length();i++) {char ch1 = text1.charAt(i);char ch2 = text2.charAt(i);sb.append((ch1) ^ (ch2));}return sb.toString().trim();}/*** 置换运算* @param text 文本* @param table 置换运算表* @return 置换运算后结果*/private String swap(String text,int[][] table) {char[] chs = text.toCharArray();StringBuilder sb = new StringBuilder();int rowNb = table.length;int colNb = table[0].length;for (int i = 0; i < rowNb * colNb;i++) {sb.append(chs[table[i/colNb][i%colNb] - 1]);}return sb.toString().trim();}public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {/*** desutil使用方法* 1. 使用base64编码字符串* 2. 使用des加密,获得16进制字符串*/DesUtil util = new DesUtil();String result = util.encrypt("{\"code\":200,\"message\":\"成功!\",\"data\":{\"id\": \"2103813902831\"}}");System.out.println("encrypt result=" + result);System.out.println("decrypt result = " + util.decrypt(result));}
}
存在的不足
- 密钥较短(64位),安全性能较差,很容易被破解
- 加密后文本较长
- 处理速度较慢
后续改进方案
- 缩短加密后文本长度
- 尝试使用多线程处理,加快处理速度。
- 尝试更长密钥的版本。
相关文章:
程序猿成长之路之密码学篇-DES算法详解
DES的算法实现原理详情请见 https://blog.csdn.net/qq_31236027/article/details/128209185 DES算法密钥获取详情请见 https://blog.csdn.net/qq_31236027/article/details/129224730 编码工具类获取详见 https://blog.csdn.net/qq_31236027/article/details/128579451 DES算法…...
maven生命周期、阶段与默认绑定插件梳理
maven生命周期、阶段与默认绑定插件梳理 CSDN博客 码云源码 1.maven生命周期、阶段与默认绑定插件 序号生命周期lifecycle阶段phase默认绑定插件(链接官网)默认绑定插件(链接maven库)说明1cleancleanmaven-clean-pluginmaven-clean-plugin清理2.1buildvalidate——验证2.2b…...
【数学基础】
文章目录『 第1讲 高等数学预备知识 』1.1 函数的概念与特性函数的四种特性【 重要结论 】1.2 函数的图像直角坐标系下的图像极坐标系下的图像参数方程1.3 常用基础知识【 情报#1 】『 第2讲 数列极限 』2.1 引言2.2 求数列极限【 情报#2 】『 第1讲 高等数学预备知识 』 1.1 …...
网上电子商城的设计与实现
技术:Java、JSP等摘要:21 世纪以来,人类经济高速发展,人们的生活发生了日新月异的变化,特别是计算机的应用及普及到经济和社会生活的各个领域。在消费领域,网上购物已经成为大众所接受的一种新型的消费方式…...
2023thupc总结
A 大富翁 很有意思的题 ∑x∈A∑y∈B[x支配y]−∑x∈A∑y∈B[y支配x]−∑x∈Awx\sum_{x\in A}\sum_{y\in B}[x支配y]-\sum_{x\in A}\sum_{y\in B}[y支配x]-\sum_{x\in A}w_x∑x∈A∑y∈B[x支配y]−∑x∈A∑y∈B[y支配x]−∑x∈Awx ∑x∈A∑y[x支配y]−∑x∈A∑y[y支…...
【数据库】MySQL数据库基础
目录 1.数据库: 2.数据库基本操作 2.1 MySQL的运行原理 2.2显示数据库: 2.3创建数据库 2.4使用数据库 2.5删除数据库 3.常见的数据类型 3.1数值类型: 3.2字符型类型 3.3日期类型 4.表的操作 4.1创建表 4.2查看表 4.3删除表 5.汇总…...
grid了解
结构 <div class"grid"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div>&l…...
2023年全国最新工会考试精选真题及答案13
百分百题库提供工会考试试题、工会考试预测题、工会考试真题、工会证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 81.女职工委员会在()下开展工作。 A.企业工会委员会领导 B.企业工会委员会指导 …...
初识HTML技术
文章目录一、为什么学习前端?二、第一个HTML文件VSCode三. HTML元素四. HTML页面一、为什么学习前端? 我们作为一个后端程序员,为什么还要学习前端,因为我们的终极目的是实现web开发,搭建网站,网站 前端 后端 比如我们随便…...
我们为什么要用消息队列?
消息队列是系统设计中存在时间最长的中间件之一,从系统有通信需求开始,就产生了消息队列。 消息队列的使用场景 在日常系统设计与实现的过程中,下面3种场景会涉及到消息队列: 异步处理流量控制服务解耦 异步处理 典型的应用场…...
Linux进程控制
进程控制fork函数进程终止退出码常见的退出方式进程等待什么是进程等待,为什么要进程等待阻塞与非阻塞进程替换替换原理替换函数执行系统命令执行自己写的程序模拟实现简易的shellfork函数 fork函数是创建一个子进程,之前用过。 #include <unistd.h…...
PMP项目管理引论介绍
目录1. 指南概述和目的1.1 项目管理标准1.2 道德与专业行为规范2 基本要素2.1 项目2.2 项目管理的重要性2.3 项目、项目集、项目组合以及运营管理之间的关系2.3.1 概述2.3.2. 项目组合与项目集管理2.3.3. 运营管理2.3.4. 组织级项目管理和战略2.3.5. 项目管理2.3.6. 运营管理与…...
计算机视觉废钢堆提取问题
计算机视觉废钢堆提取问题 背景介绍 在钢铁炼制中,废钢是非常重要的原料,不同等级废钢对于钢成品影响很大,因此需要对废钢进行正确分类。某废钢料场中,卸料区域布置了多个摄像头,用于拍摄卸料场中废钢堆,…...
判断水仙花数-课后程序(Python程序开发案例教程-黑马程序员编著-第二章-课后作业)
实例5:判断水仙花数 水仙花数是一个3位数,它的每位数字的3次幂之和等于它本身,例如13 53 33 153,153就是一个水仙花数。 本实例要求编写程序,实现判断用户输入的3位数是否为水仙花数的功能。 实例目标 掌握Pytho…...
目标检测: 数据增强代码详解
1. 常见的数据增强 1.1 翻转图像 左右水平翻转 假设图片的宽高为w,h,bdbox左上角A坐标为(x1,y1), 右下角B为(x2,y2)。经过左右水平翻转后,bdbox的左上角A1坐标(w-x2,y1) ,右下角B1坐标为(w-x1,y2)左右水平翻转的代码实现如下:from PIL import Image image = Image.open(i…...
第二讲:ambari编译复盘,如何实现一次性成功编译ambari
上节课我们已经讲解了如何成功编译ambari源码,安装ambari-server rpm包以及成功部署ambari。本节课我们来复盘一下上节课的编译过程,以及思考如何实现一次性成功编译ambari。 要想一次性成功编译ambari,那么就需要将预置工作做好,比如: maven镜像源配置,node_moudle模块…...
Windows下jdk安装与卸载-超详细的图文教程
jdk安装 下载jdk 由于现在主流就是jdk1.8,所以这里就下载jdk1.8进行演示。官方下载地址:https://www.oracle.com/java/technologies/downloads/#java8-windows。 官方下载需要注册oracle账号,国内下载有可能速度慢,若不想注册账…...
Jackson CVE-2018-5968 反序列化漏洞
0x00 前言 同CVE-2017-15095一样,是CVE-2017-7525黑名单绕过的漏洞,主要还是看一下绕过的调用链利用方式。 可以先看: Jackson 反序列化漏洞原理 或者直接看总结也可以: Jackson总结 影响版本:至2.8.11和2.9.x至…...
解析MySQL 8.0 OCP(1Z0-908)考试中一道大部分同学都会做错的题目
一个用户有下面的权限: mysql>SHOW GRANTS FOR jsmith;---------------------------------------------------------------------- | Grants for jsmith% | ----------------------------------------------------------…...
Java死锁
什么是死锁? 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。 死锁的必要条件: 1、互斥条件:该资源任意一个时刻只由一个线程占用。 2、请求与…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
