Нужна помощь для расшифровки значений столбцов в SQL server и сохранения зашифрованных значений в таблице sql server?

#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.