diff --git a/.gitignore b/.gitignore index 17aef84..c420b67 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,8 @@ app/project.properties app/build.xml app/local.properties bin/* +local.properties +.gradle/ +.idea/ +*.iml +*/build/ diff --git a/cameraVApp/src/main/AndroidManifest.xml b/cameraVApp/src/main/AndroidManifest.xml index 3bfcf91..c2872fd 100644 --- a/cameraVApp/src/main/AndroidManifest.xml +++ b/cameraVApp/src/main/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionName="0.2.4"> @@ -22,7 +22,6 @@ - diff --git a/informaCam/src/main/AndroidManifest.xml b/informaCam/src/main/AndroidManifest.xml index 7deffd8..13def3e 100644 --- a/informaCam/src/main/AndroidManifest.xml +++ b/informaCam/src/main/AndroidManifest.xml @@ -4,7 +4,7 @@ android:versionName="1.0" > diff --git a/informaCam/src/main/java/org/witness/informacam/crypto/KeyUtility.java b/informaCam/src/main/java/org/witness/informacam/crypto/KeyUtility.java index 9da708a..90cb711 100644 --- a/informaCam/src/main/java/org/witness/informacam/crypto/KeyUtility.java +++ b/informaCam/src/main/java/org/witness/informacam/crypto/KeyUtility.java @@ -5,15 +5,20 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.math.BigInteger; +import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.security.KeyStore; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.Security; import java.security.SignatureException; +import java.util.ArrayList; +import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -45,33 +50,37 @@ import org.spongycastle.util.encoders.Hex; import org.witness.informacam.InformaCam; import org.witness.informacam.json.JSONArray; -import org.witness.informacam.json.JSONException; import org.witness.informacam.json.JSONObject; import org.witness.informacam.json.JSONTokener; import org.witness.informacam.models.credentials.IKeyStore; import org.witness.informacam.models.credentials.ISecretKey; -import org.witness.informacam.models.notifications.INotification; import org.witness.informacam.models.organizations.IOrganization; import org.witness.informacam.storage.FormUtility; import org.witness.informacam.storage.IOUtility; +import org.witness.informacam.utils.Constants.Logger; import org.witness.informacam.utils.Constants.App; import org.witness.informacam.utils.Constants.App.Storage; import org.witness.informacam.utils.Constants.App.Storage.Type; import org.witness.informacam.utils.Constants.Codes; import org.witness.informacam.utils.Constants.IManifest; -import org.witness.informacam.utils.Constants.Models; import org.witness.informacam.utils.Constants.Models.ICredentials; import org.witness.informacam.utils.Constants.Models.IUser; import android.os.Bundle; import android.os.Message; +import android.security.KeyPairGeneratorSpec; import android.util.Base64; import android.util.Log; +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.CipherOutputStream; +import javax.security.auth.x500.X500Principal; + public class KeyUtility { private final static String LOG = App.Crypto.LOG; - + public static String getFingerprintFromKey(byte[] keyblock) throws IOException, PGPException { PGPPublicKey key = extractPublicKeyFromBytes(keyblock); return new String(Hex.encode(key.getFingerprint())); @@ -112,7 +121,7 @@ public static PGPPublicKey extractPublicKeyFromBytes(byte[] keyBlock) throws IOE key = k; } } - + if(key == null) { throw new IllegalArgumentException("there isn't an encryption key here."); } @@ -132,16 +141,16 @@ public static String generatePassword(byte[] baseBytes) throws NoSuchAlgorithmEx product[b] = (byte) (baseBytes[b] ^ randomBytes[b]); } - // digest to SHA1 string, voila password. - MessageDigest md = MessageDigest.getInstance("SHA-1"); - return Base64.encodeToString(md.digest(product), Base64.DEFAULT); + // digest to SHA-256 string, voila password. + MessageDigest md = MessageDigest.getInstance("SHA-256"); + return new String(Hex.encode(md.digest(product))); } @SuppressWarnings("deprecation") public static boolean initDevice() { - + int progress = 1; - Bundle data = new Bundle(); + Bundle data = new Bundle(); data.putInt(Codes.Extras.MESSAGE_CODE, Codes.Messages.UI.UPDATE); data.putInt(Codes.Keys.UI.PROGRESS, progress); @@ -152,7 +161,7 @@ public static boolean initDevice() { @Override public void onCacheWordUninitialized() { if(firstUse) { - + Log.d(LOG, "INIT: onCacheWordUninitialized()"); try { @@ -166,17 +175,17 @@ public void onCacheWordUninitialized() { } } - + @Override public void onCacheWordOpened() { // there is not credential block, so override this. if(firstUse) { Log.d(LOG, "INIT: onCacheWordOpened()"); - + cacheWord.setTimeout(0); - + informaCam.ioService.initIOCipher(cacheWord.getEncryptionKey()); - + new Thread () { public void run () @@ -190,10 +199,10 @@ public void run () } } }); - + return true; } - + private static void initDeviceAsync (InformaCam informaCam, CredentialManager credMgr) { try { @@ -203,32 +212,32 @@ private static void initDeviceAsync (InformaCam informaCam, CredentialManager cr byte[] baseImageBytes = informaCam.ioService.getBytes(basePath, Storage.Type.INTERNAL_STORAGE); authToken = generatePassword(baseImageBytes); - + String authTokenBlobBytes = new String(credMgr.setAuthToken(authToken)); JSONObject authTokenBlob = (JSONObject) new JSONTokener(authTokenBlobBytes).nextValue(); authTokenBlob.put(ICredentials.PASSWORD_BLOCK, authTokenBlob.getString("value")); authTokenBlob.remove("value"); - + initDeviceKeys(authToken, baseImageBytes); - + if(informaCam.ioService.saveBlob(authTokenBlob.toString().getBytes(), new java.io.File(IUser.CREDENTIALS))) { informaCam.user.setHasCredentials(true); - + } informaCam.initData(); - + for(String s : informaCam.getAssets().list("includedOrganizations")) { - + InputStream ictdIS = informaCam.ioService.getStream("includedOrganizations/" + s, Type.APPLICATION_ASSET); - + byte[] ictdBytes = new byte[ictdIS.available()]; ictdIS.read(ictdBytes); - - + + IOrganization organization = informaCam.installICTD((JSONObject) new JSONTokener(new String(ictdBytes)).nextValue(), informaCam.h, informaCam); if(organization != null && !informaCam.user.isInOfflineMode) { - + /* INotification notification = new INotification(informaCam.getResources().getString(R.string.key_sent), informaCam.getResources().etResources().getString(R.string.you_have_sent_your_credentials_to_x, organization.organizationName), Models.INotification.Type.NEW_KEY); notification.taskComplete = false; @@ -239,8 +248,8 @@ private static void initDeviceAsync (InformaCam informaCam, CredentialManager cr // TransportUtility.initTransport(transportStub); } } - - + + try { for(String s : informaCam.getAssets().list("includedForms")) { InputStream formXML = informaCam.ioService.getStream("includedForms/" + s, Type.APPLICATION_ASSET); @@ -250,22 +259,95 @@ private static void initDeviceAsync (InformaCam informaCam, CredentialManager cr Log.e(LOG, e.toString()); e.printStackTrace(); } - - + + // Tell others we are done! Bundle data = new Bundle(); data.putInt(Codes.Extras.MESSAGE_CODE, org.witness.informacam.utils.Constants.Codes.Messages.UI.REPLACE); - + Message message = new Message(); message.setData(data); - + informaCam.update(data); - + } catch (Exception e) { Log.e(LOG, e.toString(),e); } } - + + public static String unwrapSecretAuthToken(String secretAuthToken) throws GeneralSecurityException, IOException { + final KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); + keyStore.load(null); + + final KeyStore.PrivateKeyEntry pke = (KeyStore.PrivateKeyEntry) keyStore.getEntry(ICredentials.PASSWORD_ALIAS, null); + final KeyPair keyPair = new KeyPair(pke.getCertificate().getPublicKey(), pke.getPrivateKey()); + + final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); + cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); + + CipherInputStream cis = new CipherInputStream( + new ByteArrayInputStream(Base64.decode(secretAuthToken.getBytes("UTF-8"), Base64.DEFAULT)), cipher); + + ArrayList a_bytes = new ArrayList(); + int next; + while ((next = cis.read()) != -1) { + a_bytes.add((byte) next); + } + + byte[] bytes = new byte[a_bytes.size()]; + for(int b=0; b publicCredentials = new HashMap(); JSONArray baseImages = informaCam.user.getJSONArray(IUser.PATH_TO_BASE_IMAGE); for(int j=0; j 0) { sig.update((byte) read); baos.write(read); } - + PGPSignatureList sigList = (PGPSignatureList) objFactory.nextObject(); - + if(sig.verify(sigList.get(0)) && data.toString().equals(new String(baos.toByteArray()))) { - baos.close(); + baos.close(); return true; } else { baos.close(); return false; } - + } catch (PGPException e) { @@ -103,22 +111,14 @@ public boolean isVerified(final ILogPack data) throws IOException { Log.d(LOG,"SignatureException: " + e.getMessage(),e); return false; } - + } - + public void signData(InputStream is, OutputStream os) throws NoSuchAlgorithmException, SignatureException, PGPException, IOException { - KeyUtility.applySignature(is, os, secretKey, publicKey, privateKey); + KeyUtility.applySignature(is, os, secretKey, publicKey, privateKey); } - + public byte[] signData(final byte[] data) throws NoSuchAlgorithmException, SignatureException, PGPException, IOException { - return KeyUtility.applySignature(data, secretKey, publicKey, privateKey); - } - - public boolean hasSecretKey () - { - return secretKey != null; + return KeyUtility.applySignature(data, secretKey, publicKey, privateKey); } - - - } diff --git a/informaCam/src/main/java/org/witness/informacam/utils/Constants.java b/informaCam/src/main/java/org/witness/informacam/utils/Constants.java index 34b1bc6..0b879a0 100644 --- a/informaCam/src/main/java/org/witness/informacam/utils/Constants.java +++ b/informaCam/src/main/java/org/witness/informacam/utils/Constants.java @@ -520,6 +520,7 @@ public class TempKeys { public class ICredentials { public final static String PASSWORD_BLOCK = "passwordBlock"; + public final static String PASSWORD_ALIAS = "CameraV1_2"; } public class IPendingConnections {