package com.sqrl.android_sqrl; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import com.github.dazoe.android.Ed25519; import eu.livotov.zxscan.ZXScanHelper; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.util.Base64; import android.util.Log; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; public class MainActivity extends Activity { private TextView textView1 = null; private EditText editText1 = null; private EditText editText2 = null; private Button confbutton = null; private authRequest authReq = null; // Contains all the info for the web page you are trying to authenticate with private identity current_identity = null; // The currently logged in identity private String pubKey = ""; private String sign = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView1 = (TextView) findViewById(R.id.textView1); editText1 = (EditText) findViewById(R.id.editText1); editText2 = (EditText) findViewById(R.id.editText2); confbutton = (Button) findViewById(R.id.confbutton); confbutton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { editText1.setText("Please wait this will take time"); confbutton.setEnabled(false); new createSignature().execute(authReq.getURL()); } }); // Delete identity button (just for testing/debugging) final Button button1 = (Button) findViewById(R.id. button1); button1.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (current_identity != null) current_identity.deleteIdentityFile(getApplicationContext()); } }); /* // ident.deleteIdentityFile(this.getApplicationContext()); // Uncomment to restart identity if (!current_identity.isIdentityCreated(this.getApplicationContext())) { // Check if an identity is created // if not create it Log.i("id", "Create new identity"); current_identity.createKeys(); current_identity.save(this.getApplicationContext()); } else { current_identity.load(this.getApplicationContext()); } current_identity.deriveMasterKey("test pass"); byte[] master =current_identity.getMasterKey(); Log.i("id", "master key1 " + Base64.encodeToString(master, Base64.DEFAULT)); current_identity.changePassword("ninja"); current_identity.deriveMasterKey("ninja"); byte[] master2 =current_identity.getMasterKey(); Log.i("id", "master key2 " + Base64.encodeToString(master2, Base64.DEFAULT)); */ // Start QR activity // ZXScanHelper.scan(this,12345); } @Override protected void onResume() { super.onResume(); if (current_identity == null) { // Show login form Intent loginAct = new Intent(MainActivity.this, loginActivity.class); startActivityForResult(loginAct, 54321); } else { if (authReq == null) ZXScanHelper.scan(this,12345); // start the camera } } // The activity is no longer visible @Override protected void onPause() { super.onPause(); // Reset for new scan textView1.setText(""); editText1.setText(""); editText2.setText(""); confbutton.setEnabled(true); authReq = null; } protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { // From loginAct if (resultCode == RESULT_OK && requestCode == 54321) { current_identity = (identity)data.getSerializableExtra("id"); } // Jumps here when QR is scanned if (resultCode == RESULT_OK && requestCode == 12345) { String scannedCode = ZXScanHelper.getScannedCode(data); authReq = new authRequest(scannedCode); textView1.setText("Authenticate to " + authReq.getDomain()); } } private class createSignature extends AsyncTask<String, Void, String[]> { @Override protected String[] doInBackground(String... params) { String URL = params[0]; byte[] privateKey = CreatePrivateKey(authReq.getDomain(), current_identity.getMasterKey()); byte[] publicKey=null; byte[] signature=null; try { publicKey = Ed25519.PublicKeyFromPrivateKey(privateKey); signature = Ed25519.Sign(URL.getBytes(), privateKey); } catch (Exception e) { e.printStackTrace(); } String publicKey_s = Base64.encodeToString(publicKey, Base64.DEFAULT); String sign_s = Base64.encodeToString(signature, Base64.DEFAULT); String verified = "n"; // not verified yet if (web_post(authReq.getReturnURL(), authReq.getURL(), sign_s, publicKey_s)) { // post the result verified = "y"; } return new String[] {publicKey_s, sign_s, verified}; } @Override protected void onPostExecute(String[]result) { pubKey = result[0]; sign = result[1]; Context context = getApplicationContext(); if (result[2].compareTo("y") == 0) Toast.makeText(context, "Verified", Toast.LENGTH_LONG).show(); // show the user editText1.setText(pubKey); editText2.setText(sign); } } // Create the private key from URL and secret key public static byte[] CreatePrivateKey(String domain, byte[] key) { byte[] hmac=null; try { SecretKeySpec pKey = new SecretKeySpec(key, "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(pKey); hmac = mac.doFinal(domain.getBytes()); } catch (Exception e) { } return hmac; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } // Send signature and pubkey to server private boolean web_post(String URL, String message, String signature, String publicKey) { HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(URL); try { // Add data to post List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2); nameValuePairs.add(new BasicNameValuePair("message", message)); nameValuePairs.add(new BasicNameValuePair("signature", signature)); nameValuePairs.add(new BasicNameValuePair("publicKey", publicKey)); httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpclient.execute(httppost); // Execute HTTP Post Request int status = response.getStatusLine().getStatusCode(); if (status == HttpStatus.SC_OK) { ByteArrayOutputStream ostream = new ByteArrayOutputStream(); response.getEntity().writeTo(ostream); String out = ostream.toString(); Log.v("web", out); // See if the page returned "Verified" if (out.contains("Verified")) { return true; // return true if verified } } else {Log.v("web", "Connection not ok");} } catch (ClientProtocolException e) { Log.e("web", "error"); } catch (IOException e) { Log.e("web", "error"); } return false; // Return false if query did not return verification } }