zoukankan      html  css  js  c++  java
  • ASE加、解密

    AES已经变成目前对称加密中最流行算法之一;AES可以使用128、192、和256位密钥,并且用128位分组加密和解密数据。

        /**
         * 加密
         *
         * @param content 需要加密的内容
         * @param password  加密密码
         * @return
         */
        public static byte[] encrypt(String content, String password) {
            try {
                KeyGenerator kgen = KeyGenerator.getInstance("AES");    //创建AES的key生产者
                kgen.init(128, new SecureRandom(password.getBytes()));  //利用用户密码作为随机码初始化 
            //使其具有确定的128个字节的密钥大小,SecureRandom是生成安全随机数序列,
            //password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行
                SecretKey secretKey = kgen.generateKey();    //根据用户密码生成密钥
                byte[] enCodeFormat = secretKey.getEncoded();  //返回基本编码格式的密钥,如果此密钥不支持编码,返回null
                SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");  //根据给定的字节数组构造一个为AES专用密钥
                Cipher cipher = Cipher.getInstance("AES");    // 创建密码器
                byte[] byteContent = content.getBytes("utf-8");
                cipher.init(Cipher.ENCRYPT_MODE, key);      // 初始化为加密模式
                byte[] result = cipher.doFinal(byteContent);
                return result; // 加密
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            }
            return null;
        }
    

      

      

      

    注意:解密的时候要传入byte数组

        /**解密
         * @param content  待解密内容
         * @param password 解密密钥
         * @return
         */
        public static byte[] decrypt(byte[] content, String password) {
            try {
                KeyGenerator kgen = KeyGenerator.getInstance("AES");
                kgen.init(128, new SecureRandom(password.getBytes()));
                SecretKey secretKey = kgen.generateKey();
                byte[] enCodeFormat = secretKey.getEncoded();
                SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
                Cipher cipher = Cipher.getInstance("AES");// 创建密码器
                cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
                byte[] result = cipher.doFinal(content);
                return result; 
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            }
            return null;
        }
    

      

    String content = "test";
    String password = "12345678";
    //加密
    System.out.println("加密前:" + content);
    byte[] encryptResult = encrypt(content, password);
    //解密
    byte[] decryptResult = decrypt(encryptResult,password);
    System.out.println("解密后:" + new String(decryptResult));
    

      

    输出结果如下:
    加密前:test
    解密后:test
     

    容易出错的地方

    但是如果我们将测试代码修改一下,如下:
     String content = "test";
    String password = "12345678";
    //加密
    System.out.println("加密前:" + content);
    byte[] encryptResult = encrypt(content, password);
    try {
        String encryptResultStr = new String(encryptResult,"utf-8");
        //解密
        byte[] decryptResult = decrypt(encryptResultStr.getBytes("utf-8"),password);
         System.out.println("解密后:" + new String(decryptResult));
    } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
    }
    则,系统会报出如下异常:
    javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
            at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
            at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
            at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
            at javax.crypto.Cipher.doFinal(DashoA13*..)
     
    这主要是因为加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;要避免这种情况,我们需要做一些修订,可以考虑将二进制数据转换成十六进制表示,主要有如下两个方
     
    将二进制转换成16进制
    **将二进制转换成16进制 
     * @param buf 
     * @return 
     */  
    public static String parseByte2HexStr(byte buf[]) {  
            StringBuffer sb = new StringBuffer();  
            for (int i = 0; i < buf.length; i++) {  
                    String hex = Integer.toHexString(buf[i] & 0xFF);  
                    if (hex.length() == 1) {  
                            hex = '0' + hex;  
                    }  
                    sb.append(hex.toUpperCase());  
            }  
            return sb.toString();  
    }  
    

      

    将16进制转换为二进制

    /**将16进制转换为二进制 
     * @param hexStr 
     * @return 
     */  
    public static byte[] parseHexStr2Byte(String hexStr) {  
            if (hexStr.length() < 1)  
                    return null;  
            byte[] result = new byte[hexStr.length()/2];  
            for (int i = 0;i< hexStr.length()/2; i++) {  
                    int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);  
                    int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);  
                    result[i] = (byte) (high * 16 + low);  
            }  
            return result;  
    }  
    

      

    String content = "test";  
    String password = "12345678";  
    //加密  
    System.out.println("加密前:" + content);  
    byte[] encryptResult = encrypt(content, password);  
    String encryptResultStr = parseByte2HexStr(encryptResult);  
    System.out.println("加密后:" + encryptResultStr);  
    //解密  
    byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);  
    byte[] decryptResult = decrypt(decryptFrom,password);  
    System.out.println("解密后:" + new String(decryptResult));  
    

      

    测试结果如下:
    加密前:test
    加密后:73C58BAFE578C59366D8C995CD0B9D6D
    解密后:test

    也可以使用BASE64进行包装处理。

    加密bytes[] ----> passwordStr: new String(new BASE64Encoder().encode(doFinal))
    

     

    解密String --->  new BASE64Decoder().decodeBuffer(passwordStr)
    

      

        public static String generatePasswordAES2(String password, String passwordKey) {
            try {
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                keyGenerator.init(128, new SecureRandom(passwordKey.getBytes("UTF-8")));
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] encoded = secretKey.getEncoded();
                SecretKey key = new SecretKeySpec(encoded, "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                System.out.println("密钥的长度为:" + key.getEncoded().length);
                cipher.init(Cipher.ENCRYPT_MODE, key);
                byte[] userPasswordBytes = password.getBytes("UTF-8");
                byte[] doFinal = cipher.doFinal(userPasswordBytes);
                String passwordBase64 = new String(new BASE64Encoder().encode(doFinal));
                return passwordBase64;
            } catch (Exception e) {
                throw new BadRequestException("密码加密错误。");
            }
        }
    

      

        public static String decryptPassword(String password, String token) {
            try {
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                keyGenerator.init(128, new SecureRandom(token.getBytes("UTF-8")));
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] encoded = secretKey.getEncoded();
                SecretKey key = new SecretKeySpec(encoded, "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, key);
                byte[] passwordBytes = new BASE64Decoder().decodeBuffer(password);
                //解密
                byte[] passwordDoFinal = cipher.doFinal(passwordBytes);
                String decrypt = new String(passwordDoFinal, "UTF-8");
                return decrypt;
            } catch (Exception e) {
                throw new BadRequestException("密码解密错误:" + e.getMessage());
            }
        }
    

      

    AES-CBC-PKCS5

    <script>
        function getAesString(data,key,iv){//加密
    
            var key  = CryptoJS.enc.Utf8.parse(key);
            //alert(key);
            var iv   = CryptoJS.enc.Utf8.parse(iv);
            var encrypted =CryptoJS.AES.encrypt(data,key,
                    {
                            iv:iv,
                    mode:CryptoJS.mode.CBC,
                    padding:CryptoJS.pad.Pkcs7
            });
            return encrypted.toString();    //返回的是base64格式的密文
        }
        function getDAesString(encrypted,key,iv){//解密
            var key  = CryptoJS.enc.Utf8.parse(key);
            var iv   = CryptoJS.enc.Utf8.parse(iv);
            var decrypted =CryptoJS.AES.decrypt(encrypted,key,
                    {
                            iv:iv,
                    mode:CryptoJS.mode.CBC,
                    padding:CryptoJS.pad.Pkcs7
            });
            returndecrypted.toString(CryptoJS.enc.Utf8);      //
        }
        function getAES(){ //加密
            var data =document.getElementById("data-ipt").value;//明文
            var key  = 'abcdefgabcdefg12';  //密钥
            var iv   = 'abcdefgabcdefg12';
            var encrypted =getAesString(data,key,iv); //密文
            var encrypted1 =CryptoJS.enc.Utf8.parse(encrypted);
            document.getElementById("encrypted").innerHTML = encrypted;
        }
    
        function getDAes(){//解密
            var encrypted =document.getElementById("encrypted").innerHTML; //密文
            var key  = 'abcdefgabcdefg12';
            var iv   = 'abcdefgabcdefg12';
            var decryptedStr =getDAesString(encrypted,key,iv);
            alert(decryptedStr);
            document.getElementById("decrypted").innerHTML = decryptedStr;
        }
        </script>
    

      

     public static void main(String[] args)throws UnsupportedEncodingException {   
            Stringcontent="12345678";   
            Stringkey="abcdefgabcdefg12";   
            Stringiv="abcdefgabcdefg12";   
            //加密  
            byte[ ]encrypted=AES_CBC_Encrypt(content.getBytes(), key.getBytes(), iv.getBytes());  
            //解密  
            byte[ ]decrypted=AES_CBC_Decrypt(encrypted, key.getBytes(), iv.getBytes());   
             
            System.out.println("解密后:"+byteToHexString(decrypted));  
           System.out.println(byteToString(decrypted));  
        }   
        public static String byteToString(byte[ ]byte1){  
             returnnew String(byte1);  
        }  
        public static byte[] AES_CBC_Encrypt(byte[]content, byte[] keyBytes, byte[] iv){   
               
            try{   
                SecretKeySpec key = newSecretKeySpec(keyBytes, "AES");  
                Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding");   
                cipher.init(Cipher.ENCRYPT_MODE,key, new IvParameterSpec(iv));   
                byte[]result=cipher.doFinal(content);  
                return result;  
            }catch (Exception e) {   
               System.out.println("exception:"+e.toString());   
            }    
            return null;   
        }   
           
        public static byte[] AES_CBC_Decrypt(byte[]content, byte[] keyBytes, byte[] iv){   
               
            try{        
                SecretKeySpec key = newSecretKeySpec(keyBytes, "AES");  
                Ciphercipher=Cipher.getInstance("AES/CBC/PKCS5Padding");   
                cipher.init(Cipher.DECRYPT_MODE,key, new IvParameterSpec(iv));   
                byte[]result=cipher.doFinal(content);   
                return result;   
            }catch (Exception e) {   
                // TODO Auto-generated catchblock   
                System.out.println("exception:"+e.toString());   
            }    
            return null;   
        }   
    /** 
         * 字符串装换成base64 
         *  
         * @param key 
         * @return 
         * @throws Exception 
         */   
        public static byte[] decryptBASE64(Stringkey) throws Exception {   
             returnBase64.decodeBase64(key.getBytes());  
        }   
           
        /** 
         *二进制装换成base64 
         *  
         * @param key 
         * @return 
         * @throws Exception 
         */   
        public static String encryptBASE64(byte[]key) throws Exception {   
             returnnew String(Base64.encodeBase64(key));  
        }  
    

      

  • 相关阅读:
    我的大学,我的梦想
    c++读取lua配置基础类
    无奖调查,你希望我写哪些题材的文章
    无奖调查,你希望我写哪些题材的文章
    lua不同模块调用
    cmake配置c++可调用的文件路径参数
    Java实现 LeetCode 335 路径交叉
    Java实现 LeetCode 335 路径交叉
    Java实现 LeetCode 335 路径交叉
    Java实现 LeetCode 334 递增的三元子序列
  • 原文地址:https://www.cnblogs.com/skyLogin/p/6767640.html
Copyright © 2011-2022 走看看