Android Open Source - java_mega_api Mega Crypto






From Project

Back to project page java_mega_api.

License

The source code is released under:

GNU General Public License

If you think the Android project java_mega_api listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*******************************************************************************
 * Copyright (c) 2013 Dan Brough dan@danbrough.org. All rights reserved. 
 * This program and the accompanying materials are made available under the 
 * terms of the GNU Public License v3.0 which accompanies this distribution, 
 * and is available at http://www.gnu.org/licenses/gpl.html
 * // w  w  w  .j  a v  a 2 s  .com
 ******************************************************************************/
package org.danbrough.mega;

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.Random;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonWriter;

public class MegaCrypto {
  public static final String ISO_8859_1 = "ISO-8859-1";

  public static final int SYMM_CIPHER_KEY_LENGTH = 16;
  public static final int ASYMM_CIPHER_MAX_LENGTH = 1024;

  private static final MegaCrypto INSTANCE = new MegaCrypto();

  public static MegaCrypto get() {
    return INSTANCE;
  }

  Random random = new Random(System.currentTimeMillis());

  public String decrypt_attrs(String attrs, byte key[]) {

    try {
      byte data[] = createCipher(key, Cipher.DECRYPT_MODE).doFinal(
          base64urldecode(attrs));
      attrs = new String(data, ISO_8859_1);

      int i = attrs.indexOf(0);
      if (i > -1) {
        attrs = attrs.substring(0, i);
      }
      return attrs;
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

  }

  public int randInt(int max) {
    return random.nextInt(max);
  }

  public String encrypt_attrs(String attrs, byte key[]) {
    attrs = "MEGA{" + attrs;

    for (int i = 0; i < 16 - attrs.length() % 16; i++) {
      attrs = attrs + '\0';
    }
    Cipher cipher = createCipher(key, Cipher.ENCRYPT_MODE);

    try {
      byte[] data = cipher.doFinal(attrs.getBytes());
      return base64urlencode(data);
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public byte[] a32_to_bytes(int a[]) {

    byte b[] = new byte[a.length * 4];

    for (int i = 0; i < a.length * 4; i++)
      b[i] = (byte) ((a[i >> 2] >>> (24 - (i & 3) * 8)) & 255);
    return b;
  }

  public String bigToString(BigInteger b) {
    String hex = toHex(b.toByteArray());
    if (hex.startsWith("00"))
      hex = hex.substring(2);
    // if (hex.length() % 4 != 0)
    // hex = "00" + hex;
    return hex;
  }

  public int[] bytes_to_a32(byte b[]) {
    int a[] = new int[(b.length + 3) >> 2];
    for (int i = 0; i < b.length; i++) {
      a[i >> 2] |= ((0x000000ff & b[i]) << (24 - (i & 3) * 8));
    }
    return a;
  }

  public String stringhash(String s, byte key[]) {

    Cipher c = createCipher(key, Cipher.ENCRYPT_MODE);

    int s32[] = null;
    try {
      s32 = bytes_to_a32(s.getBytes(ISO_8859_1));
    } catch (UnsupportedEncodingException e1) {
      e1.printStackTrace();
    }

    int h32[] = { 0, 0, 0, 0 };

    for (int i = 0; i < s32.length; i++)
      h32[i & 3] ^= s32[i];

    for (int i = 0; i < 16384; i++) {
      try {
        h32 = bytes_to_a32(c.doFinal(a32_to_bytes(h32)));
      } catch (Exception e) {
        e.printStackTrace();
        return null;
      }
    }
    return base64urlencode(a32_to_bytes(new int[] { h32[0], h32[2] }));
  }

  public String base64urlencode(byte[] data) {
    return Base64.encodeToString(data, Base64.NO_WRAP | Base64.URL_SAFE
        | Base64.NO_PADDING);
  }

  public byte[] base64urldecode(String data) {
    return Base64.decode(data, Base64.NO_WRAP | Base64.URL_SAFE
        | Base64.NO_PADDING);
  }

  public int[] aes_cbc_encrypt_a32(int data[], int key[]) {
    return bytes_to_a32(aes_cbc_encrypt(a32_to_bytes(key), a32_to_bytes(data)));
  }

  public int[] aes_cbc_decrypt_a32(int data[], int key[]) {
    return bytes_to_a32(aes_cbc_decrypt(a32_to_bytes(key), a32_to_bytes(data)));
  }

  public byte[] aes_cbc_encrypt(byte key[], byte[] data) {
    try {
      return createCipher(key, Cipher.ENCRYPT_MODE).doFinal(data);
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public byte[] aes_cbc_decrypt(byte key[], byte[] data) {
    try {
      return createCipher(key, Cipher.DECRYPT_MODE).doFinal(data);
    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  // public byte[] prepareKeyOld(String password) {
  // try {
  // return a32_to_bytes(prepare_keyOld(bytes_to_a32(password
  // .getBytes(ISO_8859_1))));
  // } catch (UnsupportedEncodingException e) {
  // e.printStackTrace();
  // return null;
  // }
  // }

  public byte[] prepareKey(String password) {
    try {
      return prepare_key(password.getBytes(ISO_8859_1));
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  //
  // public int[] prepare_keyOld(int a[]) {
  //
  // Cipher aes[] = new Cipher[a.length / 4 + (a.length % 4 == 0 ? 0 : 1)];
  // int pkey[] = { 0x93C467E3, 0x7DB0C7A4, 0xD1BE3F81, 0x0152CB56 };
  // int k = 0;
  //
  // for (int j = 0; j < a.length; j += 4) {
  // int key[] = { 0, 0, 0, 0 };
  // for (int i = 0; i < 4; i++)
  // if (i + j < a.length)
  // key[i] = a[i + j];
  //
  // aes[k++] = createCipher(a32_to_bytes(key), Cipher.ENCRYPT_MODE);
  // }
  //
  // for (int r = 0; r < 65536; r++) {
  // for (int j = 0; j < aes.length; j++) {
  // try {
  // pkey = bytes_to_a32(aes[j].doFinal(a32_to_bytes(pkey)));
  // } catch (IllegalBlockSizeException e) {
  // e.printStackTrace();
  // } catch (BadPaddingException e) {
  // e.printStackTrace();
  // }
  // }
  // }
  // return pkey;
  //
  // }

  private static final byte[] MEGA_KEY = { -109, -60, 103, -29, 125, -80, -57,
      -92, -47, -66, 63, -127, 1, 82, -53, 86 };

  public byte[] prepare_key(byte a[]) {

    Cipher aes[] = new Cipher[a.length / 16 + (a.length % 16 == 0 ? 0 : 1)];
    byte pkey[] = MEGA_KEY;
    int k = 0;

    for (int j = 0; j < a.length; j += 16) {
      byte key[] = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
      for (int i = 0; i < 16; i++)
        if (i + j < a.length)
          key[i] = a[i + j];

      aes[k++] = createCipher(key, Cipher.ENCRYPT_MODE);
    }

    for (int r = 0; r < 65536; r++) {
      for (int j = 0; j < aes.length; j++) {
        try {
          pkey = aes[j].doFinal(pkey);
        } catch (IllegalBlockSizeException e) {
          e.printStackTrace();
        } catch (BadPaddingException e) {
          e.printStackTrace();
        }
      }
    }
    return pkey;

  }

  public String toHex(byte[] buf) {
    if (buf == null)
      return "";
    StringBuffer result = new StringBuffer(2 * buf.length);
    for (int i = 0; i < buf.length; i++) {
      appendHex(result, buf[i]);
    }
    return result.toString();
  }

  private final String HEX = "0123456789abcdef";

  public void appendHex(StringBuffer sb, byte b) {
    sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
  }

  public byte[] fromHex(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
      data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character
          .digit(s.charAt(i + 1), 16));
    }
    return data;
  }

  public Cipher createCipher(byte key[], int mode) {
    return createCipher("AES/CBC/NOPADDING", key, mode, new byte[] { 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
  }

  public Cipher createCipherCTR(byte key[], int mode, byte iv[]) {
    try {

      IvParameterSpec ivSpec = new IvParameterSpec(iv);

      SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
      Cipher cipher = Cipher.getInstance("AES/CTR/NOPADDING");
      cipher.init(mode, keySpec, ivSpec);
      return cipher;

    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

  }

  public Cipher createCipher(String transformation, byte key[], int mode,
      byte iv[]) {
    try {

      IvParameterSpec ivSpec = new IvParameterSpec(iv);

      SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
      Cipher cipher = Cipher.getInstance(transformation);
      cipher.init(mode, keySpec, ivSpec);
      return cipher;

    } catch (RuntimeException e) {
      throw e;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  // public String crypto_handleauth(String h, UserContext ctx) {
  // // return a32_to_base64(encrypt_key(u_k_aes,str_to_a32(h+h)));
  //
  // try {
  // return base64urlencode(enccrypt_key((h + h).getBytes(ISO_8859_1),
  // ctx.getMasterKey()));
  // } catch (UnsupportedEncodingException e) {
  // e.printStackTrace();
  // return null;
  // }
  // }

  // return a big int from bytes, (excluding the first 2 which are a length
  // prefix)
  public BigInteger mpi2big(byte b[]) throws IOException {
    byte bb[] = new byte[b.length - 2];
    System.arraycopy(b, 2, bb, 0, bb.length);

    return new BigInteger(toHex(bb), 16);
  }

  private byte[] process_key(byte a[], byte key[], int mode) {
    byte result[] = new byte[a.length];
    Cipher cipher = createCipher(key, mode);
    for (int i = 0; i < a.length; i += 16) {
      byte copy[] = new byte[16];
      System.arraycopy(a, i, copy, 0, 16);
      try {
        byte part[] = cipher.doFinal(a, i, 16);
        System.arraycopy(part, 0, result, i, 16);
      } catch (Exception e) {
        e.printStackTrace();
        return new byte[] {};
      }
    }
    return result;
  }

  public byte[] decrypt_key(byte a[], byte key[]) {
    return process_key(a, key, Cipher.DECRYPT_MODE);
  }

  public byte[] enccrypt_key(byte a[], byte key[]) {
    return process_key(a, key, Cipher.ENCRYPT_MODE);
  }

  public BigInteger rsaDecrypt(BigInteger m, BigInteger d, BigInteger p,
      BigInteger q, BigInteger u) {

    BigInteger xp = m.mod(p).modPow(d.mod(p.subtract(BigInteger.ONE)), p);

    BigInteger xq = m.mod(q).modPow(d.mod(q.subtract(BigInteger.ONE)), q);

    BigInteger t = xq.subtract(xq);

    if (t.equals(BigInteger.ZERO)) {

      t = xp.subtract(xq);
      t = t.multiply(u).mod(q);

      t = q.subtract(t);
    } else {
      t = t.multiply(u).mod(q);
    }

    return t.multiply(p).add(xp);
  }

  public String toPrettyString(JsonElement o) {

    StringWriter out = new StringWriter();
    JsonWriter writer = new JsonWriter(out);
    writer.setIndent(" ");
    writer.setLenient(true);
    try {
      Streams.write(o, writer);
    } catch (IOException e) {
      e.printStackTrace();
    }
    return out.toString();
  }

  public JsonElement toJSON(Object o) {
    return new Gson().toJsonTree(o);
  }

  public <T> T fromJSON(JsonObject o, Class<T> cls) {
    return new Gson().fromJson(o, cls);
  }

  public <T> T fromJSON(Reader input, Class<T> cls) {
    return new Gson().fromJson(input, cls);
  }

  // ul_aes = new sjcl.cipher.aes([ul_key[0],ul_key[1],ul_key[2],ul_key[3]]);
  // for (var p in ul_plainq)
  // {
  // ul_macs[p] = encrypt_ab_ctr(ul_aes,ul_plainq[p],[ul_key[4],ul_key[5]],p);
  //
  // ul_sendchunks[p] = ul_plainq[p];
  //
  // delete ul_plainq[p];
  // }

  public byte[] encrypt_ab_ctr(Cipher aes, byte ab[], byte nonce[], int pos) {
    return null;
  }

  // //encrypt ArrayBuffer in CTR mode, return MAC
  // function encrypt_ab_ctr(aes,ab,nonce,pos)
  // {
  // var ctr = [nonce[0],nonce[1],(pos/0x1000000000) >>> 0,(pos/0x10) >>> 0];
  // var mac = [ctr[0],ctr[1],ctr[0],ctr[1]];
  //
  // var enc, i, j, len, v;
  //
  // if (have_ab)
  // {
  // var data0, data1, data2, data3;
  //
  // len = ab.buffer.byteLength-16;
  //
  // var v = new DataView(ab.buffer);
  //
  // for (i = 0; i < len; i += 16)
  // {
  // data0 = v.getUint32(i,false);
  // data1 = v.getUint32(i+4,false);
  // data2 = v.getUint32(i+8,false);
  // data3 = v.getUint32(i+12,false);
  //
  // // compute MAC
  // mac[0] ^= data0;
  // mac[1] ^= data1;
  // mac[2] ^= data2;
  // mac[3] ^= data3;
  // mac = aes.encrypt(mac);
  //
  // // encrypt using CTR
  // enc = aes.encrypt(ctr);
  // v.setUint32(i,data0 ^ enc[0],false);
  // v.setUint32(i+4,data1 ^ enc[1],false);
  // v.setUint32(i+8,data2 ^ enc[2],false);
  // v.setUint32(i+12,data3 ^ enc[3],false);
  //
  // if (!(++ctr[3])) ctr[2]++;
  // }
  //
  // if (i < ab.buffer.byteLength)
  // {
  // var fullbuf = new Uint8Array(ab.buffer);
  // var tmpbuf = new ArrayBuffer(16);
  // var tmparray = new Uint8Array(tmpbuf);
  //
  // tmparray.set(fullbuf.subarray(i));
  //
  // v = new DataView(tmpbuf);
  //
  // enc = aes.encrypt(ctr);
  //
  // data0 = v.getUint32(0,false);
  // data1 = v.getUint32(4,false);
  // data2 = v.getUint32(8,false);
  // data3 = v.getUint32(12,false);
  //
  // mac[0] ^= data0;
  // mac[1] ^= data1;
  // mac[2] ^= data2;
  // mac[3] ^= data3;
  // mac = aes.encrypt(mac);
  //
  // enc = aes.encrypt(ctr);
  // v.setUint32(0,data0 ^ enc[0],false);
  // v.setUint32(4,data1 ^ enc[1],false);
  // v.setUint32(8,data2 ^ enc[2],false);
  // v.setUint32(12,data3 ^ enc[3],false);
  //
  // fullbuf.set(tmparray.subarray(0,j = fullbuf.length-i),i);
  // }
  // }
  // else
  // {
  // var ab32 = _str_to_a32(ab.buffer);
  //
  // len = ab32.length-3;
  //
  // for (i = 0; i < len; i += 4)
  // {
  // mac[0] ^= ab32[i];
  // mac[1] ^= ab32[i+1];
  // mac[2] ^= ab32[i+2];
  // mac[3] ^= ab32[i+3];
  // mac = aes.encrypt(mac);
  //
  // enc = aes.encrypt(ctr);
  // ab32[i] ^= enc[0];
  // ab32[i+1] ^= enc[1];
  // ab32[i+2] ^= enc[2];
  // ab32[i+3] ^= enc[3];
  //
  // if (!(++ctr[3])) ctr[2]++;
  // }
  //
  // if (i < ab32.length)
  // {
  // var v = [0,0,0,0];
  //
  // for (j = i; j < ab32.length; j++) v[j-i] = ab32[j];
  //
  // mac[0] ^= v[0];
  // mac[1] ^= v[1];
  // mac[2] ^= v[2];
  // mac[3] ^= v[3];
  // mac = aes.encrypt(mac);
  //
  // enc = aes.encrypt(ctr);
  // v[0] ^= enc[0];
  // v[1] ^= enc[1];
  // v[2] ^= enc[2];
  // v[3] ^= enc[3];
  //
  // for (j = i; j < ab32.length; j++) ab32[j] = v[j-i];
  // }
  //
  // ab.buffer = _a32_to_str(ab32,ab.buffer.length);
  // }
  //
  // return mac;
  // }
}




Java Source Code List

org.danbrough.mega.APIError.java
org.danbrough.mega.AccountDetails.java
org.danbrough.mega.AndroidClient.java
org.danbrough.mega.Base64.java
org.danbrough.mega.Callback.java
org.danbrough.mega.CommandFetchNodes.java
org.danbrough.mega.CommandGetFile.java
org.danbrough.mega.CommandGetUserQuota.java
org.danbrough.mega.CommandLogin.java
org.danbrough.mega.CommandPutFile.java
org.danbrough.mega.Command.java
org.danbrough.mega.ExecutorThreadPool.java
org.danbrough.mega.GSONUtil.java
org.danbrough.mega.MegaActivity.java
org.danbrough.mega.MegaApplication.java
org.danbrough.mega.MegaClient.java
org.danbrough.mega.MegaCrypto.java
org.danbrough.mega.MegaFragmentActivity.java
org.danbrough.mega.MegaListener.java
org.danbrough.mega.Node.java
org.danbrough.mega.ThreadPool.java
org.danbrough.mega.User.java
org.danbrough.mega.ui.FilesAdapter.java
org.danbrough.mega.ui.FilesFragment.java
org.danbrough.megatest.MainActivity.java