DES算法

    xiaoxiao2025-04-01  5

    DES算法

    概要

    DES是有IBM公司研制的一种对称加密算法,美国国家标准局于1977年公布把它作为非机要部门使用的数据加密标准。

    DES是一个分组加密算法,就是将明文分组进行加密,每次按顺序取明文一部分,一个典型的DES以64位为分组,加密解密用算法相同。它的密钥长度为56位,因为每组第8位是用来做奇偶校验,密钥可以是任意56位的数,保密性依赖于密钥。

    加密步骤

    首先生成一套加密密钥,我们提供一个64位的秘钥,然后通过等分、移位、选取、迭代形成一套16个加密密钥,分别供每一轮运算使用。

    假设目前取到一个64位分组,我们称之为M,M经过一个初始置换IP,置换成m0,。将m0明文分为左半部分和右半部分,各32位长。

    然后进行16轮完全相同的运算,在每一轮运算中数据与相应的秘钥结合。

    经过16轮之后,左、右半部分合在一起经过一个末置换(数据整理),这样就完成了加密过程。

    代码实现

    package Singleton; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; public class DESDemo { public static void main(String[] args) { /** * 1.明文 * 2.提供原始秘钥 长度64位,8个字节 */ String clearText ="hello"; String originKey ="12345678"; try { String cipherText = desEncrpt(clearText,originKey); System.out.println(cipherText); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } } /** * 用DES算法进行加密 * ciper * @param clearText * @param originKey * 就是通过对比特为进行数学运算 * @return */ private static String desEncrpt(String clearText, String originKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { //获取加密类对象 Cipher cipher =Cipher.getInstance("DES"); SecretKey key =getKey(originKey); //对加密类对象进行初始化 //mode:加密/解密 //key:对原始秘钥处理之后的秘钥 cipher.init(Cipher.ENCRYPT_MODE,key); //使用加密工具类对象对明文进行加密 变成密文 byte[] doFinal= cipher.doFinal(clearText.getBytes());//默认GBK进行编码 return new String(doFinal);//默认GBK解码 //如果之前使用了其他编码方式,传入后已之前为主。 } private static SecretKey getKey(String originKey) { SecretKeySpec key= new SecretKeySpec(originKey.getBytes(),"DES"); return key; } }

    上述代码会出现乱码问题,

    ?%q%?

    乱码出现的原因

    要找的编码表就是base64。

    注:GBK、UTF-8、base64这些都是编码表

    base64编码

    加密后的结果是字节数组,这些被加密后的字节在码表(如GBK、UTF-8码表)上找不到对应内容,会出现乱码。当乱码字符串再次转换为字节数组时,长度会变化,导致解密失败,所以转换后的数据是不安全的。

    使用Base64对字节数组进行编码,任何字节都能映射成对应的Base64字符,之后都能恢复到字节数组,利用数据的保存与传输,所以是安全的。

    改进后代吗

    import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; public class DESDemo { public static void main(String[] args) { /** * 1.明文 * 2.提供原始秘钥 长度64位,8个字节 */ String clearText ="hello"; String originKey ="12345678"; try { String cipherText = desEncrpt(clearText,originKey); System.out.println(cipherText); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } } /** * 用DES算法进行加密 * ciper * @param clearText * @param originKey * 就是通过对比特为进行数学运算 * @return */ private static String desEncrpt(String clearText, String originKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { //获取加密类对象 Cipher cipher =Cipher.getInstance("DES"); SecretKey key =getKey(originKey); //对加密类对象进行初始化 //mode:加密/解密 //key:对原始秘钥处理之后的秘钥 cipher.init(Cipher.ENCRYPT_MODE,key); //使用加密工具类对象对明文进行加密 变成密文 byte[] doFinal= cipher.doFinal(clearText.getBytes()); byte[] encode =Base64.encode(doFinal); return new String(encode); } private static SecretKey getKey(String originKey) { SecretKeySpec key= new SecretKeySpec(originKey.getBytes(),"DES"); return key; } }

    默认规定,给出的秘钥必须要有8个字节,64位,这样程序员每次必须要提供八个字符的字符串,如果超过或者不够,要报错。现在有需求,不论originKey多长,我们都要形成一个8个字节长度的原始秘钥,不够自动填,超过自动截取。

    private static SecretKey getKey(String originKey) { //不够 初始值为0 byte[]buffer =new byte[8]; //获取用户提供的原始密钥字节数组 byte[] originBytes =originKey.getBytes(); for(int i=0;i<8&&i<originBytes.length;i++){ buffer[i]=originBytes[i]; } SecretKeySpec key= new SecretKeySpec(buffer,"DES"); return key; }

    解密

    import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; public class DesDemo { public static void main(String[] args) { /** * 1.明文 * 2.提供原始秘钥 长度64位,8个字节 */ String clearText ="hello"; String originKey ="12345678"; try { String cipherText = desEncrpt(clearText,originKey); System.out.println(cipherText); String clearText2 =desDecrpt(cipherText,originKey); System.out.println(clearText2); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } } private static String desDecrpt(String cipherText, String originKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { //获取加密类对象 Cipher cipher =Cipher.getInstance("DES"); SecretKey key =getKey(originKey); //对加密类对象进行初始化 //mode:加密/解密 //key:对原始秘钥处理之后的秘钥 cipher.init(Cipher.DECRYPT_MODE,key); byte[] decodebytes =Base64.decode(cipherText); //使用加密工具类对象对明文进行解密 变成明文 byte[] doFinal= cipher.doFinal(decodebytes); // String encodetext =Base64.encode(doFinal); return new String(doFinal); } /** * 用DES算法进行加密 * ciper * @param clearText * @param originKey * 就是通过对比特为进行数学运算 * @return */ private static String desEncrpt(String clearText, String originKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException { //获取加密类对象 Cipher cipher =Cipher.getInstance("DES"); SecretKey key =getKey(originKey); //对加密类对象进行初始化 //mode:加密/解密 //key:对原始秘钥处理之后的秘钥 cipher.init(Cipher.ENCRYPT_MODE,key); //使用加密工具类对象对明文进行加密 变成密文 byte[] doFinal= cipher.doFinal(clearText.getBytes()); String encodetext =Base64.encode(doFinal); return new String(encodetext); } private static SecretKey getKey(String originKey) { //不够 初始值为0 byte[]buffer =new byte[8]; //获取用户提供的原始密钥字节数组 byte[] originBytes =originKey.getBytes(); for(int i=0;i<8&&i<originBytes.length;i++){ buffer[i]=originBytes[i]; } SecretKeySpec key= new SecretKeySpec(buffer,"DES"); return key; } }

    思路:加密后的密文在GBK中有可能找不到,缺漏导致乱码,然后借助base64进行编码,在解密的时候,先通过base64解码,解码为GBK编码,最后结果返回。

    GBK->base64 ->base64->GBK
    最新回复(0)