Java AES加密解密需要更长的时间
我在Spring boot项目中使用下面的代码进行加密和解密,在我想要加密和解密的属性上使用Converter注释Java AES加密解密需要更长的时间,java,encryption,cryptography,Java,Encryption,Cryptography,我在Spring boot项目中使用下面的代码进行加密和解密,在我想要加密和解密的属性上使用Converter注释 import org.apache.commons.codec.binary.Base64; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; im
import org.apache.commons.codec.binary.Base64;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
@Converter
public class CryptoConverter implements AttributeConverter<String, String> {
@Override
public String convertToDatabaseColumn(String attribute) {
if(attribute == null){
return null;
}
try {
byte[] ivBytes;
//String password="Hello";
String password = EncryptionUtil.key.get();
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
byte[] saltBytes = bytes;
// Derive the key
SecretKeyFactory factory = null;
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(),saltBytes,65556,256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypting the word
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(attribute.getBytes("UTF-8"));
//prepend salt and vi
byte[] buffer = new byte[saltBytes.length + ivBytes.length + encryptedTextBytes.length];
System.arraycopy(saltBytes, 0, buffer, 0, saltBytes.length);
System.arraycopy(ivBytes, 0, buffer, saltBytes.length, ivBytes.length);
System.arraycopy(encryptedTextBytes, 0, buffer, saltBytes.length + ivBytes.length, encryptedTextBytes.length);
return new Base64().encodeToString(buffer);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
@Override
public String convertToEntityAttribute(String dbData) {
if(dbData == null){
return null;
}
try {
String password = EncryptionUtil.key.get();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//strip off the salt and iv
ByteBuffer buffer = ByteBuffer.wrap(new Base64().decode(dbData));
byte[] saltBytes = new byte[20];
buffer.get(saltBytes, 0, saltBytes.length);
byte[] ivBytes1 = new byte[cipher.getBlockSize()];
buffer.get(ivBytes1, 0, ivBytes1.length);
byte[] encryptedTextBytes = new byte[buffer.capacity() - saltBytes.length - ivBytes1.length];
buffer.get(encryptedTextBytes);
// Deriving the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, 65556, 256);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes1));
byte[] decryptedTextBytes = null;
decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
return new String(decryptedTextBytes);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
}
问题是这段代码需要很多时间来加密和解密
这样,我的性能受到了严重的影响。如果您想要比简单地使用实际随机生成的密钥而不是密码更快地进行加密。如果愿意,可以将其存储在密钥库实例中,并使用密码进行保护 您还可以简单地将PBKDF2密钥派生移出加密方法本身,并将生成的SecretKey实例存储在字段中,前提是且仅当密码在调用之间没有更改。这样,只需导出一次密钥
PBKDF2当前每次要加密/解密任何内容时都使用65556次迭代。PBKDF2由单个散列组成——在本例中为SHA-1——一次占用64字节。因此,即使在开始加密之前,出于某种原因,您至少已经将65556或64Ki+20散列了64个字节。这是在开始加密之前要进行的4mib散列。与此相比,您甚至不会注意到AES加密。您分析过代码以查看它一直在哪里使用吗?代码可能是从某个地方复制粘贴的,您不知道它是做什么或为什么的?你说这需要更长的时间,但比什么要长?您确实有一个PBE方案,它使用迭代来减缓攻击者的工作,但它也会使您的代码更难工作。这是故意的。我发现你在处理异常时遇到了一些问题,试着阅读;如果对你有用,别忘了投票。加密原语的一般使用是可以的,不过如果您想获得更高的安全性,可能需要使用AES/GCM/NoPadding而不是CBC模式。