Decrypting Data On Desktop That Was Encrypted On Android
Solution 1:
I have finally found the whole solution.
There were some major issues, and I would like to explain them here so that more users can find the answer. Firstly, the two things pointed out by Duncan needed to be fixed.
After fixing these issues I still had the same problem, and found out that using a pseudo random number to create the raw key is done differently by different platforms/OS'. If you want to have crossplatform independencies, don't use SHA1PRNG as your key algorithm. Instead, use PBEWithSHA256And256BitAES-CBC-BC. I am using the implementation from BouncyCastle, see below for full crypto code.
import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.security.spec.KeySpec;
import java.util.Random;
import javax.crypto.Cipher;
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;
publicclassSSL {
privatefinalstaticStringHEX="0123456789ABCDEF";
privatefinalstaticStringENC="US-ASCII";
privatefinalstaticintITERATION=1337;
privatestaticfinalStringRANDOM_ALGORITHM="PBEWithSHA256And256BitAES-CBC-BC";
privatestaticfinalStringCIPHER_ALGORITHM="AES/CBC/PKCS5Padding";
privatestaticfinalStringSECRET_KEY_ALGORITHM="AES";
privatestatic IvParameterSpec ips;
publicstaticvoidinit(byte[] iv) {
if(iv == null) {
iv = newbyte[16];
Randomrandom=newRandom();
random.nextBytes(iv);
}
ips = newIvParameterSpec(iv);
Security.addProvider(newBouncyCastleProvider());
}
publicstaticbyte[] getCertificate() {
return ips.getIV();
}
publicstatic String encrypt(Session current, String cleartext)throws Exception {
byte[] rawKey = getRawKey(current.getCurrentSession().toCharArray());
byte[] result = encrypt(rawKey, cleartext.getBytes(ENC));
return toHex(result);
}
publicstatic String decrypt(Session current, String encrypted)throws Exception {
byte[] rawKey = getRawKey(current.getCurrentSession().toCharArray());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
returnnewString(result, ENC);
}
privatestaticbyte[] getRawKey(char[] seed) throws Exception {
KeySpeckeySpec=newPBEKeySpec(seed, ips.getIV(), ITERATION);
SecretKeyFactorykeyFactory= SecretKeyFactory.getInstance(RANDOM_ALGORITHM);
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
SecretKeysecretKey=newSecretKeySpec(keyBytes, "AES");
return secretKey.getEncoded();
}
privatestaticbyte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpecskeySpec=newSecretKeySpec(raw, SECRET_KEY_ALGORITHM);
Ciphercipher= Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ips);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
privatestaticbyte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpecskeySpec=newSecretKeySpec(raw, SECRET_KEY_ALGORITHM);
Ciphercipher= Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ips);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
publicstatic String toHex(String txt)throws UnsupportedEncodingException {
return toHex(txt.getBytes(ENC));
}
publicstatic String fromHex(String hex)throws UnsupportedEncodingException {
returnnewString(toByte(hex), ENC);
}
publicstaticbyte[] toByte(String hexString) {
intlen= hexString.length()/2;
byte[] result = newbyte[len];
for (inti=0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
publicstatic String toHex(byte[] buf) {
if (buf == null)
return"";
StringBufferresult=newStringBuffer(2*buf.length);
for (inti=0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
privatestaticvoidappendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
}
Solution 2:
There are at least two problems with your code that will affect its functionality on different platforms:
You must specify a character set when calling
getBytes()
ornew String(...)
. Without this, the results will be different if your platforms have different default charsets.You must fully specify your encryption algorithm, e.g. replace
"AES"
with"AES/CBC/PKCS5Padding"
to avoid differences between providers.
Post a Comment for "Decrypting Data On Desktop That Was Encrypted On Android"