暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

生活不止眼前的代码 2020-03-18
386

网页浏览地址

https://blog.csdn.net/yingziisme/article/details/104912034


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

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

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则发现每次加密之后获取的加密字符串都不同,也无法解密

重写获取密钥部分的代码


/**
* 获取密钥
*
*
@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 系统上则不同。


文章转载自生活不止眼前的代码,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论