I have been able to use the algorithm to encrypt and decrypt files , but when I go to try and send a file from Android to a WAS server, it fails. Here is the encrypt side
Security.addProvider(new BouncyCastleProvider());
KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecureRandom random = new SecureRandom();
keygen.init(random);
SecretKey key = keygen.generateKey();
// wrap with RSA public key
ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream (getFileLocation(PUBLIC_KEY, localTest)));
Key publicKey = (Key) keyIn.readObject();
keyIn.close();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.WRAP_MODE, publicKey);
byte[] wrappedKey = cipher.wrap(key);
DataOutputStream out = new DataOutputStream(new FileOutputStream(getFileLocation(SIGN_FILE, localTest)));
out.writeInt(wrappedKey.length);
out.write(wrappedKey);
InputStream in = new ByteArrayInputStream(message.getBytes());
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
crypt(in, out, cipher);
in.close();
out.close();
FileInputStream fis = new FileInputStream(getFileLocation(SIGN_FILE, localTest));
byte[] buffer = new byte[fis.available()];
int i =0;
while (i< buffer.length ){
buffer[i]= (byte)fis.read();
i++;
}
String ss = encodeMsg(buffer);
return ss;
Here is the decrypt side
Security.addProvider(new BouncyCastleProvider());
byte[] arr = decodeMsg(encrypted);
DataInputStream in = new DataInputStream(new ByteArrayInputStream(arr));
int length = in.readInt();
byte[] wrappedKey = new byte[length];
in.read(wrappedKey, 0, length);
// unwrap with RSA private key
ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream (getFileLocation(PRIVATE_KEY, localTest)));
Key privateKey = (Key) keyIn.readObject();
keyIn.close();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.UNWRAP_MODE, privateKey);
Key key = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
OutputStream out = new FileOutputStream(getFileLocation(DECRYPTED, localTest));
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
crypt(in, out, cipher);
in.close();
out.close();
FileInputStream fis = new FileInputStream(getFileLocation(DECRYPTED, localTest));
byte[] buffer = new byte[fis.available()];
int i =0;
while (i< buffer.length ){//!= 0) {
buffer[i]= (byte)fis.read();
i++;
}
String ss = new String(buffer);
return ss;
Again, on my workstation, this works. When doing the mobile request to the WAS web server, it fails. At first, it argued with the object class and so I recreated the keys using Java 1.6. I have recompiled the war into Java 1.6 as well. It errors as below.
--cipher unwrap
java.security.InvalidKeyException com.ibm.crypto.provider.RSA.engineUnwrap(Unknown Source)
javax.crypto.Cipher.unwrap(Unknown Source)
com.webapp.web.security.RSAEncrypt.decrypt(RSAEncrypt.java:161)
com.webapp.web.MobileRequest.doPost(MobileRequest.java:81)
javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
...
Does the WAS environment have to be updated to handle this? ideas?
UPDATE the keysize is set to 2048
This could be due to key policy settings, do you have the Unlimited Strength Juristiction Policies installed on both machines? They can be found at the bottom of this page: http://www.oracle.com/technetwork/java/javase/downloads/index.html
Else, how are you sending the data to the server?
The Unlimited Jurisdiciton policy might work, but I attempted to use the IBMJCE without success as well. Then, I switched to use the SunJCE provider (version Java 1.6) and now I am able to do the encryption and decryption in both Android and Websphere. I am having the administrators look into the policy files to see if BouncyCastle could be enabled, but I am ok with using the Sun provider files.
Related
I export a database with mysqldump a database in Ubuntu with java, then I encrypt and decrypt it with Java. I doing that with the following classes Encrypt and Decrypt with Java. But after the decryption some characters at the start of the file is wrong. Here is the problem:
At the first image is the file which programmatically have mysqldump, encrypt and decrypt. At the second one is just the mysqldump from the same command line. Can you point me the direction what to do? Thanks
EDIT
I have create a salt and stored it in a file like this:
Encryption:
FileInputStream saltFis = new FileInputStream("salt.enc");
byte[] salt = new byte[8];
saltFis.read(salt);
saltFis.close();
// reading the iv
FileInputStream ivFis = new FileInputStream("iv.enc");
byte[] iv = new byte[16];
ivFis.read(iv);
ivFis.close();
SecretKeyFactory factory = SecretKeyFactory.getInstance(secretAlgorithm1);
KeySpec keySpec = new PBEKeySpec(rsaSecret.toCharArray(), salt, 65536, 256);
SecretKey secretKey = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), secretAlgorithm2);
//
Cipher cipher = Cipher.getInstance(algorithmEncryption);
cipher.init(Cipher.ENCRYPT_MODE, secret);
// file encryption
byte[] input = new byte[64];
int bytesRead;
while ((bytesRead = inFile.read(input)) != -1) {
byte[] output = cipher.update(input, 0, bytesRead);
if (output != null)
outFile.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
outFile.write(output);
inFile.close();
outFile.flush();
outFile.close();
Decryption:
FileInputStream saltFis = new FileInputStream("salt.enc");
byte[] salt = new byte[8];
saltFis.read(salt);
saltFis.close();
// reading the iv
FileInputStream ivFis = new FileInputStream("iv.enc");
byte[] iv = new byte[16];
ivFis.read(iv);
ivFis.close();
SecretKeyFactory factory = SecretKeyFactory.getInstance(secretAlgorithm1);
KeySpec keySpec = new PBEKeySpec(rsaSecret.toCharArray(), salt, 65536, 256);
SecretKey secretKey = factory.generateSecret(keySpec);
SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), secretAlgorithm2);
// file decryption
Cipher cipher = Cipher.getInstance(algorithmEncryption);
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
FileInputStream fis = new FileInputStream(decodedB64);
FileOutputStream fos = new FileOutputStream(outputFile);
byte[] in = new byte[64];
int read;
while ((read = fis.read(in)) != -1) {
byte[] output = cipher.update(in, 0, read);
if (output != null)
fos.write(output);
}
byte[] output = cipher.doFinal();
if (output != null)
fos.write(output);
fis.close();
fos.flush();
fos.close();
System.out.println("File Decrypted.");
Oh, that one is simple. That idiotic (but funny enough, seeming largely correct otherwise) method of file encryption using CBC stores the IV in a separate file, overwriting any old one. So if you overwrite or take the wrong IV file then you'll get 16 random bytes at the start after decryption. So unless you can find the IV file that hopefully makes sense, your first 16 bytes (/characters) are now lost forever.
Of course, any sane encryption program stores the salt (a password & PBKDF2 is used for key derivation) and IV in the same file as the ciphertext.
Still, if you managed to lose the salt file or password then all the data would have been lost, so there's that...
With the added code the issue becomes even more clear. In the encryption mode you are forgetting to create & use an IvParameterSpec entirely during initialization:
cipher.init(Cipher.ENCRYPT_MODE, secret);
however, because of the way the IV data is read, you don't get any warning that the variable isn't used:
ivFis.read(iv);
If you would have created a nice method such as IvParameterSpec iv = readIvFromFile() then you would have caught this error.
Note that Java (by default in the included provider for Cipher) uses an all zero IV, so you're lucky and your data isn't partially gone.
I have a problem when decrypting XML type my file my returns incomplete data algorithm and rare symbols.
public File decryptFile(File fileInput, X509Certificate certificate) throws BadPaddingException, Exception {
try (DataInputStream dis = new DataInputStream(new FileInputStream(fileInput))) {
byte[] encryptedKeyBytes = new byte[dis.readInt()];
dis.readFully(encryptedKeyBytes);
PublicKey publicKey = certificate.getPublicKey();
rsaCipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] rijndaelKeyBytes = rsaCipher.doFinal(encryptedKeyBytes);
SecretKey rijndaelKey = new SecretKeySpec(rijndaelKeyBytes, "Rijndael");
byte[] iv = new byte[16];
dis.read(iv);
IvParameterSpec spec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, rijndaelKey, spec);
try (CipherInputStream cis = new CipherInputStream(dis, cipher)) {
try (FileOutputStream fos = new FileOutputStream(fileInput.getAbsolutePath() + ".xml")) {
byte[] data = new byte[16];
int theByte;
while ((theByte = cis.read(data)) != -1) {
System.out.print(new String(data));
fos.write(data, 0, theByte);
}
System.out.println("\n\n");
}
}
}
return new File(fileInput.getAbsolutePath() + ".xml");
}
this code returns me the data
</ctaAbonBenef><distPago>00000</distPago><item>00000</item><pagoPoder>N</p�|���[�[W�Z�5��Q�
I think this has to do with UTF-8, but I can not solve.
Now I can also believe that it is the encryption algorithm to use, I leave just in case.
public static void generateFileEncrypt(File fileInput, PrivateKey privateKey, String folderSave) throws Exception {
String fileOutput = folderSave + "\" + fileInput.getName() + ENCRYPTED_FILENAME_SUFFIX;
DataOutputStream output = new DataOutputStream(new FileOutputStream(fileOutput));
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.ENCRYPT_MODE, privateKey);
KeyGenerator rijndaelKeyGenerator = KeyGenerator.getInstance("Rijndael");
rijndaelKeyGenerator.init(128);
Key rijndaelKey = rijndaelKeyGenerator.generateKey();
byte[] encodedKeyBytes = rsaCipher.doFinal(rijndaelKey.getEncoded());
output.writeInt(encodedKeyBytes.length);
output.write(encodedKeyBytes);
SecureRandom random = new SecureRandom();
byte[] iv = new byte[16];
random.nextBytes(iv);
output.write(iv);
IvParameterSpec spec = new IvParameterSpec(iv);
Cipher symmetricCipher = Cipher.getInstance("Rijndael/CBC/PKCS5Padding");
symmetricCipher.init(Cipher.ENCRYPT_MODE, rijndaelKey, spec);
try (
CipherOutputStream cos = new CipherOutputStream(output, symmetricCipher);
FileInputStream fis = new FileInputStream(fileInput)) {
int theByte;
byte[] data = new byte[16];
while ((theByte = fis.read(data)) != -1) {
System.out.print(new String(data));
cos.write(data, 0, theByte);
}
System.out.println("\n\n");
cos.flush();
}
}
Thanks in advance.
I haven't digested all your code; I stopped when I saw you trying to decrypt with the public key, and encrypting with the private key. That's sort of like a digital signature, but your padding will be all wrong and you should use the Signature class if that is what your really want to do.
The public key is used to encrypt, or to verify a digital signature. Use the private key to decrypt, and see if that resolves your problem.
You are still doing it wrong. Don't call it "encryption" if the key isn't private.
But anyway, I think the printing to stdout looks wrong because you are converting the entire buffer to text. The last block is likely to be padded, so it won't decode to valid text—it's padding; it wasn't part of the input file, and you aren't writing it to the decrypted file, but you are printing it.
Change to encrypt with the public key, decrypt with the private key, and then change your printing to this:
System.out.print(new String(data, 0, theByte));
Even better would be to specify the character set of the data (probably UTF-8, since it's the default for XML).
I think u should do the opposite. encrypt with the public key and decrypt with the private key..
I've been researching this for the past 4-5 hours now and can't seem to find an answer that actually works despite finding 'answers' that used everything from a few methods to an entire ~100 line class. I can't imagine that there isn't some simple function to do such a trivial thing :P
I have a pre-existing set of public / private keys (actually, two sets - one generated by ssh-keygen and another by openssl so .. whatever format works is cool).
All I am after is a simple java equivalent to what I write in python like -
key_object = someModule.KeyObject(nameOfPublicKeyFile)
def encrypt (SomePlainText) :
return someOtherModule.encrypt(key_object, SomePlainText)
Any help would be awesome!
These openssl commands in the shell create an RSA key pair and write the public and private keys to DER formatted files.
Here, the private key file is not password-protected (-nocrypt) to keep things simple.
$ openssl genrsa -out keypair.pem 2048
Generating RSA private key, 2048 bit long modulus
............+++
................................+++
e is 65537 (0x10001)
$ openssl rsa -in keypair.pem -outform DER -pubout -out public.der
writing RSA key
$ openssl pkcs8 -topk8 -nocrypt -in keypair.pem -outform DER -out private.der
Now that you have the DER files, you can read them in Java and use KeySpec and KeyFactory to create PublicKey and PrivateKey objects.
public byte[] readFileBytes(String filename) throws IOException
{
Path path = Paths.get(filename);
return Files.readAllBytes(path);
}
public PublicKey readPublicKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
{
X509EncodedKeySpec publicSpec = new X509EncodedKeySpec(readFileBytes(filename));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(publicSpec);
}
public PrivateKey readPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException
{
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(readFileBytes(filename));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}
With the public and private keys, you can encrypt and decrypt small amounts of data (that fit within your RSA modulus.) I recommend OAEP padding.
public byte[] encrypt(PublicKey key, byte[] plaintext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(plaintext);
}
public byte[] decrypt(PrivateKey key, byte[] ciphertext) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException
{
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
return cipher.doFinal(ciphertext);
}
Here it is tied together with a simple encryption and decryption:
public void Hello()
{
try
{
PublicKey publicKey = readPublicKey("public.der");
PrivateKey privateKey = readPrivateKey("private.der");
byte[] message = "Hello World".getBytes("UTF8");
byte[] secret = encrypt(publicKey, message);
byte[] recovered_message = decrypt(privateKey, secret);
System.out.println(new String(recovered_message, "UTF8"));
}
catch (Exception e)
{
e.printStackTrace();
}
}
I would like to share a piece of code.. well actually a whole class which can do what you require if you customize it to your own needs. I have used this in one of my application where I used to encrypt/decrypt a file with the generated public/private keys. Same can be applied to Strings as well.
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.util.*;
/**
* This class encrypts and decrypts a file using CipherStreams
* and a 256-bit Rijndael key. The key is then encrypted using
* a 1024-bit RSA key, which is password-encrypted.
*/
public class FileEncryptorRSA {
/**
* When files are encrypted, this will be appended to the end
* of the filename.
*/
private static final String ENCRYPTED_FILENAME_SUFFIX=".encrypted";
/**
* When files are decrypted, this will be appended to the end
* of the filename.
*/
private static final String DECRYPTED_FILENAME_SUFFIX=".decrypted";
/**
* Number of times the password will be hashed with MD5
* when transforming it into a TripleDES key.
*/
private static final int ITERATIONS = 1000;
/**
* FileEncryptor is started with one of three options:
*
* -c: create key pair and write it to 2 files
* -e: encrypt a file, given as an argument
* -d: decrypt a file, given as an argument
*/
public static void main (String[] args)
throws Exception {
if ((args.length < 1) || (args.length > 2)) {
usage();
} else if ("-c".equals(args[0])) {
createKey();
} else if ("-e".equals(args[0])) {
encrypt(args[1]);
} else if ("-d".equals(args[0])) {
decrypt(args[1]);
} else {
usage();
}
}
private static void usage() {
System.err.println("Usage: java FileEncryptor -c|-e|-d [filename]");
System.exit(1);
}
/**
* Creates a 1024 bit RSA key and stores it to
* the filesystem as two files.
*/
private static void createKey()
throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Password to encrypt the private key: ");
String password = in.readLine();
System.out.println("Generating an RSA keypair...");
// Create an RSA key
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.genKeyPair();
System.out.println("Done generating the keypair.\n");
// Now we need to write the public key out to a file
System.out.print("Public key filename: ");
String publicKeyFilename = in.readLine();
// Get the encoded form of the public key so we can
// use it again in the future. This is X.509 by default.
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
// Write the encoded public key out to the filesystem
FileOutputStream fos = new FileOutputStream(publicKeyFilename);
fos.write(publicKeyBytes);
fos.close();
// Now we need to do the same thing with the private key,
// but we need to password encrypt it as well.
System.out.print("Private key filename: ");
String privateKeyFilename = in.readLine();
// Get the encoded form. This is PKCS#8 by default.
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
// Here we actually encrypt the private key
byte[] encryptedPrivateKeyBytes =
passwordEncrypt(password.toCharArray(),privateKeyBytes);
fos = new FileOutputStream(privateKeyFilename);
fos.write(encryptedPrivateKeyBytes);
fos.close();
}
/**
* Encrypt the given file with a session key encrypted with an
* RSA public key which will be read in from the filesystem.
*/
private static void encrypt(String fileInput)
throws Exception {
BufferedReader in = new BufferedReader
(new InputStreamReader(System.in));
System.out.print("Public Key to encrypt with: ");
String publicKeyFilename = in.readLine();
// Load the public key bytes
FileInputStream fis = new FileInputStream(publicKeyFilename);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int theByte = 0;
while ((theByte = fis.read()) != -1)
{
baos.write(theByte);
}
fis.close();
byte[] keyBytes = baos.toByteArray();
baos.close();
// Turn the encoded key into a real RSA public key.
// Public keys are encoded in X.509.
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
// Open up an output file for the output of the encryption
String fileOutput = fileInput + ENCRYPTED_FILENAME_SUFFIX;
DataOutputStream output = new DataOutputStream
(new FileOutputStream(fileOutput));
// Create a cipher using that key to initialize it
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
rsaCipher.init(Cipher.ENCRYPT_MODE, publicKey);
// Now create a new 256 bit Rijndael key to encrypt the file itself.
// This will be the session key.
KeyGenerator rijndaelKeyGenerator = KeyGenerator.getInstance("Rijndael");
rijndaelKeyGenerator.init(256);
System.out.println("Generating session key...");
Key rijndaelKey = rijndaelKeyGenerator.generateKey();
System.out.println("Done generating key.");
// Encrypt the Rijndael key with the RSA cipher
// and write it to the beginning of the file.
byte[] encodedKeyBytes= rsaCipher.doFinal(rijndaelKey.getEncoded());
output.writeInt(encodedKeyBytes.length);
output.write(encodedKeyBytes);
// Now we need an Initialization Vector for the symmetric cipher in CBC mode
SecureRandom random = new SecureRandom();
byte[] iv = new byte[16];
random.nextBytes(iv);
// Write the IV out to the file.
output.write(iv);
IvParameterSpec spec = new IvParameterSpec(iv);
// Create the cipher for encrypting the file itself.
Cipher symmetricCipher = Cipher.getInstance("Rijndael/CBC/PKCS5Padding");
symmetricCipher.init(Cipher.ENCRYPT_MODE, rijndaelKey, spec);
CipherOutputStream cos = new CipherOutputStream(output, symmetricCipher);
System.out.println("Encrypting the file...");
FileInputStream input = new FileInputStream(fileInput);
theByte = 0;
while ((theByte = input.read()) != -1)
{
cos.write(theByte);
}
input.close();
cos.close();
System.out.println("File encrypted.");
return;
}
/**
* Decrypt the given file.
* Start by getting the RSA private key
* and decrypting the session key embedded
* in the file. Then decrypt the file with
* that session key.
*/
private static void decrypt(String fileInput)
throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Private Key to decrypt with: ");
String privateKeyFilename = in.readLine();
System.out.print("Password for the private key: ");
String password = in.readLine();
// Load the private key bytes
FileInputStream fis = new FileInputStream(privateKeyFilename);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int theByte = 0;
while ((theByte = fis.read()) != -1)
{
baos.write(theByte);
}
fis.close();
byte[] keyBytes = baos.toByteArray();
baos.close();
keyBytes = passwordDecrypt(password.toCharArray(), keyBytes);
// Turn the encoded key into a real RSA private key.
// Private keys are encoded in PKCS#8.
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
// Create a cipher using that key to initialize it
Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// Read in the encrypted bytes of the session key
DataInputStream dis = new DataInputStream(new FileInputStream(fileInput));
byte[] encryptedKeyBytes = new byte[dis.readInt()];
dis.readFully(encryptedKeyBytes);
// Decrypt the session key bytes.
rsaCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] rijndaelKeyBytes = rsaCipher.doFinal(encryptedKeyBytes);
// Transform the key bytes into an actual key.
SecretKey rijndaelKey = new SecretKeySpec(rijndaelKeyBytes, "Rijndael");
// Read in the Initialization Vector from the file.
byte[] iv = new byte[16];
dis.read(iv);
IvParameterSpec spec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, rijndaelKey, spec);
CipherInputStream cis = new CipherInputStream(dis, cipher);
System.out.println("Decrypting the file...");
FileOutputStream fos = new FileOutputStream(fileInput + DECRYPTED_FILENAME_SUFFIX);
// Read through the file, decrypting each byte.
theByte = 0;
while ((theByte = cis.read()) != -1)
{
fos.write(theByte);
}
cis.close();
fos.close();
System.out.println("Done.");
return;
}
/**
* Utility method to encrypt a byte array with a given password.
* Salt will be the first 8 bytes of the byte array returned.
*/
private static byte[] passwordEncrypt(char[] password, byte[] plaintext) throws Exception {
// Create the salt.
byte[] salt = new byte[8];
Random random = new Random();
random.nextBytes(salt);
// Create a PBE key and cipher.
PBEKeySpec keySpec = new PBEKeySpec(password);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC");
SecretKey key = keyFactory.generateSecret(keySpec);
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);
Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");
cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
// Encrypt the array
byte[] ciphertext = cipher.doFinal(plaintext);
// Write out the salt, then the ciphertext and return it.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(salt);
baos.write(ciphertext);
return baos.toByteArray();
}
/**
* Utility method to decrypt a byte array with a given password.
* Salt will be the first 8 bytes in the array passed in.
*/
private static byte[] passwordDecrypt(char[] password, byte[] ciphertext) throws Exception {
// Read in the salt.
byte[] salt = new byte[8];
ByteArrayInputStream bais = new ByteArrayInputStream(ciphertext);
bais.read(salt,0,8);
// The remaining bytes are the actual ciphertext.
byte[] remainingCiphertext = new byte[ciphertext.length-8];
bais.read(remainingCiphertext,0,ciphertext.length-8);
// Create a PBE cipher to decrypt the byte array.
PBEKeySpec keySpec = new PBEKeySpec(password);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithSHAAndTwofish-CBC");
SecretKey key = keyFactory.generateSecret(keySpec);
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATIONS);
Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");
// Perform the actual decryption.
cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
return cipher.doFinal(remainingCiphertext);
}
}
EDIT:
You will require to change Java policy of you JVM to Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction for using this code.
All related information regarding change in JAVA Policy can be found HERE
Here is a good example:
http://javadigest.wordpress.com/2012/08/26/rsa-encryption-example/
and there are many more. (Google for "java encrypt RSA example" if this link breaks.)
I can't seem to find an answer that actually works
Try the one linked above. If it doesn't work, please follow up with an edit or comment to say what is going wrong.
I can't imagine that there isn't some simple function to do such a trivial thing. :P
Well sorry, but your imagination must be broken :-)
In fact, it is not a trivial thing. And it is made more difficult by the fact that Java is trying to support a wide range of crypto functionality and crypto technology stacks using a single unified API.
I have a file which is encrypted in .Net. I have to decrypt that file in java.
I have key and IV in text file. This file in encrypted using AES, CBC and PKCS7.
I was trying to do that using following code.
Can any one please help me ?
File file = new File("myFile.txt");
String key = readFile(new File("AESKey.bin"));
String iv = readFile(new File("AESIV.bin"));
final byte[] secretKey = key.getBytes();
final byte[] initVector = iv.getBytes();
InputStream cipherInputStream = null;
final StringBuilder output = new StringBuilder();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secretKey, "AES"), new
IvParameterSpec(initVector, 0, cipher.getBlockSize()));
cipherInputStream = new CipherInputStream(new FileInputStream(file), cipher);
final byte[] buffer = new byte[8192];
int read = cipherInputStream.read(buffer);
final String charsetName = "UTF-8";
while (read > -1) {
output.append(new String(buffer, 0, read, charsetName));
read = cipherInputStream.read(buffer);
}
System.out.println(output);*
It is giving exception -
Exception in thread "main" java.security.NoSuchAlgorithmException: Cannot find any provider
supporting AES/CBC/PKCS7Padding.
Can any one help me please ?
I suggest you try to instantiate the cipher
AES/CBC/PKCS5Padding
which is
a) supported on the JDK;
b) identical in effect to PKSCS7 padding.
I am writing a program which employs RSA in Android. I have the following problem:
I am getting the RSA keys:
KeyPair kp = kpg.genKeyPair();
publicKey = kp.getPublic();
privateKey = kp.getPrivate();
Using the encryption function to encrypt a test string:
String test ="test";
byte[] testbytes = test.getBytes();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherData = cipher.doFinal(testbytes);
String s = new String(cipherData);
Log.d("testbytes after encryption",s);
In the decryption function i am decrypting the data back to get the original string
Cipher cipher2 = Cipher.getInstance("RSA");
cipher2.init(Cipher.DECRYPT_MODE, privateKey);
byte[] plainData = cipher.doFinal(cipherData);
String p = new String(plainData);
Log.d("decrypted data is:",p);
The data in 'p' printed out in the log does not match the original string "test" . Where am I going wrong in this?
Here an example on how to do it, BUT in practice,
You can't really encrypt and decrypt whole files with just RSA. The
RSA algorithm can only encrypt a single block, and it is rather slow
for doing a whole file.
You can encrypt the file using
3DES or AES, and then encrypt the AES key using intended recipient's
RSA public key.
Some code:
public static void main(String[] args) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
kpg.initialize(1024);
KeyPair keyPair = kpg.generateKeyPair();
PrivateKey privKey = keyPair.getPrivate();
PublicKey pubKey = keyPair.getPublic();
// Encrypt
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String test = "My test string";
String ciphertextFile = "ciphertextRSA.txt";
InputStream fis = new ByteArrayInputStream(test.getBytes("UTF-8"));
FileOutputStream fos = new FileOutputStream(ciphertextFile);
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
byte[] block = new byte[32];
int i;
while ((i = fis.read(block)) != -1) {
cos.write(block, 0, i);
}
cos.close();
// Decrypt
String cleartextAgainFile = "cleartextAgainRSA.txt";
cipher.init(Cipher.DECRYPT_MODE, privKey);
fis = new FileInputStream(ciphertextFile);
CipherInputStream cis = new CipherInputStream(fis, cipher);
fos = new FileOutputStream(cleartextAgainFile);
while ((i = cis.read(block)) != -1) {
fos.write(block, 0, i);
}
fos.close();
}