I am trying to encrypt a file which consists of some sample data like
company=abc-company
I have written the following code to encrypt the file using AES-128 bit key using password and salt. I am able to encrypt the file successfully to a file and write the decrypted data from the file to another file successfully. But, I want to store the decrypted data in a string. So, after roaming here on SO, I used ByteArrayOutputStream. But with that I am not able to get the complete plaintext in to the string. I am getting partial data (only first 16 characters i.e. excluding 'any') from the file. How to get the complete text from the file into the string?
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestAES {
private static final Logger logger = LoggerFactory.getLogger(TestAES.class);
private char[] password = "1111111111111111".toCharArray();
private byte[] salt = "SampleSalt".getBytes();
private byte[] initializationVector;
public static void main(String[] args) {
TestAES aes = new TestAES();
aes.encrypt(new File("D:\\plainText.licence"), new File("D:\\sample.licence"));
aes.decrypt(new File("D:\\sample.licence"));
}
public void encrypt(File plainTextFile, File encryptedLicenceFile) {
if (plainTextFile.exists() == false) {
try {
throw new FileNotFoundException("The plainTextFile was not found");
} catch (FileNotFoundException e) {
logger.error("The plainTextFile was not found", e);
e.printStackTrace();
}
}
if (encryptedLicenceFile.exists() == false) {
try {
encryptedLicenceFile.createNewFile();
} catch (IOException e) {
logger.error("IOException while creating encryptedLicenceFile", e);
e.printStackTrace();
}
}
logger.info("plainTextFile.exists() = " + plainTextFile.exists());
// To read the file to be encrypted
FileInputStream fileInputStream = null;
// To write the encrypted file
FileOutputStream fileOutputStream = null;
// To read the file information and to encrypt
CipherInputStream cipherInputStream = null;
try {
fileInputStream = new FileInputStream(plainTextFile);
fileOutputStream = new FileOutputStream(encryptedLicenceFile);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password, salt, 65536, 128);
logger.info("Generating KeySpec with password, salt.");
SecretKey secretKey = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
logger.debug("Obtaining AES cipher in encryption mode with secret key.");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters parameters = cipher.getParameters();
this.initializationVector = parameters.getParameterSpec(IvParameterSpec.class).getIV();
logger.info("Initialization Vector length = " + initializationVector.length);
cipherInputStream = new CipherInputStream(fileInputStream, cipher);
int read = 0;
while ((read = cipherInputStream.read()) != -1) {
fileOutputStream.write((char) read);
fileOutputStream.flush();
}
logger.info("Successfully written the sample.licence file.");
} catch (NoSuchAlgorithmException e) {
logger.error("NoSuchAlgorithmException: Check alogrithm.", e);
e.printStackTrace();
} catch (NoSuchPaddingException e) {
logger.error("NoSuchPaddingException: Check padding.", e);
e.printStackTrace();
} catch (InvalidKeySpecException e) {
logger.error("InvalidKeySpecException: Check keySpec.", e);
e.printStackTrace();
} catch (InvalidKeyException e) {
logger.error("InvalidKeyException: Check keySize.", e);
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
logger.error("InvalidParameterSpecException: Check parameters.", e);
e.printStackTrace();
} catch (FileNotFoundException e) {
logger.error("FileNotFoundException: Check fileToBeEncrypted.", e);
e.printStackTrace();
} catch (IOException e) {
logger.error("IOException occured.", e);
e.printStackTrace();
} finally {
try {
if (cipherInputStream != null) {
cipherInputStream.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
logger.error("Exception while closing stream.", e);
e.printStackTrace();
}
}
}
public void decrypt(File sampleLicence) {
if (sampleLicence.exists() == false) {
try {
throw new FileNotFoundException("The sampleLicence was not found");
} catch (FileNotFoundException e) {
logger.error("The sampleLicence was not found", e);
e.printStackTrace();
}
}
// To read the sample.licence
FileInputStream fileInputStream = null;
// To write decrypted licence file
FileOutputStream fileOutputStream = null;
// To read encrypted licence file and decrypt it
CipherOutputStream cipherOutputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
fileInputStream = new FileInputStream(sampleLicence);
byteArrayOutputStream = new ByteArrayOutputStream();
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(password, salt, 65536, 128);
logger.info("Generating KeySpec with password, salt during decryption.");
SecretKey secretKey = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
logger.debug("Obtaining AES cipher in decryption mode with secret key.");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(initializationVector));
cipherOutputStream = new CipherOutputStream(byteArrayOutputStream, cipher);
byte[] data = new byte[4096];
int read;
while ((read = fileInputStream.read(data)) != -1) {
cipherOutputStream.write(data, 0, read);
}
cipherOutputStream.flush();
byte[] plainText = byteArrayOutputStream.toByteArray();
System.out.println(new String(plainText, "UTF-8"));
} catch (NoSuchAlgorithmException e) {
logger.error("NoSuchAlgorithmException: Check alogrithm.", e);
e.printStackTrace();
} catch (NoSuchPaddingException e) {
logger.error("NoSuchPaddingException: Check padding.", e);
e.printStackTrace();
} catch (InvalidKeySpecException e) {
logger.error("InvalidKeySpecException: Check keySpec.", e);
e.printStackTrace();
} catch (InvalidKeyException e) {
logger.error("InvalidKeyException: Check keySize.", e);
e.printStackTrace();
} catch (FileNotFoundException e) {
logger.error("FileNotFoundException: Check fileToBeEncrypted.", e);
e.printStackTrace();
} catch (IOException e) {
logger.error("IOException occured.", e);
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
logger.error("InvalidAlgorithmParameterException", e);
e.printStackTrace();
} finally {
try {
if (cipherOutputStream != null) {
cipherOutputStream.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
} catch (IOException e) {
logger.error("Exception while closing stream.", e);
e.printStackTrace();
}
}
}
}
I did not try that, but it looks like you need to close the cipherOutputStream:
cipherOutputStream.close();
instead of the flush you have currently.
The reason is that flush can be called several times so the decryption will not be finished until close is called.
Related
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class Encryptor{
private static final int bufferSize= 128;
/**
* #param args
*/
public static void main(String[] args) {
BufferedInputStream in = null;
BufferedOutputStream out = null;
SecretKeyFactory kf = null;
KeySpec ks = null;
byte[] salt = new byte[20];
SecretKey key = null;
Cipher cipher = null;
SecretKeySpec keyspec = null;
int bytesRead = 0;
if (args.length != 4) {
printUsageMessage();
System.exit(1);
}
try {
in = new BufferedInputStream(new FileInputStream(args[1]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open input file: " + args[1], null);
System.exit(1);
}
try {
out = new BufferedOutputStream(new FileOutputStream(args[2]));
} catch (FileNotFoundException e) {
printErrorMessage("Unable to open output file: " + args[2], e);
System.exit(1);
}
try {
kf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e2) {
e2.printStackTrace();
}
String password = args[3];
ks = new PBEKeySpec(password.toCharArray(), salt, 128, 128);
try {
key = kf.generateSecret(ks);
} catch (InvalidKeySpecException e1) {
e1.printStackTrace();
}
byte[] aeskey = key.getEncoded();
try {
cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
} catch (NoSuchAlgorithmException e) {
printErrorMessage("No Such Algorithm Exception when creating main cipher", e);
System.exit(2);
} catch (NoSuchPaddingException e) {
printErrorMessage("No Such Padding Exception when creating main cipher", e);
System.exit(2);
}
int cipherMode = -1;
char mode = Character.toLowerCase(args[0].charAt(0));
switch (mode) {
case 'e':
cipherMode = Cipher.ENCRYPT_MODE;
break;
case 'd':
cipherMode = Cipher.DECRYPT_MODE;
break;
default:
printUsageMessage();
System.exit(1);
}
keyspec = new SecretKeySpec(aeskey, "AES");
try {
cipher.init(cipherMode, keyspec);
} catch (InvalidKeyException e) {
printErrorMessage("Invalid Key Spec", e);
System.exit(2);
}
byte[] inputBuffer = new byte[bufferSize];
byte[] outputBuffer = null;
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e) {
printErrorMessage("Error reading input file " + args[1], e);
System.exit(1);
}
while (bytesRead > 0) {
outputBuffer = cipher.update(inputBuffer);
try {
out.write(outputBuffer);
} catch (IOException e) {
printErrorMessage("Error writing to output file " + args[2], e);
System.exit(1);
}
try {
bytesRead = in.read(inputBuffer);
} catch (IOException e) {
printErrorMessage("Error reading input file " + args[1], e);
System.exit(1);
}
}
try {
outputBuffer = cipher.doFinal(inputBuffer);
} catch (IllegalBlockSizeException | BadPaddingException e1) {
e1.printStackTrace();
}
try {
out.write(outputBuffer);
} catch (IOException e) {
printErrorMessage("Error on final write to output file " + args[2], e);
System.exit(1);
}
try {
in.close();
out.close();
} catch (IOException e) {
printErrorMessage("Error closing file", e);
}
}
private static void printErrorMessage(String errMsg, Exception e) {
System.err.println(errMsg);
if (e != null)
System.err.println(e.getMessage());
}
private static void printUsageMessage() {
System.out.println(progName + " $Revision: 1.1 $: Usage: " + progName + " E/D infile outfile passphrase");
}
}
I am trying to write a program that encrypts and decrypts a text document using a password. It doesnt throw any errors on encrypt, but it does throw a bad padding exception on decrypt, but it still outputs the correct text but with extra stuff on the end. I have searched other answers but cannot find a solution. The program is run by compiling into runnable jar and running it like java -jar filename e/d (encrypt/decrypt) inputFile.txt outputFile.txt password.
Thanks in Advance
EDIT:
Exception:
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at java.base/com.sun.crypto.provider.CipherCore.unpad(Unknown Source)
at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(Unknown Source)
at java.base/com.sun.crypto.provider.CipherCore.doFinal(Unknown Source)
at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(Unknown Source)
at java.base/javax.crypto.Cipher.doFinal(Unknown Source)
at FileEncryptorSkeleton.main(FileEncryptorSkeleton.java:183)
this is where I add outputBuffer = cipher.doFinal(inputBuffer);
Sample Input:
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
Sample Output:
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazz
aaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzzaaaazzzz
output picture as invalid characters didnt show up in cod block
You repeatedly call bytesRead = in.read(inputBuffer) then cipher.update(inputBuffer). When the end of the input file is reached, only part of inputBuffer is set to new data and the rest is leftover residue from the previous read, but you use all of it. Then you call cipher.doFinal(inputBuffer) which uses another copy of whatever is left in the buffer after the last read.
On encryption, this results in encrypting repetitions of some data from the last few lines (up to 128 bytes). On decryption, this results in calling doFinal with data that is not actually the last part of the ciphertext, thus the 'bad padding' exception.
Instead do (modulo error handling for clarity):
bytesRead = in.read(inputBuffer);
while( bytesRead > 0 ){
outputBuffer = cipher.update(inputBuffer, 0, readBytes); // only use the part read
out.write(outputBuffer);
bytesRead = in.read(inputBuffer);
}
outputBuffer = cipher.doFinal(); // no data at all here, .update already processed it
out.write(outputBuffer);
PS: ECB applied to general data (like a 'text document') is almost always insecure; google ECB penguin. And PBKDF2 with only 128 iterations is not very good, and with constant salt is very bad. But those are security issues and offtopic here.
I have written a program to encrypt text in Java. It works fine for the most part.
Short strings encrypt and decrypt just fine.
However, if I input more than a few words, the encrypted text output to the console contains carriage-returns. Any ideas on what might be going on?
If I paste the output into notepad, and remove the returns, and then decrypt it with my program, it returns the originally input text as expected.
I have included most of the code, because I haven't any idea where the error is occurring.
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;
public class Application
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String textToEncrypt = "Hello World";
String textToDecrypt;
String textToDecryptAscii;
String result;
int operation;
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES");
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NoSuchPaddingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String key = "Baw12345Baw12345"; // 128 bit key
BASE64Encoder asciiEncoder = new BASE64Encoder();
BASE64Decoder asciiDecoder = new BASE64Decoder();
System.out.printf("Enter:\n1 for encryption\n2 for decryption\n\nChoice: ");
operation = input.nextInt();
input.nextLine();
if (operation == 1)
{
try
{
System.out.printf("\n---------\n\nText to encrypt: ");
textToEncrypt = input.nextLine();
//Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
//Cipher cipher = Cipher.getInstance("AES");
//encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(textToEncrypt.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b: encrypted)
{
sb.append((char)b);
}
// the encrypted String
String enc = sb.toString();
//System.out.println("encrypted:" + enc);
String asciiEncodedEncryptedResult = asciiEncoder.encodeBuffer(enc.getBytes());
System.out.println("Encrypted text: " + asciiEncodedEncryptedResult);
//System.out.printf("\n------------------------------\nDecrypted text: " + asciiEncodedEncryptedResult + "\n------------------------------\n\n\n");
}
catch(Exception e)
{
e.printStackTrace();
}
}
else if (operation == 2)
{
System.out.printf("\n---------\n\nText to decrypt: ");
textToDecryptAscii = input.nextLine();
byte[] decodedBytes = null;
try
{
decodedBytes = asciiDecoder.decodeBuffer(textToDecryptAscii);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//System.out.println("decodedBytes " + new String(decodedBytes));
textToDecrypt = new String(decodedBytes);
//Convert the string to byte array
//for decryption
byte[] bb = new byte[textToDecrypt.length()];
for (int i=0; i<textToDecrypt.length(); i++)
{
bb[i] = (byte) textToDecrypt.charAt(i);
}
//decrypt the text
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
try
{
cipher.init(Cipher.DECRYPT_MODE, aesKey);
}
catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String decrypted = null;
try
{
decrypted = new String(cipher.doFinal(bb));
}
catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.printf("\n------------------------------\nDecrypted text: " + decrypted + "\n------------------------------\n\n\n");
}
}
}
Your asciiEncoder (which is actually base64), will automatically add new line characters as part of how base64 works. You can remove this functionality in some implementations by something similar to this:
asciiEncoder.linelength = 0;
Additionally, you could just remove the newlines from the resulting string by replacing them with nothing.
I run a java program to verify digital signature
package com.cryptography;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
public class VerifyDkimSignature {
public static void main(String[] args) {
FileInputStream fis;
try {
//Read encoded public key bytes
fis = new FileInputStream
("/home/src/com/cryptography/DkimPublicKey");
byte[] encKey = new byte[fis.available()];
fis.read(encKey);
fis.close();
//Generate public key
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
//Read signature bytes from file
BufferedInputStream bis = new BufferedInputStream
(new FileInputStream
("/home/src/com/cryptography/Signature"));
byte[] signatureBytes = new byte[bis.available()];
bis.read(signatureBytes);
//Initialise signature instance
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify(pubKey);
//Supply signature object with the data for verification
bis = new BufferedInputStream
(new FileInputStream
("/home/src/com/cryptography/SampleFile.txt"));
byte[] origFile = new byte[1024];
int len = 0;
while(bis.available() != 0) {
len = bis.read(origFile);
sig.update(origFile, 0, len);
}
boolean isVerifies = sig.verify(signatureBytes);
System.out.println("Signature verifies::"+isVerifies);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
When I execute it, I get the following exception
java.security.SignatureException: Signature encoding error
at sun.security.rsa.RSASignature.engineVerify(Unknown Source)
at java.security.Signature$Delegate.engineVerify(Unknown Source)
at java.security.Signature.verify(Unknown Source)
at com.cryptography.VerifyDkimSignature.main(VerifyDkimSignature.java:54)
Caused by: java.io.IOException: ObjectIdentifier mismatch: 1.3.14.3.2.26
at sun.security.rsa.RSASignature.decodeSignature(Unknown Source)
... 4 more
Can someone please explain the reason for the error?
It turns out that "1.3.14.3.2.26" (from the IOException) is the OID for a SHA-1 algorithm. So the mistake which I have done here is using different algorithms for verification and signing i.e I have used SHA1withRSA for signing and SHA256With RSA for verification. This got resolved once I changed the algorithm at the verification end to SHA1WithRSA
I have this strange issue with java IO, in combination with AES encryption.
I am writing some encrypted text to a binary file, appending \n at the end of text. Say,
my beautiful string...
look! Another of my beautiful strings...
When I read the data back, I get the following text in return with a lot of extra tabs:
my beautiful string...
look! Another of my beautiful strings...
Here is my self-contained code:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class SecurityUtil
{
public static final String ENCRYPTION_ALGORITHM = "AES";
public static final String CHARACTER_SET = "UTF-8";
private static final int BLOCKS = 128;
private static final String KEY = "SomeSortOfEncryptionKey";
public static void main (String[] args) throws IOException
{
String str = "my beautiful string...\n";
byte[] encrypt = SecurityUtil.encrypt (str);
File f = new File ("C:\\myfile.dat");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f, true));
bos.write(encrypt);
bos.flush();
bos.close();
str = "look! Another of my beautiful strings...";
encrypt = SecurityUtil.encrypt (str);
bos = new BufferedOutputStream(new FileOutputStream(f, true));
bos.write(encrypt);
bos.flush();
bos.close();
byte[] buffer = new byte[(int) f.length ()];
FileInputStream fis = new FileInputStream (f);
fis.read (buffer);
fis.close ();
String decrypt = SecurityUtil.decrypt (buffer);
System.out.println(decrypt);
}
public static byte[] encrypt (String text)
{
try
{
byte[] rawKey = getRawKey (KEY.getBytes (CHARACTER_SET));
SecretKeySpec skeySpec = new SecretKeySpec (rawKey, ENCRYPTION_ALGORITHM);
Cipher cipher = Cipher.getInstance (ENCRYPTION_ALGORITHM);
cipher.init (Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal (text.getBytes (CHARACTER_SET));
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace ();
}
catch (IllegalBlockSizeException e)
{
e.printStackTrace ();
}
catch (BadPaddingException e)
{
e.printStackTrace ();
}
catch (InvalidKeyException e)
{
e.printStackTrace ();
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace ();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace ();
}
return null;
}
public static String decrypt (byte[] data)
{
try
{
byte[] rawKey = getRawKey (KEY.getBytes (CHARACTER_SET));
SecretKeySpec skeySpec = new SecretKeySpec (rawKey, ENCRYPTION_ALGORITHM);
Cipher cipher = Cipher.getInstance (ENCRYPTION_ALGORITHM);
cipher.init (Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal (data);
return new String (decrypted);
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace ();
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace ();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace ();
}
catch (InvalidKeyException e)
{
e.printStackTrace ();
}
catch (IllegalBlockSizeException e)
{
e.printStackTrace ();
}
catch (BadPaddingException e)
{
e.printStackTrace ();
}
return null;
}
private static byte[] getRawKey (byte[] seed)
{
try
{
KeyGenerator kgen = KeyGenerator.getInstance (ENCRYPTION_ALGORITHM);
SecureRandom sr = SecureRandom.getInstance ("SHA1PRNG");
sr.setSeed (seed);
kgen.init (BLOCKS, sr);
SecretKey skey = kgen.generateKey ();
byte[] raw = skey.getEncoded ();
return raw;
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace ();
}
return null;
}
}
Here is the console output (with extra spaces):
my beautiful string...
look! Another of my beautiful strings...
What am I doing wrong?
Ok! I got it. You cannot just append the encrypted text to a file. One way of solving this is extracting existing text from the file, append the new text, encrypt and write in the file again.
This doesn't seem to be a good solution, but in my case, where there is little text in a file, this can work.
I have an application which displays image downloaded from server. the image is encrypted and kept in the server using AES. I need to decrypt the image at the client side. The code used for encryption is as follows
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.ImageIO;
public class Crypto {
Cipher ecipher;
Cipher dcipher;
/**
* Input a string that will be md5 hashed to create the key.
* #return void, cipher initialized
*/
public Crypto(){
try{
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
this.setupCrypto(kgen.generateKey());
} catch (Exception e) {
e.printStackTrace();
}
}
public Crypto(String key){
SecretKeySpec skey = new SecretKeySpec(getMD5(key), "AES");
this.setupCrypto(skey);
}
private void setupCrypto(SecretKey key){
try
{ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
ecipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
dcipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
ecipher.init(Cipher.ENCRYPT_MODE, key);
dcipher.init(Cipher.DECRYPT_MODE, key);
}
catch (Exception e)
{
e.printStackTrace();
}
}
// Buffer used to transport the bytes from one stream to another
byte[] buf = new byte[1024];
public void encrypt(InputStream in, OutputStream out){
try {
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, ecipher);
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while ((numRead = in.read(buf)) >= 0){
out.write(buf, 0, numRead);
}
out.close();
}
catch (java.io.IOException e){
e.printStackTrace();
}
}
public void decrypt(InputStream in, OutputStream out){
try {
// Bytes read from in will be decrypted
in = new CipherInputStream(in, dcipher);
// Read in the decrypted bytes and write the cleartext to out
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
private static byte[] getMD5(String input){
try{
byte[] bytesOfMessage = input.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
return md.digest(bytesOfMessage);
} catch (Exception e){
return null;
}
}
public static void main(String args[]){
try {
Crypto encrypter = new Crypto("yursxjdlbkuikeqe"); ///key for decryption logic
encrypter.encrypt(new FileInputStream("D:\\Path\\Lighthouse.jpg"),new FileOutputStream("D:\\Encryption\\iOS code base\\Lighthouse.jpg.pkcs5"));
encrypter.decrypt(new FileInputStream("D:\\Path\\Lighthouse.jpg.pkcs5"),new FileOutputStream("D:\\Encryption\\iOS code base\\Lighthouse.jpg"));
System.out.println("DONE");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
I am not able to decrypt this using Blackberry AESDecryptor Engine. I am new to this crypto graphy. Is it possible to decrypt using AESDecryptor engine. I am attaching the code which I am using. Please help me in solving this
public MyScreen(){
// Set the displayed title of the screen
setTitle("MyTitle");
byte[] keyData = new String("yursxjdlbkuikeqe").getBytes();
byte[] cipherText = openFile("file:///SDCard/Lighthouse.jpg.pkcs5");
try {
imageData = decrypt(keyData, cipherText);
} catch (CryptoException e) {
System.out.println("::::::::::::::::::::::::::::::::::Crypto Exception:::::::"+e.getMessage());
} catch (IOException e) {
System.out.println("::::::::::::::::::::::::::::::::::IO Exception:::::::"+e.getMessage());
}
if(imageData!=null){
writeByteData(imageData);
// EncodedImage image = EncodedImage.createEncodedImage(imageData, 0, imageData.length);
// add(new BitmapField(image.getBitmap()));
System.out.println("------------------Image saved successfully-----------");
}else{
System.out.println("-------------------Image Data is null");
}
}
public static byte[] decrypt(byte[] keyData, byte[] ciphertext) throws CryptoException, IOException {
// First, create the AESKey again.
/*String str=new String(keyData);
System.out.println(str);*/
AESKey key = new AESKey(keyData,0,128);
System.out.println("Key is ::"+key.getAlgorithm()+"Length:"+key.getBitLength());
//
// // Now, create the decryptor engine.
AESDecryptorEngine engine = new AESDecryptorEngine(key);
PKCS5UnformatterEngine uengine = new PKCS5UnformatterEngine(engine);
/
// // Create the BlockDecryptor to hide the decryption details away.
ByteArrayInputStream input = new ByteArrayInputStream(ciphertext);
BlockDecryptor decryptor = new BlockDecryptor(engine, input);
byte[] plaintextAndHash = new byte[1024];
ByteArrayOutputStream output = new ByteArrayOutputStream();
int bytesRead=0;
do{
bytesRead =decryptor.read(plaintextAndHash);
if(bytesRead!=-1){
output.write(plaintextAndHash,0,bytesRead);
}
}
while(bytesRead!=-1);
return output.toByteArray();
}
You don't really say what your problem is, but at least the following line looks incorrect:
BlockDecryptor decryptor = new BlockDecryptor(engine, input);
It should be
BlockDecryptor decryptor = new BlockDecryptor(uengine, input);
I just changed engine to uengine
RIM's APIs make this pretty easy but it is a little tough to find the documentation. Check out the Javadocs for the package net.rim.device.api.crypto at:
http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/crypto/package-summary.html
You should look through all of it but the answer is in number 7: Encryptor and decryptor factories.
http://www.blackberry.com/developers/docs/7.0.0api/net/rim/device/api/crypto/doc-files/factories.html
The DecryptorFactory can create an input stream that you can just read as any InputStream.