
package com.battlelancer.seriesguide.util;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * Usage:
 * 
 * <pre>
 * String crypto = SimpleCrypto.encrypt(cleartext)
 * ...
 * String cleartext = SimpleCrypto.decrypt(crypto)
 * </pre>
 * 
 * @author ferenc.hechler, modified by Uwe Trottmann for SeriesGuide
 */
public class SimpleCrypto {

    private static final String KEY_SECURE = "com.battlelancer.seriesguide.secure";

    public static String encrypt(String cleartext, Context context) throws Exception {
        byte[] rawKey = getRawKey(context);
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
    }

    public static String decrypt(String encrypted, Context context) throws Exception {
        byte[] rawKey = getRawKey(context);
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    private static byte[] getRawKey(Context context) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        String seed = prefs.getString(KEY_SECURE, null);
        if (seed == null) {
            seed = toHex(sr.generateSeed(128));
            prefs.edit().putString(KEY_SECURE, seed).commit();
        } else {
            sr.setSeed(toByte(seed));
        }

        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }

    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    public static String toHex(String txt) {
        return toHex(txt.getBytes());
    }

    public static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    public static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
        return result;
    }

    public static String toHex(byte[] b) {
        String result = "";
        for (int i = 0; i < b.length; i++) {
            result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
        }
        return result;
    }

}

@@ -1478,36 +1478,78 @@
 ferences(context
+%0D%0A                .getApplicationContext()
 );%0D%0A
-
         String s
@@ -1586,24 +1586,51 @@
 RE, null);%0D%0A
+        byte%5B%5D seedBytes;%0D%0A
         if (
@@ -1666,17 +1666,16 @@
 seed
- = toHex(
+Bytes = 
 sr.g
@@ -1691,11 +1691,47 @@
 ed(1
-28)
+6);%0D%0A            seed = toHex(seedBytes
 );%0D%0A
@@ -1829,18 +1829,19 @@
    s
-r.setSeed(
+eedBytes = 
 toBy
@@ -1848,17 +1848,16 @@
 te(seed)
-)
 ;%0D%0A     
@@ -1857,24 +1857,56 @@
 %0D%0A        %7D%0D
+%0A        sr.setSeed(seedBytes);%0D
 %0A%0D%0A        k

Use a smaller seed, actually use a newly generated seed (fixes trakt credentials not working on first try).