From 10ac1af6b0b536cf543777967b2f60229fc90c3a Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 26 Dec 2019 20:47:28 +0100 Subject: [PATCH] Replace implementations of Base16, Base32 and Base64 with Guava I kept the classes in the encoding package and turned them into wrappers for Guava. I also changed the functions in the Base32 class to take and return strings insteads if character arrays. --- app/build.gradle | 3 + .../aegis/crypto/CryptParameters.java | 4 +- .../aegis/encoding/Base32.java | 152 ++---------------- .../aegis/encoding/Base32Exception.java | 7 - .../aegis/encoding/Base64.java | 13 +- .../aegis/encoding/Base64Exception.java | 7 - .../aegis/encoding/EncodingException.java | 9 ++ .../beemdevelopment/aegis/encoding/Hex.java | 43 ++--- .../aegis/encoding/HexException.java | 7 - .../aegis/importers/AegisImporter.java | 6 +- .../aegis/importers/AndOtpImporter.java | 6 +- .../aegis/importers/AuthyImporter.java | 6 +- .../aegis/importers/GoogleAuthImporter.java | 6 +- .../aegis/importers/SteamImporter.java | 4 +- .../aegis/otp/GoogleAuthInfo.java | 6 +- .../beemdevelopment/aegis/otp/OtpInfo.java | 6 +- .../aegis/ui/EditEntryActivity.java | 26 +-- .../beemdevelopment/aegis/vault/Vault.java | 4 +- .../aegis/vault/VaultEntry.java | 4 +- .../aegis/vault/VaultFile.java | 9 +- .../aegis/vault/slots/Slot.java | 4 +- .../com/beemdevelopment/aegis/SCryptTest.java | 4 +- .../com/beemdevelopment/aegis/TOTPTest.java | 6 +- 23 files changed, 88 insertions(+), 254 deletions(-) delete mode 100644 app/src/main/java/com/beemdevelopment/aegis/encoding/Base32Exception.java delete mode 100644 app/src/main/java/com/beemdevelopment/aegis/encoding/Base64Exception.java create mode 100644 app/src/main/java/com/beemdevelopment/aegis/encoding/EncodingException.java delete mode 100644 app/src/main/java/com/beemdevelopment/aegis/encoding/HexException.java diff --git a/app/build.gradle b/app/build.gradle index 12aebeb0..cdd7c79d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,6 +21,7 @@ android { targetSdkVersion 29 versionCode 28 versionName "1.1.4" + multiDexEnabled true buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\"" buildConfigField "String", "GIT_BRANCH", "\"${getGitBranch()}\"" } @@ -72,6 +73,7 @@ dependencies { implementation 'androidx.preference:preference:1.1.0' implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'com.google.guava:guava:28.2-android' implementation 'com.getbase:floatingactionbutton:1.10.1' implementation 'com.github.apl-devs:appintro:5.1.0' implementation 'com.github.avito-tech:krop:0.44' @@ -91,5 +93,6 @@ dependencies { annotationProcessor 'androidx.annotation:annotation:1.1.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.5.2' + testImplementation 'com.google.guava:guava:28.2-jre"' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2' } diff --git a/app/src/main/java/com/beemdevelopment/aegis/crypto/CryptParameters.java b/app/src/main/java/com/beemdevelopment/aegis/crypto/CryptParameters.java index 9b6a749e..3f1a55b0 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/crypto/CryptParameters.java +++ b/app/src/main/java/com/beemdevelopment/aegis/crypto/CryptParameters.java @@ -1,7 +1,7 @@ package com.beemdevelopment.aegis.crypto; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.encoding.Hex; -import com.beemdevelopment.aegis.encoding.HexException; import org.json.JSONException; import org.json.JSONObject; @@ -30,7 +30,7 @@ public class CryptParameters implements Serializable { return obj; } - public static CryptParameters fromJson(JSONObject obj) throws JSONException, HexException { + public static CryptParameters fromJson(JSONObject obj) throws JSONException, EncodingException { byte[] nonce = Hex.decode(obj.getString("nonce")); byte[] tag = Hex.decode(obj.getString("tag")); return new CryptParameters(nonce, tag); diff --git a/app/src/main/java/com/beemdevelopment/aegis/encoding/Base32.java b/app/src/main/java/com/beemdevelopment/aegis/encoding/Base32.java index 2f5a72f3..29c0f89a 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/encoding/Base32.java +++ b/app/src/main/java/com/beemdevelopment/aegis/encoding/Base32.java @@ -1,155 +1,23 @@ package com.beemdevelopment.aegis.encoding; -// modified for use in Aegis +import com.google.common.io.BaseEncoding; -/* (PD) 2001 The Bitzi Corporation - * Please see http://bitzi.com/publicdomain for more info. - * - * As modified by Patrick Woodworth: - * - * Copyright 2011 Patrick Woodworth - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.util.Arrays; - -/** - * Base32 - encodes and decodes RFC3548 Base32 - * (see http://www.faqs.org/rfcs/rfc3548.html ) - * - * @author Robert Kaye - * @author Gordon Mohr - */ public class Base32 { - private static final String base32Chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; - private static final int[] base32Lookup = - { 0xFF,0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, // '0', '1', '2', '3', '4', '5', '6', '7' - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // '8', '9', ':', ';', '<', '=', '>', '?' - 0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, // '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G' - 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O' - 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W' - 0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF, // 'X', 'Y', 'Z', '[', '\', ']', '^', '_' - 0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, // '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g' - 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o' - 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w' - 0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF // 'x', 'y', 'z', '{', '|', '}', '~', 'DEL' - }; + private static final BaseEncoding _encoding = BaseEncoding.base32().omitPadding(); - /** - * Encodes byte array to Base32 String. - * - * @param bytes Bytes to encode. - * @return Encoded byte array bytes as a String. - * - */ - public static char[] encode(final byte[] bytes) { - int i = 0, index = 0, digit = 0, j = 0; - int currByte, nextByte; - char[] base32 = new char[(bytes.length + 7) * 8 / 5]; + private Base32() { - while (i < bytes.length) { - currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256); // unsign - - /* Is the current digit going to span a byte boundary? */ - if (index > 3) { - if ((i + 1) < bytes.length) { - nextByte = - (bytes[i + 1] >= 0) ? bytes[i + 1] : (bytes[i + 1] + 256); - } else { - nextByte = 0; - } - - digit = currByte & (0xFF >> index); - index = (index + 5) % 8; - digit <<= index; - digit |= nextByte >> (8 - index); - i++; - } else { - digit = (currByte >> (8 - (index + 5))) & 0x1F; - index = (index + 5) % 8; - if (index == 0) - i++; - } - base32[j++] = base32Chars.charAt(digit); - } - - return Arrays.copyOf(base32, j); } - /** - * Decodes the given Base32 String to a raw byte array. - * - * @param base32 - * @return Decoded base32 String as a raw byte array. - */ - public static byte[] decode(final char[] base32) throws Base32Exception { - int i, index, lookup, offset, digit; - byte[] bytes = new byte[base32.length * 5 / 8]; - - for (i = 0, index = 0, offset = 0; i < base32.length; i++) { - // stop decoding when a padding char is encountered - if (base32[i] == '=') { - // make sure the rest is also padding, but don't bother verifying the length - for (int j = i + 1; j < base32.length; j++) { - if (base32[j] != '=') { - throw new Base32Exception("bad padding"); - } - } - break; - } - - lookup = base32[i] - '0'; - digit = decodeDigit(lookup); - - if (index <= 3) { - index = (index + 5) % 8; - if (index == 0) { - bytes[offset] |= digit; - offset++; - if (offset >= bytes.length) - break; - } else { - bytes[offset] |= digit << (8 - index); - } - } else { - index = (index + 5) % 8; - bytes[offset] |= (digit >>> index); - offset++; - - if (offset >= bytes.length) { - break; - } - bytes[offset] |= digit << (8 - index); - } + public static byte[] decode(String s) throws EncodingException { + try { + return _encoding.decode(s.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new EncodingException(e); } - return bytes; } - private static int decodeDigit(int c) throws Base32Exception { - /* Skip chars outside the lookup table */ - if (c < 0 || c >= base32Lookup.length) { - throw new Base32Exception("char not found in base32 lookup table"); - } - - int digit = base32Lookup[c]; - - /* If this digit is not in the table, ignore it */ - if (digit == 0xFF) { - throw new Base32Exception("char not found in base32 lookup table"); - } - - return digit; + public static String encode(byte[] data) { + return _encoding.encode(data); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/encoding/Base32Exception.java b/app/src/main/java/com/beemdevelopment/aegis/encoding/Base32Exception.java deleted file mode 100644 index 63a21022..00000000 --- a/app/src/main/java/com/beemdevelopment/aegis/encoding/Base32Exception.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.beemdevelopment.aegis.encoding; - -public class Base32Exception extends Exception { - public Base32Exception(String message) { - super(message); - } -} diff --git a/app/src/main/java/com/beemdevelopment/aegis/encoding/Base64.java b/app/src/main/java/com/beemdevelopment/aegis/encoding/Base64.java index 09966972..91613eab 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/encoding/Base64.java +++ b/app/src/main/java/com/beemdevelopment/aegis/encoding/Base64.java @@ -1,24 +1,21 @@ package com.beemdevelopment.aegis.encoding; -import java.nio.charset.StandardCharsets; +import com.google.common.io.BaseEncoding; public class Base64 { - private static final int _flags = android.util.Base64.NO_WRAP; - private Base64() { } - public static byte[] decode(String s) throws Base64Exception { + public static byte[] decode(String s) throws EncodingException { try { - return android.util.Base64.decode(s, _flags); + return BaseEncoding.base64().decode(s); } catch (IllegalArgumentException e) { - throw new Base64Exception(e); + throw new EncodingException(e); } } public static String encode(byte[] data) { - byte[] encoded = android.util.Base64.encode(data, _flags); - return new String(encoded, StandardCharsets.UTF_8); + return BaseEncoding.base64().encode(data); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/encoding/Base64Exception.java b/app/src/main/java/com/beemdevelopment/aegis/encoding/Base64Exception.java deleted file mode 100644 index 09219bf7..00000000 --- a/app/src/main/java/com/beemdevelopment/aegis/encoding/Base64Exception.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.beemdevelopment.aegis.encoding; - -public class Base64Exception extends Exception { - public Base64Exception(Throwable cause) { - super(cause); - } -} diff --git a/app/src/main/java/com/beemdevelopment/aegis/encoding/EncodingException.java b/app/src/main/java/com/beemdevelopment/aegis/encoding/EncodingException.java new file mode 100644 index 00000000..ac75a347 --- /dev/null +++ b/app/src/main/java/com/beemdevelopment/aegis/encoding/EncodingException.java @@ -0,0 +1,9 @@ +package com.beemdevelopment.aegis.encoding; + +import java.io.IOException; + +public class EncodingException extends IOException { + public EncodingException(Throwable cause) { + super(cause); + } +} diff --git a/app/src/main/java/com/beemdevelopment/aegis/encoding/Hex.java b/app/src/main/java/com/beemdevelopment/aegis/encoding/Hex.java index de96e015..db8ff046 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/encoding/Hex.java +++ b/app/src/main/java/com/beemdevelopment/aegis/encoding/Hex.java @@ -1,46 +1,21 @@ package com.beemdevelopment.aegis.encoding; -// The hexadecimal utility functions in this file were taken and modified from: http://www.docjar.com/html/api/com/sun/xml/internal/bind/DatatypeConverterImpl.java.html -// It is licensed under GPLv2 with a classpath exception. +import com.google.common.io.BaseEncoding; + public class Hex { private Hex() { + } - private static int hexToBin(char ch) { - if ('0' <= ch && ch <= '9') return ch - '0'; - if ('A' <= ch && ch <= 'F') return ch - 'A' + 10; - if ('a' <= ch && ch <= 'f') return ch - 'a' + 10; - return -1; - } - - private static final char[] hexCode = "0123456789abcdef".toCharArray(); - - public static byte[] decode(String s) throws HexException { - final int len = s.length(); - - if (len % 2 != 0) - throw new HexException("hexBinary needs to be even-length: " + s); - - byte[] out = new byte[len / 2]; - - for (int i = 0; i < len; i += 2) { - int h = hexToBin(s.charAt(i)); - int l = hexToBin(s.charAt(i + 1)); - if (h == -1 || l == -1) - throw new HexException("contains illegal character for hexBinary: " + s); - - out[i / 2] = (byte) (h * 16 + l); + public static byte[] decode(String s) throws EncodingException { + try { + return BaseEncoding.base16().decode(s.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new EncodingException(e); } - - return out; } public static String encode(byte[] data) { - StringBuilder r = new StringBuilder(data.length * 2); - for (byte b : data) { - r.append(hexCode[(b >> 4) & 0xF]); - r.append(hexCode[(b & 0xF)]); - } - return r.toString(); + return BaseEncoding.base16().lowerCase().encode(data); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/encoding/HexException.java b/app/src/main/java/com/beemdevelopment/aegis/encoding/HexException.java deleted file mode 100644 index 12d9782c..00000000 --- a/app/src/main/java/com/beemdevelopment/aegis/encoding/HexException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.beemdevelopment.aegis.encoding; - -public class HexException extends Exception { - public HexException(String message) { - super(message); - } -} diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/AegisImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/AegisImporter.java index 7cff6531..4df7a83a 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/AegisImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/AegisImporter.java @@ -2,13 +2,13 @@ package com.beemdevelopment.aegis.importers; import android.content.Context; +import com.beemdevelopment.aegis.encoding.EncodingException; +import com.beemdevelopment.aegis.otp.OtpInfoException; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.vault.VaultFile; import com.beemdevelopment.aegis.vault.VaultFileCredentials; import com.beemdevelopment.aegis.vault.VaultFileException; import com.beemdevelopment.aegis.vault.slots.SlotList; -import com.beemdevelopment.aegis.encoding.Base64Exception; -import com.beemdevelopment.aegis.otp.OtpInfoException; import org.json.JSONArray; import org.json.JSONException; @@ -102,7 +102,7 @@ public class AegisImporter extends DatabaseImporter { private static VaultEntry convertEntry(JSONObject obj) throws DatabaseImporterEntryException { try { return VaultEntry.fromJson(obj); - } catch (JSONException | OtpInfoException | Base64Exception e) { + } catch (JSONException | OtpInfoException | EncodingException e) { throw new DatabaseImporterEntryException(e, obj.toString()); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/AndOtpImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/AndOtpImporter.java index 19f576e4..5df1ce51 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/AndOtpImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/AndOtpImporter.java @@ -10,7 +10,7 @@ import com.beemdevelopment.aegis.crypto.CryptResult; import com.beemdevelopment.aegis.crypto.CryptoUtils; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.encoding.Base32; -import com.beemdevelopment.aegis.encoding.Base32Exception; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.otp.HotpInfo; import com.beemdevelopment.aegis.otp.OtpInfo; import com.beemdevelopment.aegis.otp.OtpInfoException; @@ -201,7 +201,7 @@ public class AndOtpImporter extends DatabaseImporter { String type = obj.getString("type").toLowerCase(); String algo = obj.getString("algorithm"); int digits = obj.getInt("digits"); - byte[] secret = Base32.decode(obj.getString("secret").toCharArray()); + byte[] secret = Base32.decode(obj.getString("secret")); OtpInfo info; switch (type) { @@ -230,7 +230,7 @@ public class AndOtpImporter extends DatabaseImporter { } return new VaultEntry(info, name, issuer); - } catch (DatabaseImporterException | Base32Exception | OtpInfoException | JSONException e) { + } catch (DatabaseImporterException | EncodingException | OtpInfoException | JSONException e) { throw new DatabaseImporterEntryException(e, obj.toString()); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/AuthyImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/AuthyImporter.java index ef3fec8f..a2e77c5f 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/AuthyImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/AuthyImporter.java @@ -5,7 +5,7 @@ import android.util.Xml; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.encoding.Base32; -import com.beemdevelopment.aegis.encoding.Base32Exception; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.otp.OtpInfo; import com.beemdevelopment.aegis.otp.OtpInfoException; import com.beemdevelopment.aegis.otp.TotpInfo; @@ -97,12 +97,12 @@ public class AuthyImporter extends DatabaseImporter { sanitizeEntryInfo(authyEntryInfo); int digits = entry.getInt("digits"); - byte[] secret = Base32.decode(entry.getString("decryptedSecret").toCharArray()); + byte[] secret = Base32.decode(entry.getString("decryptedSecret")); OtpInfo info = new TotpInfo(secret, "SHA1", digits, 30); return new VaultEntry(info, authyEntryInfo.Name, authyEntryInfo.Issuer); - } catch (OtpInfoException | JSONException | Base32Exception e) { + } catch (OtpInfoException | JSONException | EncodingException e) { throw new DatabaseImporterEntryException(e, entry.toString()); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/GoogleAuthImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/GoogleAuthImporter.java index fc1e4169..89a3a24b 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/GoogleAuthImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/GoogleAuthImporter.java @@ -7,7 +7,7 @@ import android.database.sqlite.SQLiteException; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.encoding.Base32; -import com.beemdevelopment.aegis.encoding.Base32Exception; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.otp.HotpInfo; import com.beemdevelopment.aegis.otp.OtpInfo; import com.beemdevelopment.aegis.otp.OtpInfoException; @@ -104,7 +104,7 @@ public class GoogleAuthImporter extends DatabaseImporter { private static VaultEntry convertEntry(Entry entry) throws DatabaseImporterEntryException { try { - byte[] secret = Base32.decode(entry.getSecret().toCharArray()); + byte[] secret = Base32.decode(entry.getSecret()); OtpInfo info; switch (entry.getType()) { @@ -125,7 +125,7 @@ public class GoogleAuthImporter extends DatabaseImporter { } return new VaultEntry(info, name, entry.getIssuer()); - } catch (Base32Exception | OtpInfoException | DatabaseImporterException e) { + } catch (EncodingException | OtpInfoException | DatabaseImporterException e) { throw new DatabaseImporterEntryException(e, entry.toString()); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/SteamImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/SteamImporter.java index 9cf3c921..36a91ebf 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/SteamImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/SteamImporter.java @@ -3,9 +3,9 @@ package com.beemdevelopment.aegis.importers; import android.content.Context; import android.content.pm.PackageManager; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.encoding.Base64; -import com.beemdevelopment.aegis.encoding.Base64Exception; import com.beemdevelopment.aegis.otp.OtpInfoException; import com.beemdevelopment.aegis.otp.SteamInfo; import com.beemdevelopment.aegis.util.ByteInputStream; @@ -82,7 +82,7 @@ public class SteamImporter extends DatabaseImporter { String account = obj.getString("account_name"); return new VaultEntry(info, account, "Steam"); - } catch (JSONException | Base64Exception | OtpInfoException e) { + } catch (JSONException | EncodingException | OtpInfoException e) { throw new DatabaseImporterEntryException(e, obj.toString()); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java b/app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java index 5e25a9ff..0f35e7b5 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java +++ b/app/src/main/java/com/beemdevelopment/aegis/otp/GoogleAuthInfo.java @@ -3,7 +3,7 @@ package com.beemdevelopment.aegis.otp; import android.net.Uri; import com.beemdevelopment.aegis.encoding.Base32; -import com.beemdevelopment.aegis.encoding.Base32Exception; +import com.beemdevelopment.aegis.encoding.EncodingException; public class GoogleAuthInfo { private OtpInfo _info; @@ -71,8 +71,8 @@ public class GoogleAuthInfo { // decode secret byte[] secret; try { - secret = Base32.decode(encodedSecret.toCharArray()); - } catch (Base32Exception e) { + secret = Base32.decode(encodedSecret); + } catch (EncodingException e) { throw new GoogleAuthInfoException("bad secret", e); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/otp/OtpInfo.java b/app/src/main/java/com/beemdevelopment/aegis/otp/OtpInfo.java index 498e2681..5c77411f 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/otp/OtpInfo.java +++ b/app/src/main/java/com/beemdevelopment/aegis/otp/OtpInfo.java @@ -1,7 +1,7 @@ package com.beemdevelopment.aegis.otp; import com.beemdevelopment.aegis.encoding.Base32; -import com.beemdevelopment.aegis.encoding.Base32Exception; +import com.beemdevelopment.aegis.encoding.EncodingException; import org.json.JSONException; import org.json.JSONObject; @@ -93,7 +93,7 @@ public abstract class OtpInfo implements Serializable { OtpInfo info; try { - byte[] secret = Base32.decode(obj.getString("secret").toCharArray()); + byte[] secret = Base32.decode(obj.getString("secret")); String algo = obj.getString("algo"); int digits = obj.getInt("digits"); @@ -110,7 +110,7 @@ public abstract class OtpInfo implements Serializable { default: throw new OtpInfoException("unsupported otp type: " + type); } - } catch (Base32Exception | JSONException e) { + } catch (EncodingException | JSONException e) { throw new OtpInfoException(e); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java index 1bf58044..bf3f28ca 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java @@ -22,12 +22,18 @@ import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.TableRow; +import androidx.annotation.ArrayRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AlertDialog; + import com.amulyakhare.textdrawable.TextDrawable; import com.avito.android.krop.KropView; import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.encoding.Base32; -import com.beemdevelopment.aegis.encoding.Base32Exception; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.helpers.EditTextHelper; import com.beemdevelopment.aegis.helpers.SpinnerHelper; import com.beemdevelopment.aegis.helpers.TextDrawableHelper; @@ -36,11 +42,11 @@ import com.beemdevelopment.aegis.otp.OtpInfo; import com.beemdevelopment.aegis.otp.OtpInfoException; import com.beemdevelopment.aegis.otp.SteamInfo; import com.beemdevelopment.aegis.otp.TotpInfo; +import com.beemdevelopment.aegis.util.Cloner; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.transition.Transition; -import com.beemdevelopment.aegis.util.Cloner; import java.io.ByteArrayOutputStream; import java.text.Collator; @@ -49,11 +55,6 @@ import java.util.List; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicReference; -import androidx.annotation.ArrayRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AlertDialog; import de.hdodenhof.circleimageview.CircleImageView; public class EditEntryActivity extends AegisActivity { @@ -163,8 +164,8 @@ public class EditEntryActivity extends AegisActivity { byte[] secretBytes = _origEntry.getInfo().getSecret(); if (secretBytes != null) { - char[] secretChars = Base32.encode(secretBytes); - _textSecret.setText(secretChars, 0, secretChars.length); + String secretString = Base32.encode(secretBytes); + _textSecret.setText(secretString); } String type = _origEntry.getInfo().getType(); @@ -458,8 +459,11 @@ public class EditEntryActivity extends AegisActivity { byte[] secret; try { - secret = Base32.decode(EditTextHelper.getEditTextChars(_textSecret, true)); - } catch (Base32Exception e) { + secret = Base32.decode(new String(EditTextHelper.getEditTextChars(_textSecret, true))); + if (secret.length == 0) { + throw new ParseException("Secret cannot be empty"); + } + } catch (EncodingException e) { throw new ParseException("Secret is not valid base32."); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/Vault.java b/app/src/main/java/com/beemdevelopment/aegis/vault/Vault.java index 99ec9202..99b90732 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/Vault.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/Vault.java @@ -1,6 +1,6 @@ package com.beemdevelopment.aegis.vault; -import com.beemdevelopment.aegis.encoding.Base64Exception; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.otp.OtpInfoException; import com.beemdevelopment.aegis.util.UUIDMap; @@ -43,7 +43,7 @@ public class Vault { VaultEntry entry = VaultEntry.fromJson(array.getJSONObject(i)); entries.add(entry); } - } catch (Base64Exception | OtpInfoException | JSONException e) { + } catch (EncodingException | OtpInfoException | JSONException e) { throw new VaultException(e); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java index ceba2518..a610e1e4 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java @@ -1,7 +1,7 @@ package com.beemdevelopment.aegis.vault; import com.beemdevelopment.aegis.encoding.Base64; -import com.beemdevelopment.aegis.encoding.Base64Exception; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.otp.GoogleAuthInfo; import com.beemdevelopment.aegis.otp.OtpInfo; import com.beemdevelopment.aegis.otp.OtpInfoException; @@ -60,7 +60,7 @@ public class VaultEntry extends UUIDMap.Value { return obj; } - public static VaultEntry fromJson(JSONObject obj) throws JSONException, OtpInfoException, Base64Exception { + public static VaultEntry fromJson(JSONObject obj) throws JSONException, OtpInfoException, EncodingException { // if there is no uuid, generate a new one UUID uuid; if (!obj.has("uuid")) { diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultFile.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultFile.java index 66f4a331..ba68f08d 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultFile.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultFile.java @@ -3,11 +3,10 @@ package com.beemdevelopment.aegis.vault; import com.beemdevelopment.aegis.crypto.CryptParameters; import com.beemdevelopment.aegis.crypto.CryptResult; import com.beemdevelopment.aegis.crypto.MasterKeyException; +import com.beemdevelopment.aegis.encoding.Base64; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.vault.slots.SlotList; import com.beemdevelopment.aegis.vault.slots.SlotListException; -import com.beemdevelopment.aegis.encoding.Base64; -import com.beemdevelopment.aegis.encoding.Base64Exception; -import com.beemdevelopment.aegis.encoding.HexException; import org.json.JSONException; import org.json.JSONObject; @@ -95,7 +94,7 @@ public class VaultFile { byte[] bytes = Base64.decode((String) _content); CryptResult result = creds.decrypt(bytes, _header.getParams()); return new JSONObject(new String(result.getData(), StandardCharsets.UTF_8)); - } catch (MasterKeyException | JSONException | Base64Exception e) { + } catch (MasterKeyException | JSONException | EncodingException e) { throw new VaultFileException(e); } } @@ -136,7 +135,7 @@ public class VaultFile { SlotList slots = SlotList.fromJson(obj.getJSONArray("slots")); CryptParameters params = CryptParameters.fromJson(obj.getJSONObject("params")); return new Header(slots, params); - } catch (SlotListException | JSONException | HexException e) { + } catch (SlotListException | JSONException | EncodingException e) { throw new VaultFileException(e); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/slots/Slot.java b/app/src/main/java/com/beemdevelopment/aegis/vault/slots/Slot.java index 0c29982a..c0f35343 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/slots/Slot.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/slots/Slot.java @@ -5,8 +5,8 @@ import com.beemdevelopment.aegis.crypto.CryptResult; import com.beemdevelopment.aegis.crypto.CryptoUtils; import com.beemdevelopment.aegis.crypto.MasterKey; import com.beemdevelopment.aegis.crypto.SCryptParameters; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.encoding.Hex; -import com.beemdevelopment.aegis.encoding.HexException; import com.beemdevelopment.aegis.util.UUIDMap; import org.json.JSONException; @@ -144,7 +144,7 @@ public abstract class Slot extends UUIDMap.Value { default: throw new SlotException("unrecognized slot type"); } - } catch (JSONException | HexException e) { + } catch (JSONException | EncodingException e) { throw new SlotException(e); } diff --git a/app/src/test/java/com/beemdevelopment/aegis/SCryptTest.java b/app/src/test/java/com/beemdevelopment/aegis/SCryptTest.java index 2483aa9e..12a9afd3 100644 --- a/app/src/test/java/com/beemdevelopment/aegis/SCryptTest.java +++ b/app/src/test/java/com/beemdevelopment/aegis/SCryptTest.java @@ -2,8 +2,8 @@ package com.beemdevelopment.aegis; import com.beemdevelopment.aegis.crypto.CryptoUtils; import com.beemdevelopment.aegis.crypto.SCryptParameters; +import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.encoding.Hex; -import com.beemdevelopment.aegis.encoding.HexException; import org.junit.jupiter.api.Test; @@ -15,7 +15,7 @@ import static org.junit.jupiter.api.Assertions.*; public class SCryptTest { @Test - public void testTrailingNullCollision() throws HexException { + public void testTrailingNullCollision() throws EncodingException { byte[] salt = new byte[0]; SCryptParameters params = new SCryptParameters( CryptoUtils.CRYPTO_SCRYPT_N, diff --git a/app/src/test/java/com/beemdevelopment/aegis/TOTPTest.java b/app/src/test/java/com/beemdevelopment/aegis/TOTPTest.java index 58bad037..3a9653da 100644 --- a/app/src/test/java/com/beemdevelopment/aegis/TOTPTest.java +++ b/app/src/test/java/com/beemdevelopment/aegis/TOTPTest.java @@ -2,14 +2,14 @@ package com.beemdevelopment.aegis; import com.beemdevelopment.aegis.crypto.otp.OTP; import com.beemdevelopment.aegis.crypto.otp.TOTP; -import com.beemdevelopment.aegis.encoding.HexException; import org.junit.jupiter.api.Test; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; public class TOTPTest { private static class Vector { @@ -66,7 +66,7 @@ public class TOTPTest { }; @Test - public void vectorsMatch() throws NoSuchAlgorithmException, InvalidKeyException, HexException { + public void vectorsMatch() throws NoSuchAlgorithmException, InvalidKeyException { for (Vector vector : _vectors) { byte[] seed;