Trying to use the javax.crypto library to encrypt a string and store it in the database (Oracle). I will need to decrypt this string later, so I need a two-way algorithm.
The problem is the database doesn't seem to accept some of the encrypted characters the method creates. We are in between migrating our databases to a new server. The old databases use US7ASCII charset while the new databases use AL32UTF8. When I go to put the encrypted string in the database, the database just converts them to question marks (?) in the US7ASCII databases. It appears to store just fine in the AL32UTF8 database.
So, I have to make this cross-compatible. I've tried sending it different StandardCharsets values when using the getBytes() method, but it doesn't seem to help. Maybe I'm missing something. Any way I can get the desired result doing it differently?
Here is my code to generate the cipher text. Modded from another post on StackOverflow
import java.io.PrintStream;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public class test
{
public static void main(String[] args)
throws Exception
{
//byte[] encryptionKey = "Es6XYPkgCV75J95Y".getBytes(StandardCharsets.UTF_8);
byte[] encryptionKey = "Es6XYPkgCV75J95Y".getBytes(StandardCharsets.ISO_8859_1);
//byte[] plainText = args[0].getBytes(StandardCharsets.UTF_8);
byte[] plainText = args[0].getBytes(StandardCharsets.ISO_8859_1);
MyCrypto aes = new MyCrypto(encryptionKey);
byte[] cipherText = aes.encrypt(plainText);
byte[] decryptedCipherText = aes.decrypt(cipherText);
System.out.println(new String(plainText));
System.out.println(new String(cipherText));
System.out.println(new String(decryptedCipherText));
}
}
class MyCrypto
{
private byte[] key;
private static final String ALGORITHM = "AES";
public MyCrypto(byte[] key)
{
this.key = key;
}
/**
* Encrypts the given plain text
*
* @param plainText The plain text to encrypt
*/
public byte[] encrypt(byte[] plainText) throws Exception
{
SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(plainText);
}
/**
* Decrypts the given byte array
*
* @param cipherText The data to decrypt
*/
public byte[] decrypt(byte[] cipherText) throws Exception
{
SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(cipherText);
}
}
解决方案
When you encrypt data you are turning it into binary data. It sounds like you are trying to store it as character data, which is a bad idea.
You really have two options;
Encode the encrypted binary data using a binary-to-text scheme such as Base64. You can then store the encoded data as character data. When you want to retrieve it you read the character data and decode (text to binary) before decrypting.
Store the encrypted binary data as binary (for example as a BLOB).