1

I have to store in a DB table the connection details to another databases, I must encrypt the passwords to those DBs and one must be able to "manually" insert data into that table via SQL scripts...

I need to encrypt and decrypt it because my app must be able to use those data and connect to other databases, so MD5 and similar are not useful..

I thought of Blowfish, AES, etc... but if I store the password as VARCHAR in the DB the decrypt part doesn't work... so I stored it as BYTE, but if I do so no one can write a script to pre-load data on the table..

Maybe I'm missing something here...

Here's the code I used when the registry in the table was defined as VARCHAR:

package main;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;


public class Prueba {

    private static final String keyValue = "fd<[;.7e/OC0W!d|";
    private static final String ALG = "Blowfish";

    public static void main(String[] args) {
        String text = "some random text";

        try {
            SecretKeySpec key = new SecretKeySpec(keyValue.getBytes(), ALG);
            Cipher cipher = Cipher.getInstance(ALG);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encryptedBytes = cipher.doFinal(text.getBytes());
            String encrypted = new String(encryptedBytes);

            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] recoveredBytes = cipher.doFinal(encrypted.getBytes());
            String recovered = new String(recoveredBytes);

        } catch (NoSuchAlgorithmException nsa) {
            nsa.printStackTrace();
        } catch (NoSuchPaddingException nspe) {
            nspe.printStackTrace();
        } catch (InvalidKeyException ike) {
            ike.printStackTrace();
        } catch (BadPaddingException bpe) {
            bpe.printStackTrace();
        } catch (IllegalBlockSizeException ibse) {
            ibse.printStackTrace();
        } 
    }


}

And I get the exception:

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
    at com.sun.crypto.provider.SunJCE_h.b(DashoA12275)
    at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(DashoA12275)
    at javax.crypto.Cipher.doFinal(DashoA12275)
    at main.Prueba.main(Prueba.java:30)

If instead of:

byte[] recoveredBytes = cipher.doFinal(encrypted.getBytes());

I do

byte[] recoveredBytes = cipher.doFinal(encryptedBytes);

I get no exception, but then I must store the password as byte[] soooo no script posible...

Any ideas?

4
  • 2
    Why not just store the hex (or Base64) encoded string of the bytes instead of the bytes themselves? There will be a space penalty but then you can preload from scripts, etc. Also it might be more portable between databases. Commented Oct 9, 2012 at 15:24
  • I believe you may find this useful stackoverflow.com/a/4183913/579580 Commented Oct 9, 2012 at 15:27
  • 1
    Passwors for safety reason should always be stored as byte[] Commented Oct 9, 2012 at 15:31
  • That's quite a good idea maerics... I'll ask the project manager about it... Thanx :) Commented Oct 9, 2012 at 15:32

3 Answers 3

2

It seems like when you store the key as bytes something somewhere is interpreting it incorrectly. It could be a character encoding problem.

If you want to store the key as text you might want to base64 encode it first. You can then base64 decode the text back to the key.

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

1 Comment

This is doomed before it even gets to the DB, a problem that stems from encrypted.getBytes() being different from encryptedBytes (which is itself a problem caused by converting a byte array into a string)
0
String encrypted = new BASE64Encoder ().encodeBuffer ( encryptedBytes );            
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] recoveredBytes = cipher.doFinal( new BASE64Decoder ().decodeBuffer (  encrypted ) );

Comments

0

In the end, as maerics suggested, I solved it this way:

import org.apache.commons.net.util.Base64;

public class MyCrypto {

    /**
     * Codifica un texto usando Base64.
     * @param texto <code>String</code> texto a codificar.
     * @return <code>String</code> texto codificado.
     */
    public static String encrypt(String texto) {
        return new String(Base64.encodeBase64(texto.getBytes()));
    }

    /**
     * Decodifica un texto usando Base64.
     * @param texto <code>String</code> texto a decodificar.
     * @return <code>String</code> texto decodificado.
     */
    public static String decrypt(String texto) {
        return new String(Base64.decodeBase64(texto.getBytes()));
    }
}

3 Comments

This is not right. Base64 encoding is not the same as encryption
Base64 is deprecated in the newest versions
I couldnt fully understand your usecase but like @Minh Kieu said, encoding is not the same as encryption and definately not secure, anyone can decode base64 string.

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.