zoukankan      html  css  js  c++  java
  • Linux进行AES加密每次结果都不一致并且解密失败报错

    1. 现象

    windows操作系统下进行"123456"的AES加密

    encrypted message is below :
    QLNYZyjRnKF/zxAjzDt/lw==
    decrypted message is below :
    123456
     
    阿里云服务器,同样是"123456"的密码,每次加密结果都不一样,且不是QLNYZyjRnKF/zxAjzDt/lw==,解密是报错的
     
    2.解决方法
     
    经过检查之后,定位在生成KEY的方法上,如下:
    public static Key getSecretKey(String key) throws Exception {
        SecretKey secureKey = null;
        if (key == null) {
            key = "";
        }
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(new SecureRandom(key.getBytes()));
        secureKey = keyGenerator.generateKey();
        return secureKey;
    }

    修改到如下方式,问题解决:

    public static Key getKey(String strKey) {
        try {
            if (strKey == null) {
                strKey = "";
            }
            KeyGenerator _generator = KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(strKey.getBytes());
            _generator.init(128, secureRandom);
            return _generator.generateKey();
        } catch (Exception e) {
            throw new RuntimeException(" 初始化密钥出现异常 ");
        }
    }
    3.原因分析
     
    原因一:
    SecureRandom 实现完全隨操作系统本身的内部状态,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系统上则不同。
     
    原因二:
     
    1、加密完byte[] 后,需要将加密了的byte[] 转换成base64保存,如: 
    BASE64Encoder base64encoder = new BASE64Encoder(); 
    String encode=base64encoder.encode(bytes); 

    2、解密前,需要将加密后的字符串从base64转回来再解密,如: 
    BASE64Decoder base64decoder = new BASE64Decoder(); 
    byte[] encodeByte = base64decoder.decodeBuffer(str); 
     
    4. 附录完整代码
    package com.binfoo.wechat.util;
    
    import java.security.Key;
    import java.security.SecureRandom;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
    
    public class SecurityUtil {
        public static String DES = "AES"; // optional value AES/DES/DESede
    
        public static String CIPHER_ALGORITHM = "AES"; // optional value AES/DES/DESede
    
    
        public static Key getKey(String strKey) {
            try {
                if (strKey == null) {
                    strKey = "";
                }
                KeyGenerator _generator = KeyGenerator.getInstance("AES");
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                secureRandom.setSeed(strKey.getBytes());
                _generator.init(128, secureRandom);
                return _generator.generateKey();
            } catch (Exception e) {
                throw new RuntimeException(" 初始化密钥出现异常 ");
            }
        }
    
        public static String encrypt(String data, String key) throws Exception {
            SecureRandom sr = new SecureRandom();
            Key secureKey = getKey(key);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secureKey, sr);
            byte[] bt = cipher.doFinal(data.getBytes());
            String strS = new BASE64Encoder().encode(bt);
            return strS;
        }
    
    
        public static String decrypt(String message, String key) throws Exception {
            SecureRandom sr = new SecureRandom();
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            Key secureKey = getKey(key);
            cipher.init(Cipher.DECRYPT_MODE, secureKey, sr);
            byte[] res = new BASE64Decoder().decodeBuffer(message);
            res = cipher.doFinal(res);
            return new String(res);
        }
    
        public static void main(String[] args) throws Exception {
            String message = "123456";
            String key = "landLeaf";
            String encryptMsg = encrypt(message, key);
            System.out.println("encrypted message is below :");
            System.out.println(encryptMsg);
    
            String decryptedMsg = decrypt(encryptMsg, key);
            System.out.println("decrypted message is below :");
            System.out.println(decryptedMsg);
        }
    }
     
  • 相关阅读:
    重建二叉树
    字符串移位包含的问题
    整数的逆序存储
    容器的综合应用:文本查询程序(摘自C++ Primer)
    vsprintf 变参函数可以用
    常用项目依赖(前端)
    eslint一些常见配置
    Jscrpit中的原型对象
    html网页自适应手机屏幕大小
    A Bit of Fun
  • 原文地址:https://www.cnblogs.com/binfoo/p/5568010.html
Copyright © 2011-2022 走看看