zoukankan      html  css  js  c++  java
  • java加密之AES/CBC/PKCS5Padding

    1.加密

    public static String Encrypt(String sSrc, String sKey) throws Exception {  
            if (sKey == null) {  
                System.out.print("Key为空null");  
                return null;  
            }  
            // 判断Key是否为16位  
            if (sKey.length() != 16) {  
                System.out.print("Key长度不是16位");  
                return null;  
            }  
            byte[] raw = sKey.getBytes("utf-8");  
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");  
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//"算法/模式/补码方式"  
            IvParameterSpec iv = new IvParameterSpec(cKey.getBytes());//使用CBC模式,需要一个向量iv,可增加加密算法的强度  
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);  
            byte[] encrypted = cipher.doFinal(sSrc.getBytes());  
            return new Base64().encode(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。  
        }  
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2.解密

    // 解密  
        public static String Decrypt(String sSrc, String sKey) throws Exception {  
            try {  
                // 判断Key是否正确  
                if (sKey == null) {  
                    System.out.print("Key为空null");  
                    return null;  
                }  
                // 判断Key是否为16位  
                if (sKey.length() != 16) {  
                    System.out.print("Key长度不是16位");  
                    return null;  
                }  
                byte[] raw = sKey.getBytes("utf-8");  
                SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");  
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");  
                IvParameterSpec iv = new IvParameterSpec(cKey.getBytes());  
                cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);  
                byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密  
                try {  
                    byte[] original = cipher.doFinal(encrypted1);  
                    String originalString = new String(original);  
                    return originalString;  
                } catch (Exception e) {  
                    System.out.println(e.toString());  
                    return null;  
                }  
            } catch (Exception ex) {  
                System.out.println(ex.toString());  
                return null;  
            }  
        }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    3.测试

     public static void main(String[] args) throws Exception {  
            /* 
             * 加密用的Key 可以用26个字母和数字组成,最好不要用保留字符,虽然不会错,至于怎么裁决,个人看情况而定 
             * 此处使用AES-128-CBC加密模式,key需要为16位。 
             */  
    
            // 需要加密的字串  
            String cSrc = "{data:[{'name':'你好','age':20},{'name':'zd','age':18}]}";  
            System.out.println(cSrc);  
            // 加密  
            long lStart = System.currentTimeMillis();  
            String enString = AES.Encrypt(cSrc, cKey);  
            System.out.println("加密后的字串是:" + enString);  
    
            long lUseTime = System.currentTimeMillis() - lStart;  
            System.out.println("加密耗时:" + lUseTime + "毫秒");  
            // 解密  
            lStart = System.currentTimeMillis();  
            String DeString = AES.Decrypt(enString, cKey);  
            System.out.println("解密后的字串是:" + DeString);  
            lUseTime = System.currentTimeMillis() - lStart;  
            System.out.println("解密耗时:" + lUseTime + "毫秒");  
        } 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    4.结果

    {data:[{'name':'你好','age':20},{'name':'zd','age':18}]}
    加密后的字串是:NYVX44VBZP9890WYjeJC7lOnpXCR/Z/B+kbc+nu432KrcegOS08U+lA6clLoP92bHblcBcYf1dced25iNLTTIA==
    加密耗时:413毫秒
    解密后的字串是:{data:[{'name':'你好','age':20},{'name':'zd','age':18}]}
    解密耗时:0毫秒
    • 1
    • 2
    • 3
    • 4
    • 5

    本事例中偏移量直接使用密钥,但是为了安全起见,最好不要这么做


    偶尔会报错 抛出异常,

    javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
     
    原因  加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;要避免这种情况,我们需要做一些修订,可以考虑将二进制数据转换成十六进制表示
    解决方案 


    二进制转换成16进制

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**将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;
    }

      

    16进制转换为二进制

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /**将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;
    }

      

     测试结果,问题解决

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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));



  • 相关阅读:
    Working with Deployment Configurations in CodeDeploy
    ECS 容器实例生命周期
    设置 API Gateway 金丝雀版本部署
    Elastic Beanstalk 滚动环境配置更新
    Kinesis Data Firehose 中的数据保护
    为 API Gateway REST API 资源启用 CORS
    高级 AWS Elastic Beanstalk 环境配置
    Amazon SWF Actors
    AWS CloudFormation 模板结构
    字符编码
  • 原文地址:https://www.cnblogs.com/llhl/p/9648623.html
Copyright © 2011-2022 走看看