JAVA應用AES/DES算法時需要注意的地方


先說AES,看代碼:

    public static byte[] doEncrypt(byte[] key, byte[] initialVector, byte[] text) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/補碼方式"
            IvParameterSpec iv = new IvParameterSpec(initialVector);//使用CBC模式,需要一個向量iv,可增加加密算法的強度
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
            byte[] encrypted = cipher.doFinal(text);
            return encrypted;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }



    public static byte[] doEncryptByRandom(int length, byte[] key, byte[] initialVector, byte[] text) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); 
            secureRandom.setSeed(key);
            kgen.init(length, secureRandom);
            SecretKey secretKey = kgen.generateKey();
            byte[] enCodeFormat = secretKey.getEncoded();
            //return doEncrypt(enCodeFormat, initialVector, text);
            SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/補碼方式"
            if (initialVector==null){
                initialVector = new byte[length/8];
            }else if (initialVector.length*8!=length){
                byte[] tmp = new byte[length/8];
                if (tmp.length>initialVector.length){
                    System.arraycopy(initialVector, 0, tmp, 0, initialVector.length);
                }else{
                    System.arraycopy(initialVector, 0, tmp, 0, tmp.length);
                }
                initialVector = tmp;
            }
            IvParameterSpec iv = new IvParameterSpec(initialVector);//使用CBC模式,需要一個向量iv,可增加加密算法的強度
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
            byte[] encrypted = cipher.doFinal(text);
            return encrypted;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

這是之前遇到的問題,

  doEncrypt是給定密鑰和向量進行加密,是最基本的加密算法。

  而doEncryptByRandom則是對密鑰進行了變換之后加密的,變換主要是對密鑰不足的部分進行補充,內容以給定密鑰作為種子,進行隨機生成,並且只要給定同一密鑰,隨機后的結果應該是一致的。

  So,  doEncryptByRandom方法中,

    byte[] enCodeFormat = secretKey.getEncoded();

  把后面

    //return doEncrypt(enCodeFormat, initialVector, text);

  的注釋打開,並注釋掉后面的部分,與操作之前得出的加解密結果是一致的。

 

 

3DES,代碼:

    public static byte[] doTripleEncrypt(byte[] rawKeyData, byte[] plainText) throws Exception {
        byte[] k = new byte[24];
        int len = plainText.length;
        if (plainText.length % 8 != 0) {
            len = plainText.length - plainText.length % 8 + 8;
        }
        byte[] needData = null;
        if (len != 0){
            needData = new byte[len];
        }
        for (int i = 0; i < len; i++) {
            needData[i] = 0x00;
        }
        System.arraycopy(plainText, 0, needData, 0, plainText.length);
        if (rawKeyData.length == 16) {
            System.arraycopy(rawKeyData, 0, k, 0, rawKeyData.length);
            System.arraycopy(rawKeyData, 0, k, 16, 8);
        } else {
            System.arraycopy(rawKeyData, 0, k, 0, 24);
        }
        KeySpec ks = new DESedeKeySpec(k);
        SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede");
        SecretKey ky = kf.generateSecret(ks);        
        Cipher DESedecipher = Cipher.getInstance("DESede/ECB/NoPadding");
        DESedecipher.init(Cipher.ENCRYPT_MODE, ky);
        return DESedecipher.doFinal(needData);
    }

  

根據定義,3DES密鑰是由3個密鑰單位構成的:K1+K2+K3;結合到具體的加解密,即:EnK3(DeK2(EnK1(明文)));而我們在分發密鑰時,有可能只分發其中的一部分,即K1,K1+K2,缺失的部分,需要自行補齊,在PHP中,缺失部分可能會被填充0x00,所以,我們在分發3DES密鑰時應該主動補齊缺失的部分,以防止疏漏。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM