一、密钥长度处理

实现了小于8 bytes的密钥都可以进行测试,原理其实很简单,只需要在密钥生成的时候对密钥的长度进行判断,不够的进行补0操作。

//密钥生成public StringBuffer[] getSubkey() {StringBuffer keyBinary = new StringBuffer(stringBufferToBinary(key)); //把密钥转成二进制StringBuffer subkey[] = new StringBuffer[16];  //subkey数组用来存储子密钥StringBuffer C0 = new StringBuffer(); //左密钥StringBuffer D0 = new StringBuffer(); //右密钥//判断密钥长度while (keyBinary.length() < 64) {keyBinary.append("0");}//PC1置换(64 bits --> 56 bits)for (int i = 0; i < 28; i++) {C0.append(keyBinary.charAt(PC1[i] - 1));D0.append(keyBinary.charAt(PC1[i + 28] - 1));}//16轮循环生成子密钥//16轮移位操作,每轮左移一位,特殊情况左移两位(查看密钥移位表)for (int i = 0; i < 16; i++) {//把第一位删了添加到最后一位char tmp;tmp = C0.charAt(0);C0.deleteCharAt(0);C0.append(tmp);tmp = D0.charAt(0);D0.deleteCharAt(0);D0.append(tmp);//特殊位置左移两位if (i != 0 && i != 1 && i != 8 && i != 15) {tmp = C0.charAt(0);C0.deleteCharAt(0);C0.append(tmp);tmp = D0.charAt(0);D0.deleteCharAt(0);D0.append(tmp);}//左右合并StringBuffer CODO = new StringBuffer(C0.toString() + D0.toString());//PC2置换StringBuffer C0D0tmp = new StringBuffer();for (int j = 0; j < 48; j++) {C0D0tmp.append(CODO.charAt(PC2[j] - 1));}subkey[i] = C0D0tmp;//  System.out.println(i + "轮密钥:" + subkey[i]);}return subkey;}

二、分组加密

实现了对任意长度的明文进行加密,实现这个功能需要引入一个分组数变量,用来记录分几组。

整个源代码如下:

package DES;import java.util.Scanner;public class Demo {private StringBuffer plaintext;  //明文字符串64 bits----8 bytesprivate StringBuffer ciphertext;  //密文字符串64 bits----8 bytesprivate StringBuffer key;  //密钥字符串64 bits ----8 bytesprivate int group;  //分组public int getGroup() {return group;}//设置分组数public void setGroup() {group = plaintext.length() / 8;}public StringBuffer getPlaintext() {return plaintext;}public void setPlaintext(StringBuffer plaintext) {this.plaintext = plaintext;}public StringBuffer getCiphertext() {return ciphertext;}public void setCiphertext(StringBuffer ciphertext) {this.ciphertext = ciphertext;}public StringBuffer getKey() {return key;}public void setKey(StringBuffer key) {this.key = key;}//IP置换private static final int[] IP = {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};//IP逆置换private static final int[] IPReverse = {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};// E位选择表(扩展置换表)private static final int[] E = {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 final int[] P = {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};//PC1private static final int[] PC1 = {57, 49, 41, 33, 25, 17, 9,1, 58, 50, 42, 34, 26, 18,10, 2, 59, 51, 43, 35, 27,19, 11, 3, 60, 52, 44, 36,63, 55, 47, 39, 31, 23, 15,7, 62, 54, 46, 38, 30, 22,14, 6, 61, 53, 45, 37, 29,21, 13, 5, 28, 20, 12, 4};// PC2private static final int[] PC2 = {14, 17, 11, 24, 1, 5,3, 28, 15, 6, 21, 10,23, 19, 12, 4, 26, 8,16, 7, 27, 20, 13, 2,41, 52, 31, 37, 47, 55,30, 40, 51, 45, 33, 48,44, 49, 39, 56, 34, 53,46, 42, 50, 36, 29, 32};// SBoxprivate static final int[][] SBox = {// S1{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},// S2{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},// S3{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},// S4{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},// S5{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},// S6{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},// S7{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},// S8{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}};//StringBuffer转成二进制public StringBuffer stringBufferToBinary(StringBuffer s) {StringBuffer res = new StringBuffer();StringBuffer stmp = new StringBuffer();for (int i = 0; i < s.length(); i++) {stmp = new StringBuffer(Integer.toBinaryString(s.charAt(i)));while (stmp.length() < 8) {  //转成8位二进制stmp.insert(0, 0);}//System.out.println(stmp);res.append(stmp);}return res;}//二进制字符串转成字符64->8//int column = Integer.parseInt(Sinput.substring(1, 5), 2);public StringBuffer BinaryTostringBuffer(StringBuffer s) {StringBuffer res = new StringBuffer();for (int i = 0; i < 8; i++) {int t = Integer.parseInt(s.substring(i * 8, (i + 1) * 8), 2);res.append((char) t);}return res;}//初始置换IPpublic StringBuffer Initial(StringBuffer r) {StringBuffer res = new StringBuffer();for (int i = 0; i < 64; i++) {res.append(r.charAt(IP[i] - 1)); //数组的索引是从0开始的}return res;}//终止置换IPpublic StringBuffer Final(StringBuffer r) {StringBuffer res = new StringBuffer();for (int i = 0; i < 64; i++) {res.append(r.charAt(IPReverse[i] - 1)); //数组的索引是从0开始的}return res;}//P置换public StringBuffer P(StringBuffer r) {StringBuffer res = new StringBuffer();for (int i = 0; i < 32; i++) {res.append(r.charAt(P[i] - 1)); //数组的索引是从0开始的}return res;}//扩展置换(E表)public StringBuffer Extent(StringBuffer r) {StringBuffer res = new StringBuffer();for (int i = 0; i < 48; i++) {res.append(r.charAt(E[i] - 1)); //数组的索引是从0开始的}return res;}//密钥生成public StringBuffer[] getSubkey() {StringBuffer keyBinary = new StringBuffer(stringBufferToBinary(key)); //把密钥转成二进制StringBuffer subkey[] = new StringBuffer[16];  //subkey数组用来存储子密钥StringBuffer C0 = new StringBuffer(); //左密钥StringBuffer D0 = new StringBuffer(); //右密钥//判断密钥长度while (keyBinary.length() < 64) {keyBinary.append("0");}//PC1置换(64 bits --> 56 bits)for (int i = 0; i < 28; i++) {C0.append(keyBinary.charAt(PC1[i] - 1));D0.append(keyBinary.charAt(PC1[i + 28] - 1));}//16轮循环生成子密钥//16轮移位操作,每轮左移一位,特殊情况左移两位(查看密钥移位表)for (int i = 0; i < 16; i++) {//把第一位删了添加到最后一位char tmp;tmp = C0.charAt(0);C0.deleteCharAt(0);C0.append(tmp);tmp = D0.charAt(0);D0.deleteCharAt(0);D0.append(tmp);//特殊位置左移两位if (i != 0 && i != 1 && i != 8 && i != 15) {tmp = C0.charAt(0);C0.deleteCharAt(0);C0.append(tmp);tmp = D0.charAt(0);D0.deleteCharAt(0);D0.append(tmp);}//左右合并StringBuffer CODO = new StringBuffer(C0.toString() + D0.toString());//PC2置换StringBuffer C0D0tmp = new StringBuffer();for (int j = 0; j < 48; j++) {C0D0tmp.append(CODO.charAt(PC2[j] - 1));}subkey[i] = C0D0tmp;//  System.out.println(i + "轮密钥:" + subkey[i]);}return subkey;}//f轮函数public StringBuffer F(StringBuffer R, StringBuffer subkey) {StringBuffer res = new StringBuffer();//E盒扩展res = Extent(R);//异或运算for (int i = 0; i < 48; i++) {res.replace(i, i + 1, (res.charAt(i) == subkey.charAt(i) ? "0" : "1"));}//S盒压缩StringBuffer sBox = new StringBuffer();  //sBox用来接收压缩后的32 bitsfor (int i = 0; i < 8; i++) {String Sinput = res.substring(i * 6, (i + 1) * 6);//首尾两位转化为行,中间四位转化为列//parseInt(String s,int radix)---把字符串s根据radix(进制)转成对应的整数int row = Integer.parseInt(Character.toString(Sinput.charAt(0)) + Sinput.charAt(5), 2);int column = Integer.parseInt(Sinput.substring(1, 5), 2);StringBuffer Soutput = new StringBuffer(Integer.toBinaryString(SBox[i][row * 16 + column]));while (Soutput.length() < 4) {//小于四位要添0Soutput.insert(0, 0);}sBox.append(Soutput);}//P置换sBox = P(sBox);return sBox;}//16轮迭代public StringBuffer iteration(StringBuffer L, StringBuffer R, int mode) {StringBuffer res = new StringBuffer();StringBuffer[] subkey = getSubkey(); //获取子密钥//mode == 1 解密  密钥反转if (mode == 1) {StringBuffer[] tmp = getSubkey();  //mode ==1for (int i = 0; i < 16; i++) {subkey[i] = tmp[15 - i];//  System.out.println(i+"轮密钥:"+subkey[i]);}}//查看密钥
//        for (int i =0;i<16;i++){
//            System.out.println(i+"轮密钥:"+subkey[i]);
//        }//16轮循环for (int i = 0; i < 16; i++) {StringBuffer Ltmp = new StringBuffer(L);StringBuffer Rtmp = new StringBuffer(R);//右边的赋给左边L.replace(0, 32, R.toString());//F轮函数StringBuffer Fstring = F(Rtmp, subkey[i]);//Fstring异或Rfor (int j = 0; j < 32; j++) {R.replace(j, j + 1, (Fstring.charAt(j) == Ltmp.charAt(j) ? "0" : "1"));}}//循环结束后左右交换StringBuffer RL = new StringBuffer(R.toString() + L.toString());//终止置换RL = Final(RL);return RL;}public static void main(String[] args) {System.out.println("----DES----");Demo instance = new Demo();//创建实例StringBuffer plain = new StringBuffer(); //录入明文String tmp = ""; //用来临时录入明文密文Scanner sc = new Scanner(System.in);System.out.println("请输入明文:");tmp = sc.next();plain.append(tmp);int length = plain.length(); //保存明文的长度instance.setPlaintext(plain);System.out.println("明文:" + instance.getPlaintext());//密钥产生System.out.println("输入密钥:");tmp = sc.next();StringBuffer mykey = new StringBuffer();mykey.append(tmp);instance.setKey(mykey);System.out.println("密钥:" + instance.getKey());//设置分组数instance.setGroup();//测试加密System.out.println("-----DES加密-----");plain = instance.stringBufferToBinary(instance.getPlaintext()); //明文转成二进制StringBuffer L = new StringBuffer();//左明文StringBuffer R = new StringBuffer();//右明文StringBuffer plainBackup = new StringBuffer(plain);  //二进制明文备份StringBuffer cipherBackup = new StringBuffer();  //二进制密文备份StringBuffer descipher = new StringBuffer(); //解密后的明文//扩充明文while (plainBackup.length() < 64 * (instance.group + 1)) {plainBackup.append("0");}//分组加密for (int i = 0; i <= instance.group; i++) {//明文分组处理for (int j = 0; j < 64; j++) {plain.replace(j, j + 1, plainBackup.substring(j + i * 64, j + 64 * i + 1));}//初始置换plain = instance.Initial(plain);L.replace(0, 32, plain.substring(0, 32));R.replace(0, 32, plain.substring(32, 64));//16轮迭代plain = instance.iteration(L, R, 0);//plain是加密后的二进制密文System.out.println(i + "轮迭代后:" + plain);//备份二进制密文cipherBackup.append(plain);System.out.println(i + "轮密文:" + instance.BinaryTostringBuffer(plain));}//测试解密System.out.println("-----DES解密-----");//分组解密for (int i = 0; i <= instance.group; i++) {//密文分组处理for (int j = 0; j < 64; j++) {plain.replace(j, j + 1, cipherBackup.substring(j + i * 64, j + 64 * i + 1));}//初始置换plain = instance.Initial(plain);L.replace(0, 32, plain.substring(0, 32));R.replace(0, 32, plain.substring(32, 64));plain = instance.iteration(L, R, 1);//plain是解密后的二进制密文System.out.println(i + "轮迭代后:" + plain);System.out.println(i + "明文:" + instance.BinaryTostringBuffer(plain));descipher.append(instance.BinaryTostringBuffer(plain));}//输出解密后的明文System.out.println("最终解密后的明文:"+descipher.substring(0,length));}
}
/*
aaaaaaaa
-----------
abcdef
abcdabcd:
abcdabcd:
----------
abcdefgh
abcdefghijkabcdefghijk*/

三、运行结果

明文长度小于8比特,密钥长度小于8。

明文长度大于8比特。

DES实现的粗略版链接:DES算法的Java实现(粗略版)_争取不划水的博客-CSDN博客

DES算法Java实现(完善版)相关推荐

  1. DES算法实现(C++版)

    文章目录 一.DES算法原理 二.相关说明 1.初始置换IP 2.子密钥 Ki 的获取 3.密码函数 f 4.尾置换IP-1 三.DES算法具体实现(C++) 一.DES算法原理 DES算法是一种最通 ...

  2. java des算法_Java DES算法程序

    java des算法 Java Cryptography Extension (JCE) provides framework and implementation for generating ke ...

  3. DES加密解密算法Java实现

    DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小.这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半.使用子密钥对其中一半应 ...

  4. IDEA配置java《算法》第四版环境(耗时6小时,总算配置成功了,希望能给大家一点帮助)

    0.前言 最近在学java语言,然后想用java语言来学习算法,在网上听说看<算法>第四版学习java算法不错,于是就去下载了<算法>电子书来啃 今天看到了用java java ...

  5. java 随机金额_java_微信随机生成红包金额算法java版,最近几年玩得最疯狂的应该是 - phpStudy...

    微信随机生成红包金额算法java版 最近几年玩得最疯狂的应该是发红包了,尤其是过年的时候特别受欢迎,下面写了红包的随机算法,其实挺简单的,仅是提供一种思路,希望可以给大家一些启发. public cl ...

  6. 最小生成树Prim算法Java版

    最小生成树Prim算法Java版 算法描述: 在一个加权连通图中,顶点集合V,边集合为E 任意选出一个点作为初始顶点,标记为visit,计算所有与之相连接的点的距离,选择距离最短的,标记visit. ...

  7. Java算法:华为机试算法(下),华为算法Java版,牛客网华为算法73~108题

    接上篇:Java算法:华为机试算法(中),华为算法Java版,牛客网华为算法55~72题   HJ73 计算日期到天数转换 计算日期到天数转换 题目描述 根据输入的日期,计算是这一年的第几天.. 测试 ...

  8. java设计单词英译汉小助手_C语言实现单词小助手功能完善版

    本文为大家分享了完善版的C语言单词小助手的具体实现代码,供大家参考,具体内容如下 一.题目分析 1.在原有代码基础上添加文档注释,函数注释及语句注释,使代码风格良好,易于阅读和修改. 2.完善功能,实 ...

  9. leetcode刷题java、c++、go语言三合一版本 谷歌师兄的刷题笔记、东哥的算法小抄、 Guide哥的Java面试突击版

    不久前火爆 GitHub 的 LeetCode 中文刷题手册,分享给大家,让正在找工作的朋友能够快速找到心仪的offer! <LeetCode Cookbook>目前已经收录了 520 道 ...

最新文章

  1. 负载均衡中使用 Redis 实现共享 Session
  2. 【Qt】QtCreator updatePchInfo:switching to none
  3. Android studio 刷新文件状态
  4. window.print 固定表头不影响_Excel中的表头,你会处理吗
  5. java 数组group by_java Group by分组算法
  6. lucene使用3.0.3_Jirasearch 2.0狗粮:使用Lucene查找我们的Jira问题
  7. php指定字符编码,PHP字符编码问题
  8. 上海大学计算机网络实验报告3,上海大学计算机组成原理实验报告(全)
  9. 计算机普通用户没有软件怎么回事,请教各位高手:单机多用户账户计算机,当管理员用户安装了程序,其它普通用户账户不能使用怎么处理?比如在管理...
  10. 诺基亚收购阿朗再交易 持股比例将超95%
  11. 矛与盾的较量──网络***和防火墙详解
  12. 《Arduino》开发 之 用 u8g2 库 给 0.96寸OLED 刷bmp图片,OLED图片取模
  13. GoldenDict 上的那些精美版权词典(附下载地址)(英语、俄语、梵语、印地语)
  14. Mac安装虚拟机和CentOS
  15. Linux cppcheck使用
  16. 【canvas 太阳系的动画】
  17. 大学计算机考试59分,大学期末考59分,你会找老师理论吗?很多人都猜错
  18. U-Mail邮件系统管理功能 高效办公轻松搞定
  19. 【云原生】AI云开发平台——AI Model Foundry介绍(开发者可免费体验AI训练模型)
  20. Pytho解析器的安装及配置

热门文章

  1. Android-自定义ViewPager指示器
  2. SSH终端远程复制:scp命令详解
  3. Kubernetes示例Guestbook
  4. mysql动态多条件模糊查询方法
  5. 别人的灵敏度永远压不住枪?手把手教你怎么调节一套适合自己的刺激战场灵敏度
  6. Unity3D研究院之FBX模型的载入与人物行走动画的播放(十二)
  7. 教你如何教女朋友学Python?
  8. 华南理工计算机学院硕士研究生导师何生导师,中国南玻集团何进副总裁获聘华南理工大学研究生校外导师...
  9. 计算机在英语口语教学中的应用,英语口语论文,关于小组合作学习在中职英语口语教学中的实践运用相关参考文献资料-免费论文范文...
  10. 使用ChatGPT练习英语口语,用AI帮你设计场景练习