美文网首页JAVA进阶
2.2 DES/3DES算法Java用法

2.2 DES/3DES算法Java用法

作者: saillen | 来源:发表于2018-11-29 20:06 被阅读0次

    对称加密技术 - DES系列的Java用法

    Java中的用法

    JDK仅仅提供了针对56位密钥长度的DES算法实现,提供了针对112位、168位密钥长度的3DES的算法实现,使用起来不复杂,主要分为3个步骤:

    • 构建密钥:使用KeyGenerator,这个步骤对称加密算法和非对称加密算法都需要;
    • 构建DES专用的SecretKey:DES和3DES构建SecretKey的时候略有不同,这步是针对存储下来的密钥进行处理;
    • 进行加解密:要注意设置Cipher的工作模式。

    密钥生成

    DES的算法安全很依赖密钥长度,所以一般都要配合KeyGenerator使用,用KeyGenerator建立密钥,密钥生成过程(一般是一次):

    //生成时候DES算法的密钥,主要是密钥长度和随机性,比一般的Random随机性更好
    KeyGenerator kg = KeyGenerator.getInstance("DES")
    //初始化密钥长度
    kg.init(56);
    //生成密钥
    SecretKey secretKey = kg.generateKey();
    //获取密钥,把这个密钥发送给其他系统作为加解密密钥,一般是做base64/toHex
    byte[] b = secretKey.getEncoded();
    

    构建DES密钥

    //将上面的b放到这里构建DES的专用密钥对象
    DESKeySpec dks = new DESKeySpec(keyBytes);
    // 3DS算法的密钥构建过程稍有不同,密钥需要特殊处理
    //DESedeKeySpec 3desKey = new DESedeKeySpec(keyBytes);
    
    //获取一个DES的密钥工厂,用来处理密钥
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    //生成密钥
    SecretKey secretKey = keyFactory.generateSecret(dks);
    
    

    数据加解密

    //获取DES加解密对象
    Cipher cipher = Cipher.getInstance("DES");
    //设置为加密模式:Cipher.DECRYPT_MODE为解密模式
    cipher.init(Cipher.ENCRYPT_MODE,secretKey);
    //加解密都是这个操作,如果是想解密,则在init的设置为解密模式
    byte[] rs = cipher.doFinal(input.getBytes());
    

    完整流程

    在完整流程中,有四点要注意:

    • DES切换到3DES(DESede)的时候,要修改生成的密钥长度,DES的为56位(Java仅支持56位),但是3DES则要112位或者168位;
    • DES切换到3DES的时候,3DES使用DESedeKeySpec这个特殊的类,而DES使用DESKeySpec即可;
    • 密钥产生算法和加密算法不一样,是两个变量,加解密算法还指定了算法工作模式填充模式,一般是在getInstatnce的时候通过/来指定,格式"DES/工作模式/填充模式";
    • 实际使用时,Key产生一次后,使用Base64(or toHex)存储下来,不是每次都产生的,每次都产生效率比较低属于性能浪费;
    public class DESTest {
    
        // private static final String CIPHER_ALGORITHM = "DESede";
        private static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
        private static final String KEY_ALGORITHM = "DES";
    
        public static void main(String[] args) throws Exception {
            // 产生Key,一般只产生一次
            byte[] key = generateKey();
            String keyStr = Base64.getEncoder().encodeToString(key);
            String input = "加密我";
    
            // 加密数据
            byte[] encryptData = encrypt(input.getBytes(), key);
            // 解密数据
            byte[] dencryData = decrypt(encryptData, key);
    
            String msg = String.format("原始数据: %s , Key : %s , 加密数据: %s , 解密数据: %s", input, keyStr,
                    HexBin.encode(encryptData), new String(dencryData));
            System.out.println(msg);
        }
    
        /**
         * 产生符合要求的Key,如果不用KeyGenerator随机性不好,而且要求自己对算法比较熟悉,能产生符合要求的Key
         * 
         * @return
         * @throws NoSuchAlgorithmException
         */
        public static byte[] generateKey() throws NoSuchAlgorithmException {
            KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
            // 3DES要求使用112或者168位密钥
            // kg.init(112);
            kg.init(56);
            SecretKey secretKey = kg.generateKey();
            byte[] key = secretKey.getEncoded();
            return key;
        }
    
        /**
         * 获取算法需要的安全密钥
         * 
         * @param key
         * @return
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeyException
         * @throws InvalidKeySpecException
         */
        public static SecretKey getSecretKey(byte[] key)
                throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
            DESKeySpec keySpec = new DESKeySpec(key);
            // 3DES使用的密钥
            // DESedeKeySpec keySpec = new DESedeKeySpec(key);
            SecretKeyFactory kf = SecretKeyFactory.getInstance(KEY_ALGORITHM);
            SecretKey secretKey = kf.generateSecret(keySpec);
            return secretKey;
        }
    
        /**
         * 加密数据
         * 
         * @param input
         * @param key
         * @return
         * @throws Exception
         */
        public static byte[] encrypt(byte[] input, byte[] key) throws Exception {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
            return cipher.doFinal(input);
        }
    
        /**
         * 解密数据
         * 
         * @param input
         * @param key
         * @return
         * @throws Exception
         */
        public static byte[] decrypt(byte[] input, byte[] key) throws Exception {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
            return cipher.doFinal(input);
        }
    
    }
    

    相关文章

      网友评论

        本文标题:2.2 DES/3DES算法Java用法

        本文链接:https://www.haomeiwen.com/subject/vfhqcqtx.html