精华内容
下载资源
问答
  • javaDES加密算法
    2020-01-18 18:05:11

    密钥

    首先这个类中要有一个密码作为密钥,是加密解密的凭据,长度为8的倍数。

    private static String password = "ZNMJJWEB";
    

    加密方法

    参数为数据源,返回加密后的数据

    public static String encrypt(String data) {
    			try {
    				byte[] datasource = data.getBytes("UTF-8");
    				SecureRandom random = new SecureRandom();//获得安全随机数,DES算法要求有一个可信任的随机数源
    				DESKeySpec desKey = new DESKeySpec(password.getBytes("UTF-8"));
    				// 创建一个密匙工厂,然后用它把DESKeySpec转换成一个SecretKey对象
    				SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    				SecretKey securekey = keyFactory.generateSecret(desKey);
    				// Cipher对象实际完成加密操作
    				Cipher cipher = Cipher.getInstance("DES");
    				// 用密匙初始化Cipher对象
    				cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
    				// 现在,获取数据并加密
    				// 正式执行加密操作
    				byte[] enc = cipher.doFinal(datasource);
    				return APPub.StringUtils.ByteToHexString(enc);//返回加密后数据
    			} catch (Throwable e) {
    				e.printStackTrace();
    			}
    			return null;
    		}
    

    解密方法

    参数是数据源,返回加密前的原始数据

    public static String decrypt(String Data) {
    			String Rlt = "";
    			try {
    				byte[] datasource = APPub.StringUtils.HexStringToByte(Data);// Data.getBytes("UTF-8");
    				// DES算法要求有一个可信任的随机数源
    				SecureRandom random = new SecureRandom();
    				// 创建一个DESKeySpec对象
    				DESKeySpec desKey = new DESKeySpec(password.getBytes("UTF-8"));
    				// 创建一个密匙工厂
    				SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    				// 将DESKeySpec对象转换成SecretKey对象
    				SecretKey securekey = keyFactory.generateSecret(desKey);
    				// Cipher对象实际完成解密操作
    				Cipher cipher = Cipher.getInstance("DES");
    				// 用密匙初始化Cipher对象
    				cipher.init(Cipher.DECRYPT_MODE, securekey, random);
    				// 真正开始解密操作
    				byte[] dec = cipher.doFinal(datasource);
    				return new String(cipher.doFinal(datasource), "UTF-8");
    			} catch (Exception e) {
    				e.printStackTrace();
    
    			}
    			return Rlt;
    		}
    

    博客资料:
    DES加密

    更多相关内容
  • 使用java实现的DES算法加密,带有界面。DES加密算法JAVA实现(带简单界面)
  • des加密算法java实现

    2016-04-17 10:12:41
    DES加解密算法java实现,可运行!
  • 项目中需要用到这个,后来到网上找了不少,但算出来结果不对.这个是经过个人验证的.有类似需要的可以考虑
  • 这是一个用Java实现的DES高级加密算法的源代码
  • DES算法为密码体制中的对称密码体制,是一个分组加密算法,典型的DES以64位为分组对数据加密,加密和解密用的是同一个算法。 这里以Java代码实现DES算法。
  • DES数据加密算法,网络安全中较为基础的算法之一,用于学习交流使用
  • 主要介绍了java实现的DES加密算法,结合实例形式详细分析了java实现DES加密操作的原理、实现技巧与相关注意事项,需要的朋友可以参考下
  • 下面小编就为大家带来一篇Java最简单的DES加密算法实现案例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 三重DES加密实验

    实验环境

    Eclipse

    实验步骤

    利用Java开发一个文件加密软件,使之能够对任何文件通过三重DES 加密,加密密钥key1、key2、key3由用户输入的24个字符构成,加密后生成的文件为“原文件名.tdes”。

    单击“浏览...”按钮可选择加密或解密的文件。然后输人24个字符的密钥,程序自动取前8个字符为keyl,中间8个字符为key2,最后8个字符为key3。之后,单击“加密”或“解密”按钮,即可进行加密或解密。注意,在对文件解密时,在文件选择文本框里的文件扩展名必须为.tdes。

    源代码

    import java.awt.*;
    
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    import javax.crypto.spec.DESedeKeySpec;
    import javax.swing.*;
    import java.awt.event.*;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    
    
    public class FileEncrypter extends JFrame{
        public static void main(String[] args) {
            FileEncrypter fe = new FileEncrypter();
            fe.show();
        }
    
        FileEncrypter(){
            this.setSize(550,200);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setLocation(400,300);
            this.setTitle("3DES加密工具");
            Container c = this.getContentPane();
            c.setLayout(new FlowLayout());
            JLabel label = new JLabel("选择文件");
            c.add(label);
            final JTextField fileText = new JTextField(35);
            c.add(fileText);
    
            JButton chooseButton = new JButton("浏览");
            chooseButton.addActionListener(new ActionListener(){
                //浏览按钮的点击事件监听
                @Override
                public void actionPerformed(ActionEvent e){
                    JFileChooser chooser = new JFileChooser();
                    chooser.setCurrentDirectory(new File("."));
                    int result = chooser.showOpenDialog(null);
                    if(result == JFileChooser.APPROVE_OPTION){
                        //获得文件绝对路径
                        String path = chooser.getSelectedFile().getAbsolutePath();
                        fileText.setText(path);
                    }
                }
            });
    
            c.add(chooseButton);
            JLabel label2 = new JLabel("秘钥(24个字符):");
            c.add(label2);
            final JTextField keyText = new JTextField(35);
            c.add(keyText);
            JButton jbe = new JButton("加密");
            c.add(jbe);
            jbe.addActionListener(new ActionListener(){
                //以下编写"加密"按钮的监听和事件
                @Override
                public void actionPerformed(ActionEvent event) {
                    String wenjian,miyao;
                    wenjian = fileText.getText();
                    miyao = keyText.getText();
                    if("".equals(wenjian) || wenjian == null){
                        JOptionPane.showMessageDialog(null,"请选择文件!","提示",JOptionPane.OK_OPTION);
                    }else{
                        if("".equals(miyao) || miyao == null){
                            JOptionPane.showMessageDialog(null,"请输入24字节秘钥!","提示",JOptionPane.OK_OPTION);
                        }else{
                            if(miyao.length() != 24){
                                JOptionPane.showMessageDialog(null, "秘钥必须为24字节!","提示",JOptionPane.OK_OPTION);
                            }else{
                                //将三个秘钥分别 存入三个字节型数组中
                                byte[] key1 = miyao.substring(0,8).getBytes();
                                byte[] key2 = miyao.substring(8,16).getBytes();
                                byte[] key3 = miyao.substring(16,24).getBytes();
    
                                File file = new File(wenjian);
                                //读取明文并存入字节型数组plain中
                                byte[] plain = bytefromfile(file);
    
                                try {
                                    byte[] bytOut = encryptByDES(encryptByDES(encryptByDES(plain,key1),key2),key3);
                                    String fileOut = wenjian + ".tdes";
                                    FileOutputStream fos = new FileOutputStream(fileOut);
                                    for(int i = 0; i < bytOut.length; i++){
                                        fos.write((int)bytOut[i]);
                                    }
                                    fos.close();
                                    JOptionPane.showMessageDialog(null,"加密成功!","提示",JOptionPane.INFORMATION_MESSAGE);
                                } catch (Exception e) {
                                    //e.printStackTrace();
                                    JOptionPane.showMessageDialog(null,"加密失败!请检查文件或者秘钥","提示",JOptionPane.OK_OPTION);
                                }
    
                            }
                        }
                    }
                }
    
            });
    
    
            JButton jbD = new JButton("解密");
            c.add(jbD);
            //解密按钮点击事件
            jbD.addActionListener(new ActionListener(){
    
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    String wenjian,wenjian1,miyao;
                    wenjian = fileText.getText();
                    miyao = keyText.getText();
                    if("".equals(wenjian) || wenjian == null){
                        JOptionPane.showMessageDialog(null,"请选择文件!","提示",JOptionPane.OK_OPTION);
                        return;
                    }
                    if(wenjian.substring(wenjian.length() - 5).toLowerCase().equals(".tdes")){
                        if(miyao.length()!=24){
                            JOptionPane.showMessageDialog(null, "秘钥必须为24字节!","提示",JOptionPane.OK_OPTION);
                            return;
                        }else{
                            wenjian1 = wenjian.substring(0,wenjian.length() - 5);
                            JFileChooser chooser = new JFileChooser();
                            chooser.setCurrentDirectory(new File("."));
                            //用户指定要保存的文件的位置
                            chooser.setSelectedFile(new File(wenjian1));
                            int ret = chooser.showSaveDialog(null);
                            if(ret == 0){
                                byte[] key1 = miyao.substring(0,8).getBytes();
                                byte[] key2 = miyao.substring(8,16).getBytes();
                                byte[] key3 = miyao.substring(16,24).getBytes();
    
                                File file = new File(wenjian);
                                //读取密文
                                byte[] miwen = bytefromfile(file);
                                try{
                                    //解密
                                    byte[] bytOut = decryptByDES(decryptByDES(decryptByDES(miwen,key3),key2),key1);
    
                                    File fileOut = chooser.getSelectedFile();
                                    fileOut.createNewFile();
                                    FileOutputStream fos = new FileOutputStream(fileOut);
    
                                    for(int i = 0; i < bytOut.length; i++){
                                        fos.write((int) bytOut[i]);
                                    }
    
                                    fos.close();
                                    JOptionPane.showMessageDialog(null, "解密成功!","提示",JOptionPane.INFORMATION_MESSAGE);
    
                                }catch (Exception e) {
                                    JOptionPane.showMessageDialog(null, "解密失败!请检查文件或秘钥","提示",JOptionPane.OK_OPTION);
                                }
    
    
                            }
                        }
                    }else{
                        JOptionPane.showMessageDialog(null, "不是合法的加密文件!","提示",JOptionPane.OK_OPTION);
                    }
                }
    
            });
    
    
    
        }
    
    
        //从输入的文件中读取字节,保存于TextofFile数组中,并返回
        private byte[] bytefromfile(File filein){
            byte[] TextofFile = new byte[(int)filein.length()];
            try{
                FileInputStream fin = new FileInputStream(filein);
                for(int i = 0; i < filein.length(); i++){
                    TextofFile[i] = (byte)fin.read();
                }
                fin.close();
            }catch(IOException e){
                e.printStackTrace();
            }
            return TextofFile;
        }
    
        //根据输入的明文进行加密 
        private byte[] encryptByDES(byte[] bytP, byte[] bytKey) throws Exception{
            DESKeySpec desKS = new DESKeySpec(bytKey);
            SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
            SecretKey sk = skf.generateSecret(desKS);
            Cipher cip = Cipher.getInstance("DES");
            cip.init(Cipher.ENCRYPT_MODE, sk);
            return cip.doFinal(bytP);
        }
    
        //根据密文和秘钥进行解密
        private byte[] decryptByDES(byte[] bytE, byte[] bytKey) throws Exception{
            DESKeySpec desKS = new DESKeySpec(bytKey);
            SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
            SecretKey sk = skf.generateSecret(desKS);
            Cipher cip = Cipher.getInstance("DES");
            cip.init(Cipher.DECRYPT_MODE, sk);
            return cip.doFinal(bytE);
        }
    
    
    }

    运行截图

     

    原文:

     加密后:

    对加密后的文件解密 

     

     

     

    展开全文
  • 主要介绍了使用java自带des加密算法实现文件加密和字符串加密的示例,需要的朋友可以参考下
  • DES算法Java实现源代码

    2019-04-08 17:36:47
    DES算法Java实现源代码;网络安全技术及应用;java图形界面实现
  • DES加密算法Java实现】

    千次阅读 2021-04-13 22:20:55
    DES是一个分组加密算法,以64位为分组对数据加密(每次处理固定长度的数据段,称之为分组)。如果加密的数据长度不是64位的倍数,可以按照某种具体的规则来填充位。 DES的明文长为64位,密钥长64位,但密钥事实上是...

    简单介绍

    1. DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准,2000年以前一直是业界的标准。
    2. DES是一个分组加密算法,以64位为分组对数据加密(每次处理固定长度的数据段,称之为分组)。如果加密的数据长度不是64位的倍数,可以按照某种具体的规则来填充位。
    3. DES的明文长为64位,密钥长64位,但密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组。
    4. DES算法具体通过对明文进行一系列的排列和替换操作来将其加密。DES 解密算法与加密算法完全相同,只需要将子密钥的使用顺序反过来就行了。

    算法流程

    DES加密算法流程总体如上图所示,主体内容为中间操作(包括密码函数f和异或操作)循环16次。

    DES加密算法五个最值得注意的部分为:

    • IP置换;
    • 子密钥 Ki 的获取;
    • 密码函数 f ;
    • 逆IP置换;
    • 其他;

    IP置换

    IP(initial permutation 初始排列)是一个 8x8 的置换表:

        // Replacement Table(RT)
        final int RT_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置换表的含义为:原来的58位现在排在第一位,50位排在第二位…以此类推【下文所有置换都是这个含义】。注:该过程输入是64位的分组,IP置换以后得到的是一个 64 位的输出。

    子密钥 Ki 的获取

    这是图片

    • 根据密钥选择置换表RT_Key,将 64 位输入密钥变成 56 位。(去掉了奇偶校验位)

    • RT_Key置换得到的 56 位密钥(其实这也是一种压缩置换,特指去掉了奇偶校验位的过程),分为前28位 C0 和后28位 D0,分别对它们进行循环左移,C0左移得到 C1,D0 左移得到 D1。

    • 将 C1 和 D1 合并,然后通过RT_Compress表进行压缩置换,得到当前这一轮的 48 位子密钥 K1 。

    • 然后对 C1 和 D1 进行左移和压缩置换,获取下一轮的子密钥……一共进行16轮,得到 16 个 48 位的子密钥。

    这部分需要用到的置换表和移动位数记录等常量如下:

    // 密钥选择(置换)表,64位密钥去掉校验位,选择剩下的56位作为新的密钥。可以发现,去掉校验位的同时还打乱了顺序
        final int RT_Key[] = {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};
    
        // 压缩置换表,将56位密钥压缩成48位子密钥,同时打乱顺序
        final int RT_Compress[] = {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};
    
        // 每轮左移的位数
        final int shiftBits[] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
    

    密码函数 f

    密码函数f(R, K)接受两个输入:32 位的R数据(明文的右半部分)和 48 位的子密钥(Ki)。然后:

    • 通过表 E 进行扩展置换,将输入的 32 位数据扩展为 48 位;

    • 将扩展后的 48 位数据与 48 位的子密钥进行异或运算;

    • 将异或得到的 48 位数据分成 8 个 6 位的块,每一个块通过对应的一个 S 表产生一个 4 位的输出。其中,每个 S 表都是 4 行 16 列。具体的置换过程如下:把 6 位输入中的第 1 位和第 6 位取出来行成一个两位的二进制数 x ,作为 Si 表中的行数(0~3);把 6 位输入的中间 4 位构成另外一个二进制数 y,作为 Si 表的列数(0~15);查出 Si 表中 x 行 y 列所对应的整数,将该整数转换为一个 4 位的二进制数。

    • 把通过 S 表置换得到的 8 个 4 位连在一起,形成一个 32 位的数据。然后将该 32 位数据通过表 P 进行置换(称为P-置换),置换后得到一个仍然是 32 位的结果数据,这就是f(R, K)函数的输出。

      这部分用到了扩展置换表RT_E,8个S表以及P-置换表(RT_P),如下:

              // 扩展置换表 RT_E,将32位扩展至48位
          final int RT_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};
      
          // S盒,每个S盒Si是4x16的置换表,6位 -> 4位
          final int S_BOX[][][] ={
              {
                  {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}
              }
          };
      
          // P置换,32位 -> 32位
          final int RT_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 };
      

    逆IP置换

    合并 L16 和 R16 得到一个 64 位的数据,再经过尾置换后得到的就是 64 位的密文。注意:要将 L16和 R16 合并成 R16L16(即左右互换)。逆IP置换表如下:

        // 逆IP置换表
        final int RT_InverseIP [] = {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};
    

    注意:逆IP置换就是IP置换的反操作,A经过IP置换得到B,那B经过逆IP置换就可以得到A。逆IP置换表中第一个数是40,而IP置换表中,第40个元素为1。

    现在我们可以回到本文的开头,去看看 DES 算法的整体流程图,思路就已经很清楚了。

    其他

    1. 异或运算(图中的⊕符号)是指两个多位比特流之间的异或,操作为:对比特流逐位采用异或运算再拼接起来。异或运算规则为:[相同为0,不同为1,即1 ^ 1 = 0;0 ^ 0 = 0;1 ^ 0 = 1]

    代码实现

    package lesson;
    
    public class DES {
        // Replacement Table(RT)IP置换表
        final static int[] RT_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 };
    
        // 密钥选择(置换)表,64位密钥去掉校验位,选择剩下的56位作为新的密钥。可以发现,去掉校验位的同时还打乱了顺序
        final static int[] RT_Key = {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};
    
        // 压缩置换,将56位密钥压缩成48位子密钥
        final static int[] RT_Compress = {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};
    
        // 每轮左移的位数
        final static int[] shiftBits = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
    
        // 扩展置换表 RT_E,将32位扩展至48位
        final static int[] RT_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};
    
        // S盒,每个S盒Si是4x16的置换表,6位 -> 4位
        final static int[][][] S_BOX ={
            {
                {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}
            }
        };
    
        // P置换,32位 -> 32位
        final static int[] RT_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 };
    
        // 逆IP置换表
        final static int[] RT_InverseIP = {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};
    
        /**********************************************************************/
        /*                                                                    */
        /*                            下面是DES算法实现                         */
        /*                                                                    */
        /**********************************************************************/
    
        //生成16个子密钥
        public static StringBuffer[] GenerateSubKey(StringBuffer str, boolean flag) throws Exception{
            if(str.length()!=64){
                throw new Exception("输入密钥长度不是64位!");
            }
            else {
                //密钥选择
                StringBuffer choosedKey = new StringBuffer();
                for (int i = 0; i < RT_Key.length; i++) {
                    choosedKey.append(str.charAt(RT_Key[i]-1));
                }
                //拆分密钥
    //            System.out.println("choosedKey.length():"+choosedKey.length());
                StringBuffer leftString = new StringBuffer(choosedKey.substring(0,28));
                StringBuffer rightString = new StringBuffer(choosedKey.substring(28,56));
    
                //16次循环得到16个子密钥
                StringBuffer[] res = new StringBuffer[16];
                for (int i = 0; i < 16; i++) {
                    int shiftBit=shiftBits[i];
                    //两部分密钥分别左移
                    StringBuffer temp_left=new StringBuffer(leftString);
                    StringBuffer temp_right=new StringBuffer(rightString);
                    for (int j = 0; j < leftString.length(); j++) {
                        if(j-shiftBit<0){
                            leftString.setCharAt(j,temp_left.charAt(j-shiftBit+28));
                            rightString.setCharAt(j,temp_right.charAt(j-shiftBit+28));
                        }else{
                            leftString.setCharAt(j,temp_left.charAt(j-shiftBit));
                            rightString.setCharAt(j,temp_right.charAt(j-shiftBit));
                        }
                    }
                    //压缩置换
                    StringBuffer temp=new StringBuffer(leftString);
                    StringBuffer input = temp.append(rightString);
                    StringBuffer subKey = new StringBuffer();
                    for (int k = 0; k < RT_Compress.length; k++) {
                        subKey.append(input.charAt(RT_Compress[k]-1));
                    }
                    res[i]=subKey;
                }
                StringBuffer[] res_reverse = new StringBuffer[16];
                for (int i = 0; i < res.length; i++) {
                    res_reverse[i]=res[res.length-i-1];
                }
                return flag?res:res_reverse;
            }
        }
    
        //IP置换
        public static StringBuffer IPReplacement(StringBuffer str){
            StringBuffer res = new StringBuffer();
            for (int i = 0; i < RT_IP.length; i++) {
                res.append(str.charAt(RT_IP[i]-1));
            }
            return res;
        }
    
        //执行F密码函数
        public static StringBuffer function(StringBuffer subKey, StringBuffer R) throws Exception {
            //1.扩展置换
            StringBuffer extendedString = new StringBuffer();
            for (int i = 0; i < RT_E.length; i++) {
                extendedString.append(R.charAt(RT_E[i]-1));
            }
            //2.异或操作
            StringBuffer xor = XOR(extendedString, subKey);
            if(xor.length()!=48){
                throw new Exception("异或结果不等于48位!");
            }else{
                //3.S盒
                StringBuffer S_output =new StringBuffer();
                for (int i = 0; i < 8; i++) {
                    //3.1 拆分为6位子串substring
                    String substring = xor.substring(6 * i, 6 * (i+1));
                    //3.2 将substring取0,5位为x;其余4位为y【二进制转换】
                    int x=binaryToDecimal(substring.substring(0,1)+substring.substring(5,6));
                    int y=binaryToDecimal(substring.substring(1,5));
                    //3.3 从S盒取S[i][x][y]转化为4位输出
                    String s = Integer.toBinaryString(S_BOX[i][x][y]);
                    StringBuffer stringBuffer = new StringBuffer(s);
                    //3.4 如果输出未达到4位则往前补0,补齐4位
                    while(4-stringBuffer.length()!=0){
                        stringBuffer.insert(0,'0');
                    }
                    S_output.append(stringBuffer);
                }
                //4.P盒
                StringBuffer res = new StringBuffer();
                for (int i = 0; i < RT_P.length; i++) {
                    res.append(S_output.charAt(RT_P[i]-1));
                }
                return res;
            }
        }
    
        //执行异或操作
        public static StringBuffer XOR(StringBuffer L, StringBuffer output) throws Exception{
    
            if(L.length()!=output.length()){
                throw new Exception("两者长度不同,不能进行异或运算!");
            }else{
                StringBuffer res = new StringBuffer(L.length());
                for (int i = 0; i < L.length(); i++) {
                    int temp =0;
                    if(L.charAt(i)!=output.charAt(i)){temp=1;}
                    res.append(temp);
                }
            return res;
            }
        }
    
        //逆IP置换
        public static StringBuffer ReverseIPReplacement(StringBuffer str){
            StringBuffer res = new StringBuffer();
            for (int i = 0; i < RT_InverseIP.length; i++) {
                res.append(str.charAt(RT_InverseIP[i]-1));
            }
            return res;
        }
    
        //二进制转化为10进制
        public static int binaryToDecimal(String str){
            int len  = str.length();
            int res=0;
            for (int i = 0; i < len; i++) {
                res+=Integer.parseInt(String.valueOf(str.charAt(len-i-1)))*Math.pow(2,i);
            }
            return res;
        }
    
        //完整加密过程
        public static StringBuffer Encryption(StringBuffer Plaintext, StringBuffer Key) throws Exception {
            //1.获取子密钥
            StringBuffer[] subKeys =GenerateSubKey(Key,true);
            //2.IP置换
            StringBuffer stringBuffer = IPReplacement(Plaintext);
            StringBuffer Leftstring = new StringBuffer(stringBuffer.substring(0, 32));
            StringBuffer Rightstring = new StringBuffer(stringBuffer.substring(32,64));
            //3.for循环16轮
            for (int i = 0; i < 16; i++) {
                //3.1 f函数
                StringBuffer f_output=function(subKeys[i],Rightstring);
                //3.2 异或
                StringBuffer temp=XOR(Leftstring,f_output);
                //3.3 更新Li和Ri
                Leftstring=Rightstring;
                Rightstring=temp;
            }
            //4.左右互换
            StringBuffer res = Rightstring.append(Leftstring);
            //5.逆IP置换
            res=ReverseIPReplacement(res);
            return  res;
        }
    
        //完整解密过程
        public static StringBuffer Decryption(StringBuffer Plaintext, StringBuffer Key) throws Exception {
            //1.获取子密钥
            StringBuffer[] subKeys =GenerateSubKey(Key,false);
            //2.IP置换
            StringBuffer stringBuffer = IPReplacement(Plaintext);
            StringBuffer Leftstring = new StringBuffer(stringBuffer.substring(0, 32));
            StringBuffer Rightstring = new StringBuffer(stringBuffer.substring(32,64));
            //3.for循环16轮
            for (int i = 0; i < 16; i++) {
                //3.1 f函数
                StringBuffer f_output=function(subKeys[i],Rightstring);
                //3.2 异或
                StringBuffer temp=XOR(Leftstring,f_output);
                //3.3 更新Li和Ri
                Leftstring=Rightstring;
                Rightstring=temp;
            }
            //4.左右互换
            StringBuffer res = Rightstring.append(Leftstring);
            //5.逆IP置换
            res=ReverseIPReplacement(res);
            return  res;
        }
    
    
        /**********************************************************************/
        /*                                                                    */
        /*                            下面是测试代码                             */
        /*                                                                    */
        /**********************************************************************/
    
    //    a) 使用同一密钥,对两组明文进行加密和解密。
    //            64位密钥:
    //            00000010 10010110 01001000 11000100 00111000 00110000 00111000 01100100
    //
    //            64位明文块1:
    //            00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    //
    //            64位明文块2(与明文块1仅有一位的不同):
    //            10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    //
    //    输出两个密文块的二进制流,统计两个密文块间不同数据位的数量。
    //
    //    b) 对同一段明文,使用不同密钥进行加密和解密操作。
    //            64位密钥1:
    //            11100010 11110110 11011110 00110000 00111010 00001000 01100010 11011100
    //
    //            64位密钥2(与密钥1仅有一位的不同):
    //            01100010 11110110 11011110 00110000 00111010 00001000 01100010 11011100
    //
    //    明文:
    //            01101000 10000101 00101111 01111010 00010011 01110110 11101011 10100100
    //
    //    输出两个密文块的二进制流,统计两个密文块间不同数据位的数量。
    
    
        public static void main(String[] args) throws Exception {
    
            System.out.println();
            System.out.println("a):使用同一密钥,对两组明文进行加密");
            String key ="00000010 10010110 01001000 11000100 00111000 00110000 00111000 01100100";
            String plaintext_1 ="00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000";
            String plaintext_2 ="10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000";
            StringBuffer Key= new StringBuffer(key.replaceAll(" ",""));
            StringBuffer Plaintext_1= new StringBuffer(plaintext_1.replaceAll(" ",""));
            StringBuffer Plaintext_2= new StringBuffer(plaintext_2.replaceAll(" ",""));
            StringBuffer Ciphertext_1 = Encryption(Plaintext_1, Key);
            StringBuffer Ciphertext_2 = Encryption(Plaintext_2, Key);
            System.out.println("密钥:"+Key);
            System.out.println("明文1:"+Plaintext_1);
            System.out.println("明文2:"+Plaintext_2);
            System.out.println("========================================================================");
            System.out.println("密文1:"+Ciphertext_1);
            System.out.println("密文2:"+Ciphertext_2);
            Helper(Ciphertext_1, Ciphertext_2);
            System.out.println();
    
    
            System.out.println("b):对同一段明文,使用不同密钥进行加密操作");
            String key_1 ="11100010 11110110 11011110 00110000 00111010 00001000 01100010 11011100";
            String key_2 ="01100010 11110110 11011110 00110000 00111010 00001000 01100010 11011100";
            String plaintext ="01101000 10000101 00101111 01111010 00010011 01110110 11101011 10100100";
            StringBuffer Key_1= new StringBuffer(key_1.replaceAll(" ",""));
            StringBuffer Key_2= new StringBuffer(key_2.replaceAll(" ",""));
            StringBuffer Plaintext= new StringBuffer(plaintext.replaceAll(" ",""));
            StringBuffer Ciphertext_b1 = Encryption(Plaintext_1, Key);
            StringBuffer Ciphertext_b2 = Encryption(Plaintext_2, Key);
            System.out.println("密钥1:"+Key_1);
            System.out.println("密钥2:"+Key_2);
            System.out.println("明文:"+Plaintext);
            System.out.println("===========================================================================");
            System.out.println("密文1:"+Ciphertext_b1);
            System.out.println("密文2:"+Ciphertext_b2);
            Helper(Ciphertext_b1, Ciphertext_b2);
            System.out.println();
    
    
            System.out.println("c):附加,对一个明文和密钥,先加密后解密");
            StringBuffer Ciphertext_c = Encryption(Plaintext_1, Key);
            StringBuffer Plaintext_c = Decryption(Ciphertext_c, Key);
            System.out.println("明文:"+Plaintext_1);
            System.out.println("密钥:"+Key);
            System.out.println("===========================================================================");
            System.out.println("加密后密文:"+Ciphertext_c);
            System.out.println("再解密后明文:"+Plaintext_c);
        }
    
        //帮助统计两个比特流之间不同的位数的数量
        public static void Helper(StringBuffer str1,StringBuffer str2){
            int res=0;
            for (int i = 0; i < str1.length(); i++) {
                int add=str1.charAt(i)==str2.charAt(i)?0:1;
                res+=add;
            }
            System.out.println("两个密文块间不同数据位的数量为:"+res);
        }
    }
    

    结果图:

    总结和思考

    1. 要多用StringBuffer(或StringBuilder)可以比 String 类更高效地处理字符串,如append操作不需要索引,setCharAt(index,‘s’) 可以更改某一个位置的char值(String做不到)。但是去除空格的时候还是得转成String类。

      		//去除字符串头尾的空格
      		System.out.println(str.trim());
      		
      		//只去除字符串中的空格
      		System.out.println(str.replaceAll(" ", ""));
      		
      		//去除空白字符, \s 可以匹配空格、制表符、换页符等空白字符的其中任意一个
      		System.out.println(str.replaceAll("\\s*", ""));
      
    2. DES加密解密就是密钥顺序反一下就好。Java函数没有默认参数(除非重载或者工厂方法实现…),所以生成子密钥需要手动输入参数flag,显式定义是子密钥在数组中顺排还是逆排(对应是加密还是解密)。

    3. 二进制与十进制间的转换

      		//10进制转化为二进制字符串
      		Integer.toBinaryString()
             
             //二进制转化为10进制,注意:幂次用Math.pow(2,i),而不要用2^i,后者相当于2+i
         public static int binaryToDecimal(String str){
              int len  = str.length();
              int res=0;
              for (int i = 0; i < len; i++) {
                  res+=Integer.parseInt(String.valueOf(str.charAt(len-i-1)))*Math.pow(2,i);
              }
              return res;
          }
      
    4. Java不像C++那样有指针。在给对象初始化的时候,记得不要用对象直接赋值的方式,而应该new一个新对象

                  //压缩置换
                   StringBuffer temp=new StringBuffer(leftString);
                   StringBuffer input = temp.append(rightString);
      
        			//这里不能写成这样,这是把leftString指针给了temp,后面操作temp其实就是操作leftString
         			 StringBuffer temp=leftString;
      
        			//这里也不能写成这样,这样leftString就会变长,因为append了一个rightString
         			 StringBuffer input = leftString.append(rightString);
      
      
    5. 什么是雪崩效益?根据以上结果,说明DES加密算法是否具有该性质:在密码学中,雪崩效应Avalanche effect)指加密算法(尤其是块密码和加密散列函数)的一种理想属性。雪崩效应是指当输入发生最微小的改变(例如,反转一个二进制位)时,也会导致输出的剧变(如,输出中一半的二进制位发生反转)。在高品质的块密码中,无论密钥明文的任何细微变化都应当引起密文的剧烈改变。DES有很好的雪崩效应,即使明文或密钥只更改了一位,密文也会有很大的差别(27位)。

    参考文献

    DES加密算法的C++实现

    数据加密算法–详解DES加密算法原理与实现

    DES算法详解

    展开全文
  • 虽然如此,在某些简单应用中,我们还是可以使用DES加密算法,本文简单讲解DES的JAVA实现。 JAVA实现加密代码有详细解释,不多废话。注意:DES加密和解密过程中,密钥长度都必须是8的倍数 代码如下: public byte[] ...
  • DES加密算法JAVA代码

    2008-12-02 14:17:59
    DES加密算法JAVA语言设计代码,是非常重要的加密技术
  • DES加密算法 java

    2014-03-27 08:32:15
    DES算法java语言写的,为了赚点积分下载自己需要的东西。谢谢大家!其实什么语言写是无所谓的,关键是一些基本模块的编写及相应的调用!
  • 本周的密码学实验要求使用任意编程语言来实现des加密算法,于是我在查阅了相关资料后有了以下成果。首先,DES算法作为经典的分块密码(block cipher),其主要的实现过程由两部分组成,分别是密钥的生成以及明文的处理...

    本周的密码学实验要求使用任意编程语言来实现des加密算法,于是我在查阅了相关资料后有了以下成果。

    首先,DES算法作为经典的分块密码(block cipher),其主要的实现过程由两部分组成,分别是密钥的生成以及明文的处理。

    610994d8c10bac6e9c18ddd3404a1298.png

    加密的大致流程如图所示

    作为分块密码,密钥的输入以及明文的输入均为64位2进制数。

    下面首先来说密钥的生成过程。

    635f3b05b27e9782c9469ac093db5ebe.png

    密钥处理部分如图所示

    密钥的输入为64位,例如00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001,然后经过pc-1盒置换,会去除每一个8的倍数位(奇偶校验位)并打乱次序,将密钥变为56位。pc-1的置换表如下(框中的数字代表的是原密钥的位置,而不是数据)

    1 57,49,41,33,25,17,9,1,2 58,50,42,34,26,18,10,2,3 59,51,43,35,27,19,11,3,4 60,52,44,36,63,55,47,39,5 31,23,15,7,62,54,46,38,6 30,22,14,6,61,53,45,37,7 29,21,13,5,28,20,12,4

    也就是说,经过pc-1盒的置换原来第57位的1将会到第1位,原来49位的数据会到第2位,以此类推。在DES密钥加密的过程中,这种置换方式经常出现。

    在经过了pc-1盒的置换后,原来56位的密钥会被均分为两组成为c0,d0。然后l0和d0会经过循环左移(left shift)的处理。

    例如一串密钥为1010101,在经过一位的循环左移后会变成0101011,即循环左移几位,最左边的几位数据会紧接在后面,达到一种左移的效果。左移后的密钥块分别称为c1,d1。这时候,将c1以及d1组合起来,经过pc-2的置换(类似于pc-1)。

    1 14,17,11,24,1,5,2 3,28,15,6,21,10,3 23,19,12,4,26,8,4 16,7,27,20,13,2,5 41,52,31,37,47,55,6 30,40,51,45,33,48,7 44,49,39,56,34,53,8 46,42,50,36,29,32

    经过了pc-2盒的置换后,原本56位的密钥会变为48位。这个时候,第一个能够用于加密的子密钥k1就生成好了。在des算法密钥生成的过程中,一个主密钥会经过16轮的循环左移和pc-2置换,生成16个子密钥。循环左移的位数和轮次的关系如下表

    867fe1ae092f873924b3f44bacd89ccc.png

    后续子密钥的生成过程就是重复上面的过程,c1和d1再进行循环左移得到c2和d2,再经过pc-2盒置换得到k2,c2和d2再经过左移得到c3和d3经过pc-2盒得到k3.....经过这样的操作16轮,得到16个子密钥。密钥的生成过程大致如上,接下来来阐述明文的处理过程。

    3ec03b1096eb0460729c5626b2d688b9.png明文的处理流程大致如图所示。

    首先,64位明文的输入需要经过初始置换,并把输出块分为L0,R0两部分,每部分32位。(有点类似于密钥初始化时的pc-1)置换规则如下:

    1 58,50,42,34,26,18,10,2,2 60,52,44,36,28,20,12,4,3 62,54,46,38,30,22,14,6,4 64,56,48,40,32,24,16,8,5 57,49,41,33,25,17, 9,1,6 59,51,43,35,27,19,11,3,7 61,53,45,37,29,21,13,5,8 63,55,47,39,31,23,15,7

    这个过程与pc-1阶段类似,置换后的第1位是原来的第58位,第2位是原来的第50位,以此类推。L0是置换后数据的前32位,R0是置换后的后32位。

    经过了初始置换之后,R0会进依次进入E-box,S-box,P-box三个置换盒,进行下一步的处理。

    fdeec3c6847f62d18c74dac7cfa725ba.png

    E-box的处理过程如图示

    E-box本质上是将原来32位的数据变为了48位,原理是将原来的32位输入以四位为一个单元分开,然后这个单元的第1位会复制到上一个单元的最后一位,这个单元的最后一位会变为下一个单元的第1位。看图可知,1234分块的第一位复制到了最后一块成为了第48位,第32位复制到了第1位成为了新数据组的第1位,具体过程如果还不明晰的话可以仔细看图解决。

    在经过了E-box后,新的R0变为了48位,刚好与生成的密钥位数一致。这个时候,需要使用k1和新R0执行一次异或(相同记为0,不同记为1)操作,在异或操作结束后新的数据块会进入S-Box进行替代。

    b52633116bc74c4888f27bacaf460ed4.png

    S-box会将48位的输入按照次序分为8组,分别进入8个子盒进行替代,每个盒的输入是6位,输出是4位。8个子盒原理如下:

    S-box1

    1 14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,2 0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,3 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,4 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13

    S-box2

    1 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10,2 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5,3 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,4 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9

    S-box3

    1 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8,2 13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,3 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,4 1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12

    S-box4

    1 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,2 13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,3 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,4 3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14

    S-box5

    1 2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,2 14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,3 4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,4 11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3

    S-box6

    1 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11,2 10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,3 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,4 4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13

    S-box7

    1 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,2 13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,3 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,4 6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12

    S-box8

    1 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7,2 1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,3 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,4 2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11

    S-box的计算规则:

    以S-box8为例,如果该盒输入为六位011100。取第一位和最后一位组成二进制数00,转化为十进制为0,对应该盒第1行。中间四位组成1110,十进制化为14,对应该盒第15列(考试的时候这个地方错了,,,1551)寻找该盒第1行第15列的元素,是12,转化为2进制是1100,这也就是该盒的输出。

    在经过了S-box置换后,数据块还需一步处理,P-box

    P-box很简单,类似于pc-1,就是简单的置换,32位的输入置换为32位的输出。置换表如下:

    1 16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10,2 2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25

    在经过了这些处理后,原来32位的R0变为了新的32位数据块,这个时候,使用这32位数据块和原来的L0进行异或,变为新的32位R1,这时候,原来的R0成为新的L1。R1再经过E-box扩展,和k2(第二个子密钥)异或,S-box替代,P-box置换的过程。再与L1进行异或,直到使用完所有的16个子密钥(也是16轮)。

    明文经过了这16轮变换之后已经面目全非,这个时候把L和R组合成为64位经过最后的置换,即成为密文。最终置换如下:

    1 40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31,2 38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,3 36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,4 34,2,42,10,50,18,58 26,33,1,41, 9,49,17,57,25

    下面附上从别的老哥那抄来的介绍:

    DES的特点:

    优点:

    效率高,算法简单,系统开销小(真的简单吗,,,,)

    适合加密大量数据

    明文长度和密文长度相等

    缺点:

    需要以安全方式进行秘钥交换

    秘钥管理复杂

    展开全文
  • DES加密算法JAVA实现

    2013-01-11 19:49:14
    通过java实现的DES加密算法,加深对加密机制的了解
  • DES加密图解、DES的java实现代码、3DES的java实现代码
  • Java 3des加密算法ECB模式,亲测完美通过。目前网上的大部分算法都通不过或者加进Base64之类的,还要不下载其它jar包。而代码使用时直接下载运行,无须配置和下载额外的jar包 ,只需换上自己的密钥和待加密的数据...
  • DES加密算法JAVA实现

    2019-12-27 18:24:17
    运行环境:Windows + eclipse + JAVA ...DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位(实际用到了56位,第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1)
  • java加密算法DES

    千次阅读 2021-06-04 08:46:57
    加密 public static String encrypt(String datasource) { try{ DESKeySpec desKey = new DESKeySpec(PASSWORD.getBytes()); //创建一个密匙工厂,获取secretKey SecretKeyFactory keyFactory = ...
  • 常用MD5加密算法和3-DES加密算法java实现,在实际项目中我们会经常用到加密字符串,用md5算法是很多人的选择,其中包含源码,可直接使用。
  • DES加密解密Java工具

    2018-07-18 21:20:50
    des对称加密,对称加密,是一种比较传统的加密方式,其加密运算、解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码),是一种对称加密算法
  • DES加密算法 JAVA语言

    2012-06-04 09:42:46
    JAVA语言编写的DES算法,自己做毕设用到的
  • DES加密算法java实现

    2019-07-23 18:17:30
    由于计算机软件的非法复制,通信的泄密、数据安全受到威胁,解密及盗版问题日益严重,甚至引发国际争端,所以在信息安全技术中,加密技术占有不可替代的位置,因此对信息加密技术和加密手段的研究与开发,受到各国...
  • 本文实例讲述了python实现的DES加密算法和3DES加密算法。分享给大家供大家参考。具体实现方法如下: ############################################################################# # Documentation # #########...
  • } /** * DES加密字符串 * * @param password 加密密码,长度不能够小于8位 * @param data 待加密字符串 * @return 加密后内容 */ public static String encrypt(String password, String data) { if (password== ...
  • DES算法Java实现

    2018-01-17 09:45:05
    DES算法,可扩展成3DES算法Java实现,Eclipse中可直接运行

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,348
精华内容 7,339
关键字:

des加密算法java

java 订阅