aspose file tools*
The moose likes Security and the fly likes encrypt data in database Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » Security
Bookmark "encrypt data in database" Watch "encrypt data in database" New topic
Author

encrypt data in database

Amin Raykou
Greenhorn

Joined: Apr 17, 2008
Posts: 10
Good evening,
I'm developping an application to encrypt data with tripleDES before getting inserted in oracle database.
Another application must consult the database, decrypt the data then show it in a jtable.
I'm a biginner in the security field, i found a source implementing triple DES encryption.
1-some byte from the encrypted data like the cote(') make some problem when executing the query, i'd like to change the type of the encryption bytes, i heard about UTF8 but i don't know how to use it.
2-when I decrypt the data from the resultset and put it in the jtable the first culumn is empty and I receive this error:
"javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher. "
It can't decrypt the first object of the resultset cause of the missing byte.
Here is the code:
The encryption class:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;


public class TripleDES {
public File f = new File("clef");

/** Read a TripleDES secret key from the specified file */
public SecretKey readKey(File f)
throws IOException, NoSuchAlgorithmException,
InvalidKeyException, InvalidKeySpecException
{
// Read the raw bytes from the keyfile
DataInputStream in = new DataInputStream(new FileInputStream(f));
byte[] rawkey = new byte[(int)f.length()];
in.readFully(rawkey);
in.close();

// Convert the raw bytes to a secret key like this
DESedeKeySpec keyspec = new DESedeKeySpec(rawkey);
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");
SecretKey key = keyfactory.generateSecret(keyspec);
return key;
}

public void encrypt(SecretKey key, InputStream in, OutputStream out)
throws NoSuchAlgorithmException, InvalidKeyException,
NoSuchPaddingException, IOException
{
// Create and initialize the encryption engine
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, key);
// Create a special output stream to do the work for us
CipherOutputStream cos = new CipherOutputStream(out, cipher);

// Read from the input and write to the encrypting output stream
byte[] buffer = new byte[2048];
int bytesRead;
while((bytesRead = in.read(buffer)) != -1) {
cos.write(buffer, 0, bytesRead);
}
cos.close();

// For extra security, don't leave any plaintext hanging around memory.
java.util.Arrays.fill(buffer, (byte) 0);
}

public void decrypt(SecretKey key, InputStream in, OutputStream out)
throws NoSuchAlgorithmException, InvalidKeyException, IOException,
IllegalBlockSizeException, NoSuchPaddingException,
BadPaddingException
{
// Create and initialize the decryption engine
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.DECRYPT_MODE, key);

// Read bytes, decrypt, and write them out.
byte[] buffer = new byte[2048];
int bytesRead;
while((bytesRead = in.read(buffer)) != -1) {
out.write(cipher.update(buffer, 0, bytesRead));
}

// Write out the final bunch of decrypted bytes
out.write(cipher.doFinal());
out.flush();
}
//manipulate a string and not streams when enrypting
public String crypterString(String s){

ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes());

try {
encrypt(readKey(f), in, out);
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return out.toString();
}
//manipulate a string and not streams when decrypting
public String decrypterString(String s){

ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(s.getBytes());
try {
decrypt(readKey(f), in, out);
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return out.toString();
}
}
I insert encrypt the data with the void crypterString() then i insert it in the database.
And here is the vector i use to fill in the jtable(the decryption application side)

public Vector donnee(ResultSet rs)
{int numRows=0;
int numColumns = 0;
TripleDES td = new TripleDES();
try {
td.readKey(td.f);
} catch (InvalidKeyException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvalidKeySpecException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Vector data = new Vector();
try{
numColumns=rs.getMetaData().getColumnCount();
while (rs.next())

{ Vector rowData = new Vector();
for (int i = 0; i < numColumns; i++)
rowData.addElement(td.decrypterString(rs.getObject(i+1).toString()));
data.addElement(rowData);
numRows++;
}

}

catch (java.sql.SQLException e)
{
JOptionPane.showMessageDialog(null,"Erreur de connexion � la base. Veuillez contacter votre administrateur syst�me","Connexion",JOptionPane.WARNING_MESSAGE);

}return data;
}

Thanks for your help.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

3DES is OK, but you are better off with AES, its faster and as secure.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

You should be careful, DES and other ciphers work on byte arrays, actually octet arrays, which are essentially unsigned bytes, But Java doesn't have such a thing as unsigned bytes.

You should start with the validation vectors and the test keys. AES has a nice suite. Make sure you code can create the proper cipher text from the test vectors, and can decipher the resulting cipher text back to the clear text.

Then you can try with your local strings, arguments and tests.
Amin Raykou
Greenhorn

Joined: Apr 17, 2008
Posts: 10
Thanks for your reply.
When I tested the code with a string (without databse), it work :it encrypt the string and then it decrypt the cipher text back.
But when I want to insert the string into the database and then retrieve it and decipher, I don't get the wanted result for the first column.The other columns are perfect(decrypted to the right data).So the key and vector test run correctly for all the columns but not for the first one.
I'll try to use AES.
Thanks for your help.
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

Originally posted by amin amin:
Thanks for your reply.
When I tested the code with a string (without databse), it work :it encrypt the string and then it decrypt the cipher text back.
But when I want to insert the string into the database and then retrieve it and decipher,


The result of a cipher is binary. It is not a string. You have to convert it to something that is a string, hex, mime, radix64, or something.
Or you can store it as a blob if your DBMS handles blobs.
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282
Originally posted by amin amin:
Good evening,


Good morning.


Why do you throw away the desKeySpec?


Why not Cipher.getInstance("Rijndael");// Advanced Encryption Standard
As discussed in NIST website?


Probably, I have not read Cipher.....Stream yet. I just write raw bytes or Base64 - "uN9f9Xerbmw8+qGq44yqzw==" doing getBytes() on the string here so that I do not get editors replacing nulls in the protected information. If you have a database with operational controls in place and proven reliability then there should be some way to store strings on the database using their methods and tools.


Do it yourself, I just got through two days of struggling with what I thought was a library that was working. Discovered that super(byte[] rawKey); does a copy operation. Fortunately I have done enought computer work to recognize a default value was being placed in a buffer without telling me or throwing an exception. If you use the libs, be sure to read them.


Wrong, do as Pat says. For the reasons Pat says.


Did you read BAOS? Without looking, what is the default buffer size for new ByteArrayOutputStream();//?


Who works where the machine is located and how much computer knowledge do they have? Write to a log file, put up a short and easily digestable notice to call sys admin.


Why not pass in a reference to avoid buffers being created that do not show in code?


Manipulate bytes, for reasons Pat gives.



Some re-wording here to give you things to think about.

And here is the vector i use to fill in the jtable(the decryption application side)

Who is donnee? Rule #ONE: Do not ever at any time under any duress reveal ANYTHING, do not even,... uh, we have issues.


Yet another leak, are you using the LeakySieve security model?


Yet another revelation. I hope this is a study project, not real application.

Thanks for your help.

We enjoy the work, just look at the post times.

[ May 07, 2008: Message edited by: Nicholas Jordan ]

"The differential equations that describe dynamic interactions of power generators are similar to that of the gravitational interplay among celestial bodies, which is chaotic in nature."
Amin Raykou
Greenhorn

Joined: Apr 17, 2008
Posts: 10
Good morning;
Thanks for your replys.
To Pat:
The result of a cipher is binary. It is not a string. You have to convert it to something that is a string, hex, mime, radix64, or something.

The void toString() doesn't convert the output to a string?
I tryed to convert from output to string then from string to base64 encoding but it doesn't resolve the problem.
A sample code to how to convert the cipher output to a string or hexa ascii (or how to use blob on oracle 10g) will be apreciated.Thanks

To Nicholas: I know it's a shame to do such mistakes but I'm a biginner with java and cryptography, and it's just a study project.
Code ( should ) insert(s) encrypted data in a byte buffer with the
void encipherString() then make the byte buffer insert(able) in (?) database.
how can i insert the byte buffer, should i just convert it to string ?
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

calling toString() on an object changes it to something that is a String. Whether it is a useful thing depends on what the object is.

You can not assume it will do something domain specific. And you can not expect that what the toString() generates can be converted back into the object that it was.

Do a trivial example, generate a HashMap and to a toString on it. Can you parse the answer back into a HashMap?
Amin Raykou
Greenhorn

Joined: Apr 17, 2008
Posts: 10
Thanks for your help Pat.
I understand that toString() isn't the solution to get the data from the output stream.
Now I'm in a lost!!!
How could I get the data from the output stream (of the encryption void) to store it into the database?
And how could I extract it to the input stream of the decryption void?
Can you please help me with a sample of code.
Thanks a lot for your help.
David O'Meara
Rancher

Joined: Mar 06, 2001
Posts: 13459

"amin amin",
Please check your private messages.
-DOM
Pat Farrell
Rancher

Joined: Aug 11, 2007
Posts: 4646
    
    5

I'm not willing to write the code for you. I will help.

But you have to actually write code that comes close. And as others have said, put it in [code] tags so it can be read by humans.
Nicholas Jordan
Ranch Hand

Joined: Sep 17, 2006
Posts: 1282


To get bytes out of a string, use the library method from the String class. To do this level of work, you have to look at the documentation. About one tenth to one third of your time is spent doing nothing but looking up documentaion. About 40-50 percent is spent actually writing code and the remainder is spent in sort of faraway contemplation.

Make sure you do not walk into any street lamp poles while in contemplation. It's kind of like drinking V-8 Juice with lots of ice in the glass. It will only go so fast, no further effort achieves anything.

[Amin Raykou]   The void toString() doesn't convert the output to a string?

This is a question I will answer without looking at whatever code you got it from. As a student, if this were any forum/issue other than Security you could be told to look it up in the docs. For this forum, we can examine what is being transformed to string and why. Consider the following code:

I wrote some 25,000 keystrokes of code since I last posted - most of which I copy-pasted from some code that was already written somewhere - but I knew either how it worked or how it was supposed to work. The code to do what I sample here is in the String class source code and as well is documented in the javadocs for the string class. Since this is a student project, you can just read the JavaDocs for the string class and put it up.

But where?

That is a simple issue, after you gain greater skills. Need a byte[]? Just declare one. That declaration is only a way to address a byte buffer ~ that does not give you one. If a library function returns a byte buffer, you just write byte[] buffer = libraryFunction(Type value); the single equals sign copys the ADDRESSING MECHANISIM not the acutal data. To conduct operations on the data, such as encipherment/encryption or BASE-64 encode/decode or any other operation you .... well you have to operate on each item in the compound data structure individually.

That is ususally done in a loop.

How you 'insert' the 'byte buffer' depends in great measure on where you are putting it and how secure the data needs to be. DES-Triple should be sufficient for any student level project. I do not have any exposure to BLOB's - the documentation for whatever tool you are using must be examined. You can insert a string using a base-64 encoder. If this is a study project and you have an instructor, the instructor is the first place you should look. If not, look a few posts back in this thread - Pat has one he shared with a poster.

I got alot of my project running in the last few days because of now having a base 64 encoder, Thanks Pat!

Now I'm in a lost!!!


Get used to it, bring your lunch and have some diversionary activities not too far away.

I understand that toString() isn't the solution to get the data from the output stream.

Correct, read the docs. For the reasons Pat gives you. Simple answers in the form of boilerplate code are only for the masters. If this is for actual learning, even without considering the security aspect, you have to do some "hours and hours of digging" or it won't do any of us any good.

  • How could I get the data from the output stream (of the encryption void) to store it into the database?
  • And how could I extract it to the input stream of the decryption void?

  • That is what your assignment is, we cannot do it for you.

    [ May 10, 2008: Message edited by: Nicholas Jordan ]
    [ May 11, 2008: Message edited by: Nicholas Jordan ]
    Amin Raykou
    Greenhorn

    Joined: Apr 17, 2008
    Posts: 10
    Thanks Nicholas for your help.
    It was so usefull.
    I'll bring my lunch and try to solve the problem
    Nicholas Jordan
    Ranch Hand

    Joined: Sep 17, 2006
    Posts: 1282
    Okay, this is much better.
  • Get bytes - though maybe for multiple objects. To obtain bytes on a primitive such as an int, wrap it in an object such as java.lang.Integer ( you may have to look around for one that has a get bytes method ) and call get bytes() or focus on how to get bytes for that object.
  • Encipher / encrypt or as the library tool you are using is documented to work.
  • Store those bytes somehow. Threre are several ways of doing this, read the docs of the database you wish to use. You may have to write some code yourself to do this effectively.
  • Store it.
  • THEN
    Figure out how to get it back out before using any actual data.


    To do that, focus on PF's post of Tuesday, May 06, 2008 8:24 PM. That is ultimately where your question has it's root, it is just that there is a lot of intevening matters that will seem like extracting tree sap on a fourty degree Winter day.

    { message edit: see also Pat's advice: 5/11/2008 - 11:31 PM Library for Encrypting Voice? }
    [ May 12, 2008: Message edited by: Nicholas Jordan ]
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: encrypt data in database