Android Open Source - AndroidWallet Blobvault






From Project

Back to project page AndroidWallet.

License

The source code is released under:

MIT License

If you think the Android project AndroidWallet 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

package com.ripple;
//from  w  ww.  j ava2  s. c o m
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
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.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.codehaus.jackson.map.ObjectMapper;
import org.json.JSONException;
import org.json.JSONObject;
import org.spongycastle.crypto.DataLengthException;
import org.spongycastle.crypto.InvalidCipherTextException;
import org.spongycastle.crypto.PBEParametersGenerator;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.engines.AESFastEngine;
import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.spongycastle.crypto.modes.CCMBlockCipher;
import org.spongycastle.crypto.params.CCMParameters;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.jcajce.provider.digest.SHA256.KeyGenerator;

import com.aurionx.wallet.GlobalState;
import com.aurionx.wallet.LoginActivity;
import com.aurionx.wallet.R;
import com.aurionx.wallet.WalletActivity;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.util.Base64;
import android.util.Log;

public class Blobvault {
  private LoginActivity login;
  private String key;
  
  public Blobvault (LoginActivity activity) {
    this.login = activity;
  }
  
  public Blobvault () {
  }
  
  public void importWallet (String name, String pass) {    
    String hash = this.hash(name.toLowerCase()+pass);
    String url  = login.getApplicationContext().getString(R.string.payward)+"/"+hash;
    key         = ""+name.length()+'|'+name.toLowerCase()+pass;  
    //System.out.println(url);
    if (NetworkUtil.getConnectivityStatus(login.getApplicationContext())==NetworkUtil.TYPE_NOT_CONNECTED) {
      login.showMessage("Network not connected.");
      return;
    } else {
      new GetWalletFromURL().execute(url);
    }
  }
  
  public String hash(String text) {
      MessageDigest digest;
      StringBuffer sb = new StringBuffer();
      
    try {
      digest = MessageDigest.getInstance("SHA-256");
        digest.reset();
        byte[] byteData = digest.digest(text.getBytes("UTF-8"));

        for (int i = 0; i < byteData.length; i++){
          sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }
        
        
    } catch (NoSuchAlgorithmException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      return null;
      
    } catch (UnsupportedEncodingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      return null;
    }
    
    return sb.toString();
  }
  
  private class GetWalletFromURL extends AsyncTask<String, String, String>{
  
    @Override
      protected String doInBackground(String... uri) {
          HttpClient httpclient = new DefaultHttpClient();
          HttpResponse response;
          String responseString = null;
  
          try {
              response = httpclient.execute(new HttpGet(uri[0]));
              StatusLine statusLine = response.getStatusLine();
              if(statusLine.getStatusCode() == HttpStatus.SC_OK){
                  ByteArrayOutputStream out = new ByteArrayOutputStream();
                  response.getEntity().writeTo(out);
                  out.close();
                  responseString = out.toString();
              } else{
                  //Closes the connection.
                  response.getEntity().getContent().close();
                  throw new IOException(statusLine.getReasonPhrase());
              }
          } catch (ClientProtocolException e) {
              //TODO Handle problems..
          } catch (IOException e) {
              //TODO Handle problems..
          }
          
          return responseString;
      }
  
      @Override
      protected void onPostExecute(String result) {
        JSONObject json;
        String data;
        
          super.onPostExecute(result);
          //Do anything with response..
          if (result == null) {
            login.showMessage("Unable to retrieve wallet.");
          } else if (result.length()>0) {
            //System.out.println(result);
            login.showMessage("wallet found. Decrypting wallet...");
            byte[] bytes = Base64.decode(result, Base64.DEFAULT);
            
        try {
          data = new String(bytes, "UTF-8");
          json = new JSONObject(data);
          //String adata = Uri.decode(json.getString("adata"));
          //json.put("adata", new JSONObject(adata));
          
          //System.out.println(json);

          JSONObject blob = decryptBlob (key, json);
          if (blob != null) {
            login.showMessage("Wallet decrypted.  Loading wallet...");
            login.setBlob(blob);
            
          } else {
            login.showMessage("Unable to decrypt wallet.");
          }
          
          return;
          
        } catch (JSONException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        
        login.showMessage("Unable to decode wallet.");
        
          } else {  
            login.showMessage("Login failed. Wallet name or passphrase is incorrect");
          }
      }
  }
  
  public JSONObject encryptBlob (String key, JSONObject blob) {
    JSONObject result   = new JSONObject();
    SecureRandom random = new SecureRandom();
    byte[] salt = Base64.encode("FSMRjkIkKiHReq5Pdjm863".getBytes(), Base64.DEFAULT);
    byte[] iv   = new byte[16];
    int ks      = 256;
    int iter    = 1000;
    int ts      = 64;
    
    random.nextBytes(iv);
    byte[] nonce = Arrays.copyOf(iv, 13); //truncate at 13 bytes
    
    KeyParameter keyParam = this.createKey(key, salt, iter, ks);  
    CCMParameters ccm = new CCMParameters(
                keyParam,
                ts/8-1, //not sure why but it works
                nonce,
                new byte [0]);
    
    CCMBlockCipher aes = new CCMBlockCipher(new AESFastEngine());
    aes.init(true, ccm);
    

    try {
      
      byte [] plainBytes = blob.toString().getBytes("UTF-8");
      byte [] enc        = new byte[aes.getOutputSize(plainBytes.length)];
      
      int res = aes.processBytes(
              plainBytes,
              0, 
              plainBytes.length, 
              enc, 
              0);
      
      aes.doFinal(enc, res);
          
          result.put("ct",    Base64.encodeToString(enc, Base64.DEFAULT));
          result.put("iv",    Base64.encodeToString(iv, Base64.DEFAULT));
          result.put("salt",  Base64.encodeToString(salt, Base64.DEFAULT));
          result.put("adata", Base64.encodeToString("[]".getBytes(), Base64.DEFAULT));
          result.put("ks",   ks);
          result.put("iter", iter);
          result.put("ts",   ts);
          
          //System.out.println(result);
          return result;
      
    } catch (IllegalStateException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InvalidCipherTextException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (JSONException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    
     return result;
    
  }
  
    public JSONObject decryptBlob (String key, JSONObject json) {
    try {

      KeyParameter keyParam = this.createKey(
          key, 
          Base64.decode(json.getString("salt"), Base64.DEFAULT),
          json.getInt("iter"), 
          json.getInt("ks"));
      
      byte[] iv    = Base64.decode(json.getString("iv"), Base64.DEFAULT);
      byte[] nonce = Arrays.copyOf(iv, 13); //truncate at 13 bytes
      
      CCMParameters ccm = new CCMParameters(
                    keyParam,
                    json.getInt("ts")/8-1, //not sure why but it works
                    nonce,
                    new byte [0]);
            
        CCMBlockCipher aes = new CCMBlockCipher(new AESFastEngine());
        aes.init(false, ccm);

        byte[] cipherText = Base64.decode(json.getString("ct"), Base64.DEFAULT);
        byte[] plainBytes = new byte[aes.getOutputSize(cipherText.length)];
        
        //System.out.println(byteArrayToHexString(cipherText));
        //System.out.println(aes.getAlgorithmName());
            int res = aes.processBytes(
                cipherText,
                0, 
                cipherText.length, 
                plainBytes, 
                0);
            
            
      aes.doFinal(plainBytes, res);
            String text = new String(plainBytes, "UTF-8");
            //System.out.println(text);
            return new JSONObject(text);
        
        
        
    } catch (JSONException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (DataLengthException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IllegalStateException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (InvalidCipherTextException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }  
    
    return null;
    }
    
    private KeyParameter createKey(String password, byte[] salt,
        int iterations, int keySizeInBits) {
      //System.out.println(keySizeInBits);
      //System.out.println(iterations);
      //System.out.println(salt);
      //System.out.println(password);
      
      PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator(
          new SHA256Digest());
      generator.init(
          PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password.toCharArray()), 
          salt, 
          iterations);
      KeyParameter key = (KeyParameter) generator
          .generateDerivedMacParameters(keySizeInBits);
      return key;
    }
     
    private String byteArrayToHexString(byte[] bytes) {
      StringBuilder result = new StringBuilder();
      for (byte b : bytes) {
        result.append(String.format("%02X", b));
      }
      return result.toString().toLowerCase();
    }
}




Java Source Code List

com.aurionx.wallet.BalanceItem.java
com.aurionx.wallet.BalancesListAdapter.java
com.aurionx.wallet.GlobalState.java
com.aurionx.wallet.LoginActivity.java
com.aurionx.wallet.MainActivity.java
com.aurionx.wallet.PinActivity.java
com.aurionx.wallet.SettingsActivity.java
com.aurionx.wallet.WalletActivity.java
com.aurionx.wallet.currencyName.java
com.codebutler.android_websockets.HybiParser.java
com.codebutler.android_websockets.SocketIOClient.java
com.codebutler.android_websockets.WebSocketClient.java
com.ripple.Account.java
com.ripple.Blobvault.java
com.ripple.NetworkState.java
com.ripple.NetworkUtil.java
com.ripple.RippleWS.java