AES encryption of the operating system differences

package com.shinedata.util.rsa;

import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

/**
 * @ClassName AESUtils 对称加密(同一个秘钥加/解密)
 * @Author yupanpan
 * @Date 2019/10/31 14:54
 */
public class AESUtils {

    private static final String ecnodeRules = "E91B337B0A329193BBD70A25010A45F5D9946F617C5067B212BFCBA2DF2E340E";

    /**
     * 加密
     * 1.构造密钥生成器
     * 2.根据ecnodeRules规则初始化密钥生成器
     * 3.产生密钥
     * 4.创建和初始化密码器
     * 5.内容加密
     * 6.返回字符串
     */
    public static String AESEncode(String ecnodeRules, String content) {
        try {
            ecnodeRules=createSecretkey(ecnodeRules);
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            //keygen.init(128, new SecureRandom(ecnodeRules.getBytes()));  windows系统生成密文一致,linux生成不一致
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");//跟随操作系统原则
            secureRandom.setSeed(ecnodeRules.getBytes());
            keygen.init(128, secureRandom);
            //3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, "AES");
            //6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byte_encode = content.getBytes("utf-8");
            //9.根据密码器的初始化方式--加密:将数据加密
            byte[] byte_AES = cipher.doFinal(byte_encode);
            String AES_encode = new String(new BASE64Encoder().encode(byte_AES));
            //11.将字符串返回
            return AES_encode;
        } catch (Exception e) {
            e.printStackTrace();
        }
        //如果有错就返加nulll
        return null;
    }

    /**
     * 解密
     * 解密过程:
     * 1.同加密1-4步
     * 2.将加密后的字符串反纺成byte[]数组
     * 3.将加密内容解密
     */
    public static String AESDncode(String ecnodeRules, String content) {
        try {
            ecnodeRules=createSecretkey(ecnodeRules);
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            //keygen.init(128, new SecureRandom(ecnodeRules.getBytes()));
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");//跟随操作系统原则
            secureRandom.setSeed(ecnodeRules.getBytes());
            keygen.init(128, secureRandom);
            //3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, "AES");
            //6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.DECRYPT_MODE, key);
            //8.将加密并编码后的内容解码成字节数组
            byte[] byte_content = new BASE64Decoder().decodeBuffer(content);
            /*
             * 解密
             */
            byte[] byte_decode = cipher.doFinal(byte_content);
            String AES_decode = new String(byte_decode, "utf-8");
            return AES_decode;
        } catch (Exception e) {
            e.printStackTrace();
        }
        //如果有错就返加nulll
        return null;
    }

    private static String createSecretkey(String ecnodeRules) {
        if(StringUtils.isBlank(ecnodeRules)){
            ecnodeRules=AESUtils.ecnodeRules;
        }
        return ecnodeRules;
    }

    /**
     * 生成秘钥
     * @author yupanpan
     * @date 2019/10/31 15:34
     * @param length
     * @return byte[]
     */
    public static byte[] generateDesKey(Integer length) throws Exception {
        //如果需要生成秘钥,最少128位
        if(length==null){
            length=256;
        }
        KeyGenerator kgen = null;
        kgen = KeyGenerator.getInstance("AES");
        kgen.init(length);
        //生成密钥
        SecretKey skey = kgen.generateKey();
        //返回密钥的二进制编码
        return skey.getEncoded();
    }
/**
    public static void main(String[] args) throws Exception {
//        CLVB+eVQX8HArPi0F45Ukw==
//        CLVB+eVQX8HArPi0F45Ukw==
//        CLVB+eVQX8HArPi0F45Ukw==
        System.out.println(AESEncode(null, "992"));
        System.out.println(AESDncode(null, "CLVB+eVQX8HArPi0F45Ukw=="));

    }
 */

}

Note that the operating system has some differences

keygen.init(128, new SecureRandom(ecnodeRules.getBytes()));

Above the normal line of code in the windows, each generated ciphertext decryption are the same, and is not faulty, but if the linux online environment will appear abnormal, the ciphertext generated each is different, and the decrypted when there are possible error. SecureRandom fully with the internal state Caozuojitong itself, unless the caller after a call getInstance turn invokes a method setSeed; this implementation is generated every time the windows on the same key, but is different in solaris linux system or part.

SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");//跟随操作系统原则
            secureRandom.setSeed(ecnodeRules.getBytes());
            keygen.init(128, secureRandom);

The above three lines of code that follow the current system environment generation, each generation is the same, everything is normal, the problem is solved!

supplement:

1, [] End encrypted byte, necessary encrypted byte [] is converted into base64 stored, such as: 
Base64Encoder new new Base64Encoder Base64Encoder = (); 
String = base64encoder.encode encode (bytes); 

2, prior to decryption, the encrypted needed after base64 string back again transferred from the decryption, such as: 
Base64Decoder Base64Decoder new new Base64Decoder = (); 
byte [] = encodeByte base64decoder.decodeBuffer (STR); 

Published 288 original articles · won praise 88 · views 430 000 +

Guess you like

Origin blog.csdn.net/ypp91zr/article/details/102920075