#java #sql-server #encryption #cryptography #aes
Вопрос:
Я внедряю шифрование AES-256 в своем проекте, где я успешно могу зашифровать данные и сохранить их в базе данных.
Ниже приведен мой класс утилиты шифрования:
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public class AESUtils {
//Random Initial Vector generation
public static byte[] getRandomIV(int numBytes) {
byte[] nonce = new byte[numBytes];
new SecureRandom().nextBytes(nonce);
return nonce;
}
// AES secret key
public static SecretKey getAESKey(int keysize) throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(keysize, SecureRandom.getInstanceStrong());
return keyGen.generateKey();
}
// hex representation
public static String hex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("x", b));
}
return result.toString();
}
}
Ниже приведен мой основной класс, в котором я выполняю операции шифрования/дешифрования:
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
public class AESEncryptionDecryption {
private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
private static final int TAG_LENGTH_BIT = 128;
private static final int IV_LENGTH_BYTE = 16;
private static final int AES_KEY_BIT = 256;
private static final Charset UTF_8 = StandardCharsets.UTF_8;
// AES-GCM needs GCMParameterSpec
public static byte[] encrypt(byte[] pText, SecretKey secret, byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.ENCRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
byte[] encryptedText = cipher.doFinal(pText);
return encryptedText;
}
// prefix IV length IV bytes to cipher text
public static byte[] encryptWithPrefixIV(byte[] pText, SecretKey secret, byte[] iv) throws Exception {
byte[] cipherText = encrypt(pText, secret, iv);
byte[] cipherTextWithIv = ByteBuffer.allocate(iv.length cipherText.length)
.put(iv)
.put(cipherText)
.array();
return cipherTextWithIv;
}
public static String decrypt(byte[] cText, SecretKey secret, byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
cipher.init(Cipher.DECRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
byte[] plainText = cipher.doFinal(cText);
return new String(plainText, UTF_8);
}
public static String decryptWithPrefixIV(byte[] cText, SecretKey secret) throws Exception {
ByteBuffer bb = ByteBuffer.wrap(cText);
byte[] iv = new byte[IV_LENGTH_BYTE];
bb.get(iv);
//bb.get(iv, 0, iv.length);
byte[] cipherText = new byte[bb.remaining()];
bb.get(cipherText);
String plainText = decrypt(cipherText, secret, iv);
return plainText;
}
public static void main(String[] args) throws Exception {
String pText = "Strigs to be encrypted";
// encrypt and decrypt need the same key.
// get AES 256 bits (32 bytes) key
SecretKey secretKey = AESUtils.getAESKey(AES_KEY_BIT);
// encrypt and decrypt need the same IV.
byte[] iv = AESUtils.getRandomIV(IV_LENGTH_BYTE);
byte[] encryptedText = AESEncryptionDecryption.encryptWithPrefixIV(pText.getBytes(UTF_8), secretKey, iv);
System.out.println("Input (plain text :" pText);
System.out.println("Key (hex):" AESUtils.hex(secretKey.getEncoded()));
System.out.println("IV (hex) :" AESUtils.hex(iv));
System.out.println("Encrypted (hex) : " AESUtils.hex(encryptedText));
String decryptedText = AESEncryptionDecryption.decryptWithPrefixIV(encryptedText, secretKey);
System.out.println("Decrypted (plain text) : " decryptedText);
}
}
Приведенный выше код успешно способен шифровать/расшифровывать данные и сохранять их в базе данных с помощью пользовательского перехватчика hibernate. Но проблема в том, что я не могу расшифровать зашифрованные данные столбца в sql server всякий раз, когда мне нужно исходное значение для выполнения какой-либо операции на уровне хранимой процедуры.
Как вы могли видеть, я использую IV и секретный ключ для шифрования строки(как IV, так и ключ генерируются случайным образом). в первых 16 блоках зашифрованного текста хранятся значения IV, поэтому при расшифровке я передаю только зашифрованные данные и секретный ключ, поскольку я могу легко получить значения IV из зашифрованного текста(вы можете видеть в коде). Может ли кто-нибудь помочь мне здесь, как выполнить операцию шифрования и дешифрования AES-256 в sql server, или есть какой-либо лучший подход для этого. Спасибо
Комментарии:
1. Здесь возможны варианты всегда зашифрованного или зашифрованного / дешифрованного ключа. Я не знаю, «догнали» ли драйверы jdts (согласно комментарию Аарона в связанной теме). Этот вопрос может лучше подойти для dba.stackexchange.