diff --git a/.idea/encodings.xml b/.idea/encodings.xml index e206d70..f758959 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,5 +1,6 @@ - - - + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 736c7b5..494ac83 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -3,16 +3,23 @@ - - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 92d833e..7d6cb2a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,7 +3,31 @@ - + + + + + @@ -56,5 +80,4 @@ - - + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/SecretShare.iml b/SecretShare.iml index 0bb6048..dbe00f4 100644 --- a/SecretShare.iml +++ b/SecretShare.iml @@ -1,13 +1,14 @@ - + - + @@ -15,5 +16,4 @@ - - + \ No newline at end of file diff --git a/app/app.iml b/app/app.iml index 2cd10c5..29df78b 100644 --- a/app/app.iml +++ b/app/app.iml @@ -1,5 +1,5 @@ - + @@ -9,10 +9,12 @@ - + + @@ -30,43 +33,90 @@ - - - - - + + + + + + + + - + + + + + + + + + + - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + + + + - - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index cf04386..8e9503b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,8 @@ apply plugin: 'maven' dependencies { compile 'com.tiemens:secretshare:1.4.1' compile 'com.google.zxing:core:3.1.0' - compile 'com.android.support:appcompat-v7:20.+' + compile 'com.android.support:appcompat-v7:24.1.0' + compile 'com.squareup:otto:1.3.5' } buildscript { @@ -13,7 +14,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:0.12.1' + classpath 'com.android.tools.build:gradle:2.1.2' } } @@ -24,19 +25,19 @@ allprojects { } android { - compileSdkVersion 20 - buildToolsVersion "20.0.0" + compileSdkVersion 23 + buildToolsVersion "23.0.3" defaultConfig { applicationId "org.surfsite.android.secretshare" minSdkVersion 15 - targetSdkVersion 20 + targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { - runProguard false + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index bb65c6f..968fad7 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -15,3 +15,8 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} + +-keepclassmembers class ** { + @com.squareup.otto.Subscribe public *; + @com.squareup.otto.Produce public *; +} \ No newline at end of file diff --git a/app/src/androidTest/java/org/surfsite/android/secretshare/ApplicationTest.java b/app/src/androidTest/java/org/surfsite/android/secretshare/ApplicationTest.java index f33f437..e330a59 100644 --- a/app/src/androidTest/java/org/surfsite/android/secretshare/ApplicationTest.java +++ b/app/src/androidTest/java/org/surfsite/android/secretshare/ApplicationTest.java @@ -17,7 +17,7 @@ public class ApplicationTest extends ApplicationTestCase { super(Application.class); } - public void testEncrypt() throws Exception { + public void testEncryptDescriptionUTF8() throws Exception { List pieces; int n = 16; int k = 4; @@ -34,7 +34,7 @@ public class ApplicationTest extends ApplicationTestCase { + "01234567890123456789012345678901234567890123456789"; SecretShare.PublicInfo publicInfo; SecretShare.PublicInfo pi = null; - List si = new ArrayList(); + List si = new ArrayList<>(); final BigInteger secretInteger = Renderer.stringToSecret(cleartext); final BigInteger modulus; @@ -66,4 +66,54 @@ public class ApplicationTest extends ApplicationTestCase { assertEquals(cleartext, Renderer.secretToString(combineOutput.getSecret())); assertEquals(publicInfo.getDescription(), si.get(0).getPublicInfo().getDescription()); } + + public void testEncryptDescriptionEmpty() throws Exception { + List pieces; + int n = 16; + int k = 4; + String cleartext + = "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789" + + "01234567890123456789012345678901234567890123456789"; + SecretShare.PublicInfo publicInfo; + SecretShare.PublicInfo pi = null; + List si = new ArrayList<>(); + + final BigInteger secretInteger = Renderer.stringToSecret(cleartext); + final BigInteger modulus; + + modulus = SecretShare.createAppropriateModulusForSecret(secretInteger); + publicInfo = new SecretShare.PublicInfo(n, + k, + modulus, + null); + final SecretShare.SplitSecretOutput splitSecretOutput = new SecretShare(publicInfo) + .split(secretInteger); + pieces = splitSecretOutput.getShareInfos(); + + for (int i = 0; i < pieces.size(); i++) { + final SecretShare.ShareInfo piece = pieces.get(i); + + final String data = Renderer.encodeShareInfo(piece); + + if (pi == null) + pi = Renderer.decodePublicInfo(data); + + if (i % 4 == 0) + si.add(Renderer.decodeShareInfo(data, pi)); + } + + final SecretShare.CombineOutput combineOutput = new SecretShare(pi) + .combine(si); + + assertEquals(cleartext, Renderer.secretToString(combineOutput.getSecret())); + assertEquals(publicInfo.getDescription(), si.get(0).getPublicInfo().getDescription()); + } } \ No newline at end of file diff --git a/app/src/main/java/org/surfsite/android/secretshare/Renderer.java b/app/src/main/java/org/surfsite/android/secretshare/Renderer.java index 8d4d99c..1172d60 100644 --- a/app/src/main/java/org/surfsite/android/secretshare/Renderer.java +++ b/app/src/main/java/org/surfsite/android/secretshare/Renderer.java @@ -36,9 +36,9 @@ public class Renderer { public static Bitmap createBitmap(String data) { final Hashtable hints = - new Hashtable(); - hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1"); - BitMatrix result; + new Hashtable<>(); + hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-1"); + BitMatrix result; final int size = (int) Math.sqrt(data.length() * 8) * 10; try { @@ -50,8 +50,8 @@ public class Renderer { hints); } catch (Exception e) { e.printStackTrace(); - result = null; - } + return null; + } final int width = result.getWidth(); final int height = result.getHeight(); @@ -88,6 +88,9 @@ public class Renderer { int textWidth = getTextWidth(label, textPaint); Bitmap codeBitmap = createBitmap(contents); + if (codeBitmap == null) + return null; + final int width = Math.max(textWidth, codeBitmap.getWidth()); Bitmap bmp = Bitmap.createBitmap(width + bitmapMargin * 2, textHeight + codeBitmap.getHeight() + codePadding * 2 + bitmapMargin * 2, @@ -135,9 +138,9 @@ public class Renderer { public static ArrayList wrap(String txt, int maxWidth, boolean mustFit, Paint paint) { int pos = 0; int start = pos; - ArrayList lines = new ArrayList(); - while (true) { - int i = pos; + ArrayList lines = new ArrayList<>(); + while (true) { + int i = pos; if (txt == null) txt = ""; int len = txt.length(); if (pos >= len) { @@ -208,11 +211,14 @@ public class Renderer { byte[] encBytes = new byte[bytes.length + 1]; System.arraycopy(bytes, 0, encBytes, 0, bytes.length); - encBytes[bytes.length] = (byte) (isUTF8 ? BYTE_IS_UTF8 : BYTE_NOT_UTF8); - return encBytes; - } + encBytes[bytes.length] = isUTF8 ? BYTE_IS_UTF8 : BYTE_NOT_UTF8; + return encBytes; + } static String tryUnicodeExpand(byte[] in) { + if (in.length == 0) + return null; + byte[] exBytes = new byte[in.length - 1]; System.arraycopy(in, 0, exBytes, 0, in.length - 1); if (in[in.length - 1] != BYTE_IS_UTF8) @@ -220,11 +226,9 @@ public class Renderer { final Expand unicodeExpand = new Expand(); try { return unicodeExpand.expand(exBytes); - } catch (IllegalInputException e) { - e.printStackTrace(); - } catch (EndOfInputException e) { - e.printStackTrace(); - } + } catch (IllegalInputException | EndOfInputException e) { + e.printStackTrace(); + } return new String(exBytes); } @@ -240,7 +244,15 @@ public class Renderer { final SecretShare.PublicInfo publicInfo = piece.getPublicInfo(); final byte[] bytePrimeModulus = publicInfo.getPrimeModulus().toByteArray(); final byte[] byteShare = piece.getShare().toByteArray(); - final byte[] byteDescription = tryUnicodeCompress(publicInfo.getDescription()); + String description = publicInfo.getDescription(); + final byte[] byteDescription; + + if ((description != null) && (description.length() > 0)) { + byteDescription = tryUnicodeCompress(description); + } else { + byteDescription = new byte[0]; + } + final int byteLen = 4 + 4 + 4 + (4 + byteDescription.length) @@ -250,38 +262,58 @@ public class Renderer { byteBuffer.putInt(piece.getX()); byteBuffer.putInt(publicInfo.getK()); byteBuffer.putInt(publicInfo.getN()); - byteBuffer.putInt(byteDescription.length).put(byteDescription); - byteBuffer.putInt(bytePrimeModulus.length).put(bytePrimeModulus); - byteBuffer.putInt(byteShare.length).put(byteShare); + byteBuffer.putInt(byteDescription.length); + if (byteDescription.length > 0) + byteBuffer.put(byteDescription); + byteBuffer.putInt(bytePrimeModulus.length).put(bytePrimeModulus); + byteBuffer.putInt(byteShare.length).put(byteShare); final String byteEncoded64 = Base64.encodeToString(byteBuffer.array(), Base64.DEFAULT); - return "ssss-android:" + piece.getX() + "/" + publicInfo.getK() - + ":" + publicInfo.getN() + "=" + byteEncoded64; - } + return "ssssqr:" + piece.getX() + "/" + publicInfo.getK() + + ":" + publicInfo.getN() + "=" + byteEncoded64; + } + + public static SecretShare.PublicInfo decodePublicInfo(final String buf) + throws InvalidParameterException { + if (!buf.startsWith("ssssqr:")) { + throw new InvalidParameterException("Not a SecretShare code."); + } + int index64 = buf.indexOf("=") + 1; + final ByteBuffer byteBuffer; + final byte[] byteDescription; - public static SecretShare.PublicInfo decodePublicInfo(final String buf) { - int index64 = buf.indexOf("=") + 1; - final ByteBuffer byteBuffer; byteBuffer = ByteBuffer.wrap(Base64.decode(buf.substring(index64), Base64.DEFAULT)); int x = byteBuffer.getInt(); int k = byteBuffer.getInt(); int n = byteBuffer.getInt(); + int byteDescriptionLength = byteBuffer.getInt(); - final byte[] byteDescription = new byte[byteDescriptionLength]; - byteBuffer.get(byteDescription); + if (byteDescriptionLength > 0) { + byteDescription = new byte[byteDescriptionLength]; + byteBuffer.get(byteDescription); + } else { + byteDescription = new byte[0]; + } + int bytePrimeModulusLength = byteBuffer.getInt(); - System.out.printf("len=%d\n", bytePrimeModulusLength); final byte[] bytePrimeModulus = new byte[bytePrimeModulusLength]; byteBuffer.get(bytePrimeModulus); BigInteger inPrimeModulus = new BigInteger(bytePrimeModulus); + return new SecretShare.PublicInfo(n, k, inPrimeModulus, tryUnicodeExpand(byteDescription)); } public static SecretShare.ShareInfo decodeShareInfo(final String buf, final SecretShare.PublicInfo publicInfo) throws InvalidParameterException { + if (!buf.startsWith("ssssqr:")) { + throw new InvalidParameterException("Not a SecretShare code."); + } + int index64 = buf.indexOf("=") + 1; final ByteBuffer byteBuffer; + final byte[] byteDescription; + byteBuffer = ByteBuffer.wrap(Base64.decode(buf.substring(index64), Base64.DEFAULT)); int x = byteBuffer.getInt(); int k = byteBuffer.getInt(); @@ -300,11 +332,20 @@ public class Renderer { } int byteDescriptionLength = byteBuffer.getInt(); - final byte[] byteDescription = new byte[byteDescriptionLength]; - byteBuffer.get(byteDescription); - if (publicInfo.getDescription().compareTo(tryUnicodeExpand(byteDescription)) != 0) { - throw new InvalidParameterException("SecretShare.PublicInfo.Description does not match."); - } + + if (byteDescriptionLength > 0) { + byteDescription = new byte[byteDescriptionLength]; + byteBuffer.get(byteDescription); + } else { + byteDescription = new byte[0]; + } + final String description = publicInfo.getDescription(); + final String newDescription = tryUnicodeExpand(byteDescription); + if ((description != null && newDescription != null && description.compareTo(newDescription) != 0) + || (description == null && newDescription != null) + || (description != null && newDescription == null)) { + throw new InvalidParameterException("SecretShare.PublicInfo.Description does not match."); + } int bytePrimeModulusLength = byteBuffer.getInt(); final byte[] bytePrimeModulus = new byte[bytePrimeModulusLength]; byteBuffer.get(bytePrimeModulus); diff --git a/build.gradle b/build.gradle index a75fc81..e220f0b 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:0.12.+' + classpath 'com.android.tools.build:gradle:2.1.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1e61d1f..cd24e1f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 10 15:27:10 PDT 2013 +#Tue Jul 19 16:27:54 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip