Skip to content Skip to sidebar Skip to footer

Decrypting Data On Desktop That Was Encrypted On Android

I have an app which encrypts some text strings, and then writes these to a file. The desktop version of the app is reading the file and decrypts the data. The problem is that whene

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:

  1. You must specify a character set when calling getBytes() or new String(...). Without this, the results will be different if your platforms have different default charsets.

  2. 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"