2

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);
    }
}
4
  • 1
    Have you tried Base64? A string with a character-encoding is usually not a valid container for binary data. Commented Jun 19, 2017 at 19:56
  • 1
    How are you putting the encrypted string into the database and getting it back or checking it, and what data type is it being stored as? An example of a string/value that shows the problem might be useful too. Also you can use the dump() function to see exactly what is really stored. Maybe it's just a display issue in your client. Commented Jun 19, 2017 at 19:58
  • Database fields are Varchar2 fields. Cannot modify the datatypes since the DB is third-party. I'm basically using that program I posted above to copy and paste the values into the database. I'll be programatically retrieving it from the DB. Commented Jun 19, 2017 at 20:16
  • new String(cipherText) this is where you're losing bytes that cannot be recovered. Commented Jun 19, 2017 at 20:57

1 Answer 1

5

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;

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

  2. Store the encrypted binary data as binary (for example as a BLOB).

Sign up to request clarification or add additional context in comments.

1 Comment

I'll give option 1 a try. Cannot change the datatypes of the fields

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.