I am trying to encrypt and decrypt a String using jks Keystore file.But while decryption i am getting following error...
Here is my class for encryption and decryption :
package com.Encrypt;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableEntryException;
import java.security.UnrecoverableKeyException;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;
public class Encrypt {
public String encyptCard(String card) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnrecoverableKeyException{
FileInputStream is = new FileInputStream("C:/Users/admin/Desktop/keystore/ksjksformat.jks");
String keystpassw = "9801461740";
String alias = "ksjksformat";
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(is,keystpassw.toCharArray() );
Certificate cert = ks.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherData = cipher.doFinal(card.getBytes());
String cipherData1 = Base64.encodeBase64String(cipherData);
return cipherData1;
}
public String decrypte (String encCardNo) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableEntryException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
FileInputStream is = new FileInputStream("C:/Users/admin/Desktop/keystore/ksjksformat.jks");
String keystpassw = "9801461740";
String alias = "ksjksformat";
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(is,keystpassw.toCharArray() );
Key key = ks.getKey(alias, keystpassw.toCharArray());
Certificate cert = ks.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
new KeyPair(publicKey, (PrivateKey) (key));
KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(keystpassw.toCharArray());
KeyStore.PrivateKeyEntry pkentry = (PrivateKeyEntry) ks.getEntry(alias, protParam);
PrivateKey myPrivateKey =pkentry.getPrivateKey();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, myPrivateKey);
byte[] cipherData = cipher.doFinal(encCardNo.getBytes());
String decrypted =Base64.decodeBase64(cipherData).toString();
return decrypted;
}
}
Here is my class where i am calling these methods : -
package com.Encrypt;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class CryptoHelper {
public static void main(String[] argv) throws InvalidKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException, UnrecoverableEntryException {
Encrypt obj = new Encrypt();
String answerEnc = obj.encyptCard("student");
System.out.println("encrypted data----------->"+answerEnc);
String Orginial_data = obj.decrypte(answerEnc);
System.out.println("Decrypted data-------->"+Orginial_data);
}
}
now i am getting this error : -
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at com.Encrypt.Encrypt.decrypte(Encrypt.java:56)
at com.Encrypt.CryptoHelper.main(CryptoHelper.java:17)
This error is while decryption at line
byte[] cipherData = cipher.doFinal(encCardNo.getBytes());
in public String decrypte (String encCardNo) method. Please explain how can I resolve this one.
#Maarten Bodewes answer is correct we have to decode before decryption ..
Thanks #Maarten BodewesHere is the code for decryption method which is returning correct output. `
public String decrypte (String encCardNo) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableEntryException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
FileInputStream is = new FileInputStream("C:/Users/admin/Desktop/keystore/ksjksformat.jks");
String keystpassw = "9801461740";
String alias = "ksjksformat";
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(is,keystpassw.toCharArray() );
Key key = ks.getKey(alias, keystpassw.toCharArray());
Certificate cert = ks.getCertificate(alias);
PublicKey publicKey = cert.getPublicKey();
new KeyPair(publicKey, (PrivateKey) (key));
KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(keystpassw.toCharArray());
KeyStore.PrivateKeyEntry pkentry = (PrivateKeyEntry) ks.getEntry(alias, protParam);
PrivateKey myPrivateKey =pkentry.getPrivateKey();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, myPrivateKey);
byte[] decoded = Base64.decodeBase64(encCardNo);
byte[] cipherData = cipher.doFinal(decoded);
return new String(cipherData);
}`
You need to decode before decrypting, not after.
As a special service for accepting my answer while posting your own, a bit of a rewrite of decrypte:
public String decrypte(final String encCardNo) throws IllegalBlockSizeException,
BadPaddingException {
// --- setup (should be stored differently)
final char[] keystpassw = "9801461740".toCharArray();
final String alias = "ksjksformat";
// --- retrieve private key from store
final PrivateKey key;
try (final FileInputStream is = new FileInputStream(
"C:/Users/admin/Desktop/keystore/ksjksformat.jks")) {
final KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(is, keystpassw);
key = (PrivateKey) ks.getKey(alias, keystpassw);
} catch (final KeyStoreException | IOException | NoSuchAlgorithmException | UnrecoverableKeyException | CertificateException e) {
throw new IllegalStateException("Could not load key from key store", e);
}
// --- initialize cipher
final Cipher cipher;
try {
// should use OAEP instead
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
} catch (final NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new IllegalStateException(
"RSA PKCS v1.5 should always be available", e);
} catch (final InvalidKeyException e) {
throw new IllegalStateException("Key is not an RSA private key", e);
}
// --- decode
final byte[] decoded;
try {
decoded = Base64.getDecoder().decode(encCardNo);
} catch (final IllegalArgumentException e) {
throw new IllegalArgumentException("Invalid encoded ciphertext", e);
}
// --- decrypt
final byte[] cipherData = cipher.doFinal(decoded);
final String cardNo = new String(cipherData, StandardCharsets.US_ASCII);
// --- clean up
try {
key.destroy();
} catch (final DestroyFailedException e) {
// we tried, possibly log this
}
Arrays.fill(cipherData, (byte) 0);
return cardNo;
}
Related
I am trying to encrypt and decrypt a symmetric key file (256 and 128) using RSAES - OAEP but I am getting error while encrypting :
File Sizes to encrypt: 256 and 128
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import java.util.Arrays;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
public static void main(String[] args) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.generateKeyPair();
String inputPath = "/home/roxane/Music/test_09";
String inFile = "/home/roxane/Downloads/s_key";
String encfile = "/home/roxane/Music/s_key.enc";
// get key pair
PublicKey pub = kp.getPublic();
PrivateKey PrivateKey = kp.getPrivate();
// Write Key Pair
try (FileOutputStream out = new FileOutputStream(inputPath + ".key")) {
out.write(kp.getPrivate().getEncoded());
}
try (FileOutputStream out = new FileOutputStream(inputPath + ".pub")) {
out.write(kp.getPublic().getEncoded());
}
//restore kEys
byte[] pubbytes = Files.readAllBytes(Paths.get(inputPath + ".pub"));
X509EncodedKeySpec ks = new X509EncodedKeySpec(pubbytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pub1 = kf.generatePublic(ks);
byte[] privbytes = Files.readAllBytes(Paths.get(inputPath + ".key"));
PKCS8EncodedKeySpec ks1 = new PKCS8EncodedKeySpec(privbytes);
KeyFactory kf1 = KeyFactory.getInstance("RSA");
PrivateKey pvt = kf1.generatePrivate(ks1);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-512ANDMGF1PADDING");
cipher.init(Cipher.ENCRYPT_MODE, pvt);
try (FileInputStream in = new FileInputStream(inFile);
FileOutputStream out = new FileOutputStream(encfile)) {
processFile(cipher, in, out);
}
}
static private void processFile(Cipher ci,InputStream in,OutputStream out)
throws javax.crypto.IllegalBlockSizeException,
javax.crypto.BadPaddingException,
java.io.IOException
{
byte[] ibuf = new byte[1024];
int len;
while ((len = in.read(ibuf)) != -1) {
byte[] obuf = ci.update(ibuf, 0, len);
if ( obuf != null ) out.write(obuf);
}
byte[] obuf = ci.doFinal();
if ( obuf != null ) out.write(obuf);
}
Error: Exception in thread "main" java.security.InvalidKeyException: OAEP cannot be used to sign or verify signatures
Requesting help in the code encrytption and decryption of the files compatible with openssl. I am open to use bouncycastle if required
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I want to rewrite the following code from java to golang.
Here mostly I am looking for a function which can work same as byte[] cipheredBytes = Base64.getDecoder().decode((encryptedText));
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESBase64UsedForPartners {
private final String characterEncoding = "UTF-8";
private final String cipherTransformation = "AES/CBC/PKCS5Padding";
private final String aesEncryptionAlgorithm = "AES";
static String SecretKey = "$sgettng#&Key%";
public String encrypt(String plainText) throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
byte[] plainTextbytes = plainText.getBytes(characterEncoding);
byte[] keyBytes = getKeyBytes(SecretKey);
byte[] str = Base64.getEncoder().encode(encrypt(plainTextbytes, keyBytes, keyBytes));
return new String(str);
}
public byte[] encrypt(byte[] plainText, byte[] key, byte[] initialVector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance(cipherTransformation);
SecretKeySpec secretKeySpec = new SecretKeySpec(key, aesEncryptionAlgorithm);
IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
plainText = cipher.doFinal(plainText);
return plainText;
}
public String decrypt(String encryptedText) throws KeyException, GeneralSecurityException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException, IOException {
byte[] cipheredBytes = Base64.getDecoder().decode((encryptedText));
byte[] keyBytes = getKeyBytes(SecretKey);
return new String(decrypt(cipheredBytes, keyBytes, keyBytes), characterEncoding);
}
public byte[] decrypt(byte[] cipherText, byte[] key, byte[] initialVector) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance(cipherTransformation);
SecretKeySpec secretKeySpecy = new SecretKeySpec(key, aesEncryptionAlgorithm);
IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpecy, ivParameterSpec);
cipherText = cipher.doFinal(cipherText);
return cipherText;
}
private byte[] getKeyBytes(String key) throws UnsupportedEncodingException {
byte[] keyBytes = new byte[16];
byte[] parameterKeyBytes = key.getBytes(characterEncoding);
System.arraycopy(parameterKeyBytes, 0, keyBytes, 0, Math.min(parameterKeyBytes.length, keyBytes.length));
return keyBytes;
}
public static void main(String a[]) throws GeneralSecurityException, IOException {
String str = new AESBase64UsedForPartners().encrypt("Text");
System.out.println("Encrypted---->" + str);
System.out.println(new AESBase64UsedForPartners().decrypt(str));
}
}
You can use the encoding/base64 package for decoding Base64 encoded strings:
decoded, err := base64.StdEncoding.DecodeString(s)
I have an assignment to decrypt AES using Java but I keep getting a pad block corrupted error. I know this problem has been addressed in multiple threads everywhere but I still can't figure it out.
I have this information given to me:
key : 0123456789abcdef
IV: 0000000000000000
encrypted string: 1ff4ec7cef0e00d81b2d55a4bfdad4ba
which should give the string "Plain text" according to the assignment.
This is my code: (IVtest array is the same as KeyIvEncrypted but with hex instead)
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
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;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.crypto.BufferedBlockCipher;
import java.util.Base64;
public class AESdecryptor {
/*
private static String[] KeyIvEncrypted = new String[]{
"ABEiM0RVZneImaq7zN3u/w==",
"AAECAwQFBgcICQoLDA0ODw==",
"ZtrkahwcMzTu7e/WuJ3AZmF09DE="
};*/
public static String[] KeyIvEncrypted = new String[]{
new String("0123456789abcdef"),
new String("0000000000000000"),
new String("1ff4ec7cef0e00d81b2d55a4bfdad4ba")
};
public static byte[][] Ivtest = {{0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0x1,0xf,0xf,0x4,0xe,0xc,0x7,0xc,0xe,0xf,0x0,0xe,0x0,0x0,0xd,0x8,0x1,0xb,0x2,0xd,0x5,0x5,0xa,0x4,0xb,0xf,0xd,0xa,0xd,0x4,0xb,0xa}};
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidAlgorithmParameterException, UnsupportedEncodingException, InvalidKeySpecException{
Security.addProvider(new BouncyCastleProvider());
System.out.println(new String(decrypt(),"ISO-8859-1"));
}
private static byte[] transform(int mode, byte[] keyBytes, byte[] ivBytes, byte[] messageBytes) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidKeySpecException
{
final SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
final IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
final Cipher cipher = Cipher.getInstance("AES/CBC/pkcs7Padding");
cipher.init(mode, keySpec, ivSpec);
return cipher.doFinal(messageBytes);
}
public static byte[] decrypt() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException, InvalidAlgorithmParameterException, UnsupportedEncodingException, InvalidKeySpecException{
//return AESdecryptor.transform(Cipher.DECRYPT_MODE, Base64.getDecoder().decode(KeyIvEncrypted[0]), Base64.getDecoder().decode(KeyIvEncrypted[1]), Base64.getDecoder().decode(KeyIvEncrypted[2]));
return AESdecryptor.transform(Cipher.DECRYPT_MODE, Ivtest[0], Ivtest[1], Ivtest[2]);
}
}
OK, so I needed some time to reset my mind and I needed a puzzle. You are the lucky one.
The following code will solve your issue, I'll put the remarks below...
package so;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.util.encoders.Hex;
public class AESdecryptor {
public static String[] KeyIvEncrypted = new String[]{
new String("0123456789abcdef"),
new String("0000000000000000"),
new String("1ff4ec7cef0e00d81b2d55a4bfdad4ba")
};
public static void main(String[] args) throws GeneralSecurityException {
// Security.addProvider(new BouncyCastleProvider());
byte[] decrypted = decrypt();
System.out.println(new String(decrypted, StandardCharsets.ISO_8859_1));
}
private static byte[] transform(int mode, byte[] keyBytes, byte[] ivBytes, byte[] messageBytes)
throws GeneralSecurityException {
final SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
final IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(mode, keySpec, ivSpec);
return cipher.doFinal(messageBytes);
}
public static byte[] decrypt() throws GeneralSecurityException {
return AESdecryptor.transform(Cipher.DECRYPT_MODE, KeyIvEncrypted[0].getBytes(), KeyIvEncrypted[1].getBytes(), Hex.decode(KeyIvEncrypted[2]));
}
}
The following issues were found:
the key and IV are specified in (ASCII) text. Keys and IV's should not be encoded as text, as each byte should be equally possible;
the IV should not be static, but indistinguishable from random;
the IV is not a "zero" IV, as that would consist of bytes set to 0x00, not bytes set to the character '0', i.e. 0x30;
Bouncy Castle is not needed, PKCS#5 is identical to PKCS#7 when it comes to padding;
the ciphertext is encoded in hexadecimals, so you need to decode them using two hex digits grouped together to make one byte (I've used the Hex class from Bouncy as you already have that it seems).
And please note that encryption doesn't equal security even if performed correctly.
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class Encryption {
public static byte[] encrypted(String t) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException{
byte[] dataToSend = t.getBytes();
byte[] key = new byte[16];
Cipher c = Cipher.getInstance("AES");
SecretKeySpec k = new SecretKeySpec(key, "AES");
c.init(Cipher.ENCRYPT_MODE, k);
byte[] encryptedData = c.doFinal(dataToSend);
return encryptedData;
}
public static byte[] decrypted(byte[] kr) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException{
byte[] key = new byte[16];
SecretKeySpec k = new SecretKeySpec(key, "AES");
byte[] encryptedData = kr;
Cipher c2 = Cipher.getInstance("AES");
c2.init(Cipher.DECRYPT_MODE, k);
byte[] data = c2.doFinal(encryptedData);
return data;
}
public static void main(String args[]) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
//method1
System.out.println(encrypted("adsda"));
String f = new String (encrypted("adsda")); //working on console but not works when stores to cookies because of invalid characters
System.out.println(f);
System.out.println(new String(decrypted(f.getBytes())));// works when decrypting in console, not tried in cookies because not able encrypt
//method2
String x = encrypted("adsda").toString(); // works when stores in cookies works on console
System.out.println(x);
System.out.println(new String(decrypted(x.getBytes())));// decrypt not working both on console and cookies
System.out.println(decrypted(x.getBytes()).toString()); // decrypt not working both on console and cookies
}
}
I created a method to encrypt and decrypt cookies using AES. The details is the comment on the code.
You can't just convert the byte[] returned by encrypted(..) to a String. You need to use an encoding that do not lose data.
Use an encoding like Base64 or even a hex encoding.
I'm writing an application for Android that uses symmetric key encryption to protect sensitive data. As far as I can tell, Android only directly supports "PBEWithMD5AndDES". How secure is this algorithm? Also, I've included my code below (non-andriod). Is my code correctly encrypting the data?
import java.io.UnsupportedEncodingException;
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.InvalidParameterSpecException;
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 CipherTest
{
private static class EncryptInfo
{
private final byte[] encryptedData;
private final byte[] initVector;
private final byte[] salt;
public EncryptInfo(byte[] encryptedData, byte[] initVector, byte[] salt)
{
this.encryptedData = encryptedData.clone();
this.initVector = initVector.clone();
this.salt = salt.clone();
}
public byte[] getEncryptedData()
{
return encryptedData;
}
public byte[] getInitVector()
{
return initVector;
}
public byte[] getSalt()
{
return salt;
}
}
private static final String keyGenAlgorithm = "PBEWithMD5AndDES";
private static final String keyAlgorithm = "DES";
private static final String cipherTransform = "PBEWithMD5AndDES/CBC/PKCS5Padding";
private static EncryptInfo encrypt(char[] password, byte[] data)
throws NoSuchAlgorithmException, InvalidKeySpecException,
NoSuchPaddingException, InvalidKeyException,
InvalidParameterSpecException, IllegalBlockSizeException,
BadPaddingException, UnsupportedEncodingException
{
byte[] salt = new byte[16];
new SecureRandom().nextBytes(salt);
PBEKeySpec keySpec = new PBEKeySpec(password, salt, 1024);
SecretKeyFactory secretKeyFactory = SecretKeyFactory
.getInstance(keyGenAlgorithm);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
keySpec.clearPassword();
byte[] key = secretKey.getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, keyAlgorithm);
Cipher cipher = Cipher.getInstance(cipherTransform);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] initVector = cipher.getParameters().getParameterSpec(
IvParameterSpec.class).getIV();
return new EncryptInfo(cipher.doFinal(data), initVector, salt);
}
public static byte[] decrypt(byte[] data, char[] password, byte[] salt,
byte[] initVector) throws NoSuchAlgorithmException,
InvalidKeySpecException, NoSuchPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException
{
PBEKeySpec keySpec = new PBEKeySpec(password, salt, 1024);
SecretKeyFactory secretKeyFactory = SecretKeyFactory
.getInstance(keyGenAlgorithm);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
keySpec.clearPassword();
byte[] key = secretKey.getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, keyAlgorithm);
Cipher cipher = Cipher.getInstance(cipherTransform);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(
initVector));
return cipher.doFinal(data);
}
public static void main(String[] args) throws Exception
{
char[] password = "password".toCharArray();
EncryptInfo info = encrypt(password, "Message".getBytes());
byte[] decyptedText = decrypt(info.getEncryptedData(), password, info
.getSalt(), info.getInitVector());
System.out.println(new String(decyptedText));
}
}
Both MD5 and DES are weak. If your data being encrypted is really valuable, you should look for some external crypto library for Android that offers AES and SHA256/SHA512 algorithms.
If you want to encrypt data using a symmetric key encryption, I recommend:
1) Use AES, because it is certified by the NSA for data classified as secret.
2) Use a well reviewed implementation so you don't have to research the proper way to configure the code. For example, AESCrypt.
You can find AESCrypt here: http://www.aescrypt.com/java_aes_crypt.html
I've seen AESCrypt used in several financial institutions. AESCrypt for java is a single class that calls JCE methods. Android, JCE is implemented by bouncycastle. I have seen bouncycastle used in several major financial institutions.