I want to store data (encrypted with DES) and then take the encrypted data from database and present it as a list. But I have a problem. Here is the code.
public void EncryptDemo(){
try {
FileInputStream keyfis = new FileInputStream("mainkey.key");
byte[] encodedKey = new byte[keyfis.available()];
keyfis.read(encodedKey);
keyfis.close();
Key KeyFromFile = new SecretKeySpec(encodedKey, "DES");
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
String text=txtToEncryptData.getText(), output;
cipher.init(Cipher.ENCRYPT_MODE, KeyFromFile);
DataDemo = cipher.doFinal(text.getBytes());
InsertIntoDataBase();
//I store it as varbinary in database
} catch (FileNotFoundException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void DecryptDemo(){
try {
FileInputStream keyfis = new FileInputStream("mainkey.key");
byte[] encodedKey = new byte[keyfis.available()];
keyfis.read(encodedKey);
keyfis.close();
Key KeyFromFile = new SecretKeySpec(encodedKey, "DES");
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, KeyFromFile);
String sql = "{call SelectAll}";
CallableStatement call = conn.prepareCall(sql);
call.execute();
ResultSet result = call.getResultSet();
DefaultListModel model = new DefaultListModel();
while(result.next()){
DataDemo = result.getBytes("TestData");
byte[] plainText = cipher.doFinal(DataDemo);
String after = new String(plainText);
model.addElement(after);
}
lstDecryptResult.setModel(model);
} catch (SQLException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (FileNotFoundException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
The encrypt and storing is allright. But when I take data from database, I get this error when decrypt (at byte[] plainText = cipher.doFinal(DataDemo);)
Jul 19, 2013 11:40:05 AM databaseencryptdecryptdemo.MainGUI DecryptDemo
SEVERE: null
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
Anyone have a solution for this???
You should divide DataDemo variable into 8 byte pieces.
public List<Byte[]> divideInto8(Byte[] bytes) {
int length = bytes.length;
List<Byte[]> returnValues = new ArrayList<Byte[]>();
for (int i = 0; i < length; i = i + 8) {
Byte[] thebytes = new Byte[8];
for (int j = 0; j < 8; j++) {
thebytes[j] = bytes[i * 8 + j];
}
returnValues.add(thebytes);
}
return returnValues;
}
I found the solution. But I think it's not the best.
I changed the type of table DataDemo from varbinary to image and everything became alright. But my data size store in database is heavier (about 4 times) than the oigin data.
But at least I solved my problem.
Does anyone have a better solution? I willing to hear from you.
Related
I'm trying to get the byte array value of the genrated SecretKey, but the result is always null,
This is my code :
mKeyStore = KeyStore.getInstance(ANDROID_KEYSTORE_PROVIDER);
mKeyStore.load(null);
KeyStore.SecretKeyEntry secretKeyEntry = null;
if (!mKeyStore.containsAlias(KEY_ALIAS_AES)) {
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE_PROVIDER);
KeyGenParameterSpec.Builder builder = null;
builder = new KeyGenParameterSpec.Builder(
KEY_ALIAS_AES,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT);
builder.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setKeySize(256);
keyGenerator.init(builder.build());
sKey = keyGenerator.generateKey();
secretKeyEntry = new KeyStore.SecretKeyEntry(sKey);
mKeyStore.setKeyEntry(KEY_ALIAS_AES, secretKeyEntry.getSecretKey().getEncoded(), null);
}
try {
tmpKey = mKeyStore.getKey(KEY_ALIAS_AES, null).getEncoded();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
tmpKey is always null, any help please ?
I am creating a secure chat client and server combo that, when finished, will have multiple layers of encryption. However, I don't understand why I am getting this error. I know there are multiple questions out there with many different answers (some so different I don't understand how anyone gets their problem resolved), however I have yet to find one that I can understand enough of to fix this error.
Originally, this actually worked; it sent the key through without a problem. I don't remember changing any part of this code. Maybe someone can tell me what's wrong? I'll mark the line with the error.
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at secureserver.Server$1.run(Server.java:88)
at java.lang.Thread.run(Unknown Source)
Part of Server that receives key
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec("i15646dont6321wanna".toCharArray(),"ahhalkdjfslk3205jlk3m4ljdfa85l".getBytes("UTF8"),65536,256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey key = new SecretKeySpec(tmp.getEncoded(),"AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivspec);
byte[] b = new byte[is.available()];
is.read(b);
/* Line 88 */ byte[] dec = cipher.doFinal(b);
SecretKey ck = new SecretKeySpec(dec,"AES");
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, ck, ivspec);
eciphers.put(client, c);
c.init(Cipher.DECRYPT_MODE, ck, ivspec);
dciphers.put(client, c);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Part of the client that sends key to server
public void sendKey(SecretKey k) {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec("i15646dont6321wanna".toCharArray(),"ahhalkdjfslk3205jlk3m4ljdfa85l".getBytes("UTF8"),65536,256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey key = new SecretKeySpec(tmp.getEncoded(),"AES");
Cipher ec = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
ec.init(Cipher.ENCRYPT_MODE, key, ivspec);
byte[] ekey = ec.doFinal(k.getEncoded());
os.write(ekey);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
It's probably your stream handling that causes this:
byte[] b = new byte[is.available()];
is.read(b);
Is not a correct way of handling streams. Try a Java I/O tutorial to understand how to treat streams.
As a side note, for better and more legible exception handling:
try {
// handling Cipher code...
} catch (final IllegalBlockSizeException | BadPaddingException | IOException e) {
// or use your own checked exception
throw new IllegalArgumentException("Invalid ciphertext", e);
} catch (final GeneralSecurityException e) {
throw new IllegalStateException("Cryptographic algorithms not available", e);
}
I have a table with bytea data type on a PostgreSQL table.
I am trying to write and retrieve a pdf file from the bytea data using JDBC resultset.
However the file is corrupted while trying to display it after retrieving it.
Here is my code:
private void insertBytea(java.io.File file) {
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
Logger.getLogger(BeteaTest.class.getName()).log(Level.SEVERE, null, ex);
}
try {
java.sql.Connection connectDB = java.sql.DriverManager.getConnection("jdbc:postgresql://localhost:5433/funsoft", "postgres", "xxx");
connectDB.setAutoCommit(false);
java.sql.PreparedStatement pstmt = connectDB.prepareStatement("INSERT INTO test_binary (test_bytea) VALUES(?)");
java.io.FileInputStream fis;
try {
fis = new java.io.FileInputStream(file);
pstmt.setBinaryStream(1, fis, (int) file.length());
pstmt.executeUpdate();
connectDB.commit();
pstmt.close();
java.sql.PreparedStatement pstmtR = connectDB.prepareStatement("SELECT * FROM test_binary LIMIT 1");
// pstmtR.setString(1, file.getName());
java.sql.ResultSet rs = pstmtR.executeQuery();
while (rs.next()) {
byte[] imgBytes = rs.getBytes(2);
//java.io.InputStream ios = rs.getBinaryStream(2);
java.io.ByteArrayInputStream byteaStream = new java.io.ByteArrayInputStream(imgBytes);
java.io.File tempFile;
try {
tempFile = java.io.File.createTempFile("REP" + com.afrisoftech.lib.DateLables.getDateLabel() + "_", ".pdf");
java.io.FileOutputStream fileIS = new java.io.FileOutputStream(tempFile);
fileIS.write(imgBytes);
fileIS.close();
// this is where i am trying to display the file
com.afrisoftech.lib.PDFRenderer.renderPDF(tempFile);
} catch (IOException ex) {
Logger.getLogger(BeteaTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
fis.close();
} catch (IOException ex) {
ex.printStackTrace();
Logger.getLogger(BeteaTest.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (FileNotFoundException ex) {
Logger.getLogger(BeteaTest.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (SQLException ex) {
ex.printStackTrace();
Logger.getLogger(BeteaTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
I am trying to open a Password protected keystore file which I have it in the jre security Directory. I am using Bouncy Castel as my JCE. For some reason, I seem to get exceptions for which I have no clue as to why. Please help. Thanks. Here is what I have:
Code Snippet:
String passwd = "abcd123";
try {
String file = "C:\\Program Files\\Java\\jre7\\lib\\security\\keystore.ssm";
System.out.println("file =" + file);
File keystoreFile = new File(file);
if (keystoreFile.exists()) {
KeyStore store = KeyStore.getInstance("PKCS12", "BC");
//KeyStore store = KeyStore.getInstance("PKCS12");
FileInputStream in = new FileInputStream(keystoreFile);
store.load(in, passwd.toCharArray());
// Key key = store.getKey("mykeystore",passwd.toCharArray());
}
} catch (KeyStoreException ex) {
Logger.getLogger(SimpleBCTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchProviderException ex) {
Logger.getLogger(SimpleBCTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(SimpleBCTest.class.getName()).log(Level.SEVERE, null, ex);
} /*catch (UnrecoverableKeyException ex) {
Logger.getLogger(SimpleBCTest.class.getName()).log(Level.SEVERE, null, ex);
} */ catch (IOException ex) {
Logger.getLogger(SimpleBCTest.class.getName()).log(Level.SEVERE, null, ex);
} catch (CertificateException ex) {
Logger.getLogger(SimpleBCTest.class.getName()).log(Level.SEVERE, null, ex);
}
Exception I get:
Exception in thread "main" java.lang.ClassCastException: org.bouncycastle.asn1.DLSequence cannot be cast to org.bouncycastle.asn1.ASN1Integer
I'm trying to use an AES cipher to encrypt some bytes but it's returning a silent error, meaning I enter something like:
byte[] raw = new String("Test","UTF8").getBytes("UTF8");
and it won't return anything. I think the problem is the ByteArrayInput/OutputStreams but I don't know how to do it any other way..
Here's the code in question.
public byte[] encrypt(byte[] in) {
byte[] encrypted = null;
try {
aesCipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec);
ByteArrayInputStream bais = new ByteArrayInputStream(in);
ByteArrayOutputStream baos = new ByteArrayOutputStream(bais.available());
CipherOutputStream os = new CipherOutputStream(baos, aesCipher);
copy(bais, os);
os.flush();
byte[] raw = baos.toByteArray();
os.close();
encrypted = Base64.encodeBase64(raw);
} catch (FileNotFoundException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
}
return encrypted;
}
Here's another function in the same class that does work:
public void encrypt(File in, File out) {
try {
aesCipher.getInstance("AES/CBC/PKCS5Padding");
aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec);
FileInputStream is;
is = new FileInputStream(in);
CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), aesCipher);
copy(is, os);
os.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(FileEncryption.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void copy(InputStream is, OutputStream os) throws IOException {
int i;
byte[] b = new byte[2048];
while ((i = is.read(b)) != -1) {
os.write(b, 0, i);
}
}
The first thing that catches my eye is this line:
aesCipher.getInstance("AES/CBC/PKCS5Padding");
Assuming aesCipher is a variable of type Cipher, you are calling here the static Cipher.getInstance and throwing away the result (not assigning it to any variable). I.e. this line has no effect at all, aesCipher is the same as before this line.
If it was null before, then it still is null, and the next line (which calls a non-static method) will give you a NullPointerException. If your code is silently gobbling unknown exceptions (this might be outside the code shown), this is a general problem.
Other than this, I suppose that the flush on the CipherOutputStream does not really flush the whole buffer, but only as many blocks that can be written without adding any padding. Use close() instead of flush() here (which also seems to work in the second example).
A general remark: A small self-contained complete compilable example would have enabled me to try it and give you a definite answer, instead of only guessing. For example, "does not return anything" is not a good description for the behavior of your method - does the method return null, an empty array, throw an exception, block eternally?