前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记AES加密在linux系统每次都不一样的问题

记AES加密在linux系统每次都不一样的问题

作者头像
yingzi_code
发布2020-03-18 20:05:19
1.2K0
发布2020-03-18 20:05:19
举报

记AES加密在linux系统每次都不一样的问题

在项目中通常会用到AES的加密方法,具体代码如下

代码语言:javascript
复制
package com.mt.demo.client.utils;

import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

/**
 * AESUtils
 *
 * @author mt.luo
 * @description: AES加密
 */
@Slf4j
@Component
public class AESUtils {
    private final String aesSeed = "ada46ab5da824b96a18409c49dc91dc2";
    private final String algorithm = "SHA-256";
    private final String AES = "AES";
    private final String cipher = "AES/ECB/PKCS7Padding";
    private final String provider = "BC";

    /**
     * convert to byte[]
     *
     * @param key key
     * @return byte[]
     * @throws NoSuchAlgorithmException
     */
    private byte[] toHash256(String key) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance(this.algorithm);
        messageDigest.update(key.getBytes());
        return messageDigest.digest();
    }

    /**
     * parseHexStrToByte
     *
     * @param hexStr hexStr
     * @return byte
     */
    private byte[] parseHexStrToByte(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;
    }

    /**
     * parseByteToHexStr
     *
     * @param bytes bytes
     * @return String
     */
    private String parseByteToHexStr(byte[] bytes) {
        StringBuilder stringBuilder = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            stringBuilder.append(hex.toUpperCase());
        }
        return stringBuilder.toString();
    }

    /**
     * 获取密钥
     *
     * @param seed seed
     * @return SecretKeySpec
     * @throws NoSuchAlgorithmException NoSuchAlgorithmException
     */
    private SecretKeySpec getSecretKeySpec(String seed) throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(this.AES);
        SecureRandom secureRandom = new SecureRandom(this.toHash256(seed));
        keyGenerator.init(256, secureRandom);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] encode = secretKey.getEncoded();
        SecretKeySpec secretKeySpec = new SecretKeySpec(encode, this.AES);
        Security.addProvider(new BouncyCastleProvider());
        return secretKeySpec;
    }

    /**
     * 加密
     *
     * @param data data
     * @return String
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws NoSuchPaddingException
     * @throws UnsupportedEncodingException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     */
    public String encrypt(String data) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
            UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
        SecretKeySpec secretKeySpec = this.getSecretKeySpec(this.aesSeed);
        Cipher cipher = Cipher.getInstance(this.cipher, this.provider);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        return this.parseByteToHexStr(Base64.getEncoder().encode(cipher.doFinal(data.getBytes(StandardCharsets.UTF_8.name()))));
    }
}

然后这样使用在windows系统的时候没有问题,而将程序部署到Linux则发现每次加密之后获取的加密字符串都不同,也无法解密,重写获取密钥部分的代码

代码语言:javascript
复制
    /**
     * 获取密钥
     *
     * @param seed seed
     * @return SecretKeySpec
     * @throws NoSuchAlgorithmException NoSuchAlgorithmException
     */
    private SecretKeySpec getSecretKeySpec(String seed) throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(this.AES);
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        secureRandom.setSeed(this.toHash256(seed));
        keyGenerator.init(256, secureRandom);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] encode = secretKey.getEncoded();
        SecretKeySpec secretKeySpec = new SecretKeySpec(encode, this.AES);
        Security.addProvider(new BouncyCastleProvider());
        return secretKeySpec;
    }
主要原因是SecureRandom 实现完全隨操作系统本身的内部状态,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 linux 系统上则不同。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 主要原因是SecureRandom 实现完全隨操作系统本身的内部状态,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 linux 系统上则不同。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档