From 01feaa2ecc4e99be6b538d2b1b5fafe850afe132 Mon Sep 17 00:00:00 2001 From: Santiago Garcia Mantinan <43165226+mantinan@users.noreply.github.com> Date: Fri, 7 Aug 2020 11:53:09 +0200 Subject: [PATCH 1/4] Second attempt to port our MOTP implementation to an up to date andOTP. This has been lagging around due to several things. I have also struggled to get my branch in sync with master, so I have built patches and applied them directly to mater here. Let's see if this time I can finally get this pushed and submit a pull request. --- .../Activities/IntroScreenActivity.java | 4 +- .../flocke/andotp/Database/Entry.java | 53 +- .../andotp/Dialogs/ManualEntryDialog.java | 13 +- .../flocke/andotp/Utilities/MD5.java | 515 ++++++++++++++++++ .../andotp/Utilities/TokenCalculator.java | 12 + .../flocke/andotp/Utilities/UIHelper.java | 11 +- .../andotp/View/EntriesCardAdapter.java | 68 +++ .../flocke/andotp/View/EntryViewHolder.java | 9 + .../res/layout/component_card_compact.xml | 2 + .../res/layout/component_card_default.xml | 2 + .../main/res/layout/component_card_full.xml | 2 + app/src/main/res/menu/menu_popup.xml | 5 + .../main/res/values-ar-rSA/strings_main.xml | 3 + .../main/res/values-bg-rBG/strings_main.xml | 3 + .../main/res/values-ca-rES/strings_main.xml | 3 + .../main/res/values-cs-rCZ/strings_main.xml | 3 + .../main/res/values-de-rDE/strings_main.xml | 3 + .../main/res/values-el-rGR/strings_main.xml | 3 + .../main/res/values-es-rES/strings_main.xml | 3 + .../main/res/values-fa-rIR/strings_main.xml | 3 + .../main/res/values-fr-rFR/strings_main.xml | 3 + .../main/res/values-gl-rES/strings_main.xml | 3 + .../main/res/values-hi-rIN/strings_main.xml | 3 + .../main/res/values-hu-rHU/strings_main.xml | 3 + .../main/res/values-it-rIT/strings_main.xml | 3 + .../main/res/values-ja-rJP/strings_main.xml | 3 + .../main/res/values-nl-rNL/strings_main.xml | 3 + .../main/res/values-pl-rPL/strings_main.xml | 3 + .../main/res/values-pt-rBR/strings_main.xml | 3 + .../main/res/values-ru-rRU/strings_main.xml | 3 + .../main/res/values-sl-rSI/strings_main.xml | 3 + .../main/res/values-sv-rSE/strings_main.xml | 3 + .../main/res/values-tr-rTR/strings_main.xml | 3 + .../main/res/values-uk-rUA/strings_main.xml | 3 + .../main/res/values-zh-rCN/strings_main.xml | 3 + .../main/res/values-zh-rTW/strings_main.xml | 3 + app/src/main/res/values/strings_main.xml | 3 + 37 files changed, 762 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/org/shadowice/flocke/andotp/Utilities/MD5.java diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Activities/IntroScreenActivity.java b/app/src/main/java/org/shadowice/flocke/andotp/Activities/IntroScreenActivity.java index 31724ea9..9d6c3973 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Activities/IntroScreenActivity.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Activities/IntroScreenActivity.java @@ -210,7 +210,7 @@ public class IntroScreenActivity extends IntroActivity { } }); - selection.setSelection(selectionMapping.indexOfValue(Constants.EncryptionType.PASSWORD)); + selection.setSelection(selectionMapping.indexOfValue(Constants.EncryptionType.KEYSTORE)); return root; } @@ -466,7 +466,7 @@ public class IntroScreenActivity extends IntroActivity { passwordInput.addTextChangedListener(textWatcher); passwordConfirm.addTextChangedListener(textWatcher); - selection.setSelection(selectionMapping.indexOfValue(Constants.AuthMethod.PASSWORD)); + selection.setSelection(selectionMapping.indexOfValue(Constants.AuthMethod.NONE)); return root; } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java b/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java index 32acedb3..84b387ed 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java @@ -40,11 +40,12 @@ import java.util.Objects; public class Entry { public enum OTPType { - TOTP, HOTP, STEAM + TOTP, HOTP, MOTP, STEAM } private static final OTPType DEFAULT_TYPE = OTPType.TOTP; private static final int DEFAULT_PERIOD = 30; + private static final String MOTP_NO_PIN_CODE = "PINREQ"; private static final String JSON_SECRET = "secret"; private static final String JSON_ISSUER = "issuer"; @@ -79,6 +80,7 @@ public class Entry { public static final int COLOR_RED = 1; private static final int EXPIRY_TIME = 8; private int color = COLOR_DEFAULT; + private String pin = ""; public Entry(){} @@ -106,6 +108,16 @@ public class Entry { setThumbnailFromIssuer(issuer); } + public Entry(OTPType type, String secret, String issuer, String label, List tags) { + this.type = type; + this.secret = secret.getBytes(); + this.issuer = issuer; + this.label = label; + this.tags = tags; + this.period = TokenCalculator.TOTP_DEFAULT_PERIOD; + setThumbnailFromIssuer(issuer); + } + public Entry(String contents) throws Exception { contents = contents.replaceFirst("otpauth", "http"); Uri uri = Uri.parse(contents); @@ -122,6 +134,9 @@ public class Entry { case "hotp": type = OTPType.HOTP; break; + case "motp": + type = OTPType.MOTP; + break; case "steam": type = OTPType.STEAM; break; @@ -155,7 +170,11 @@ public class Entry { this.issuer = issuer; this.label = label; - this.secret = new Base32().decode(secret.toUpperCase()); + if(type == OTPType.MOTP) { + this.secret = secret.getBytes(); + }else{ + this.secret = new Base32().decode(secret.toUpperCase()); + } if (digits != null) { this.digits = Integer.parseInt(digits); @@ -323,7 +342,7 @@ public class Entry { } public boolean isTimeBased() { - return type == OTPType.TOTP || type == OTPType.STEAM; + return type == OTPType.TOTP || type == OTPType.STEAM || type == OTPType.MOTP; } public boolean isCounterBased() { return type == OTPType.HOTP; } @@ -444,7 +463,19 @@ public class Entry { return currentOTP; } + public String getPin() { + return pin; + } + + public void setPin(String pin) { + this.pin = pin; + } + public boolean updateOTP() { + return updateOTP(false); + } + + public boolean updateOTP(boolean updateNow) { if (type == OTPType.TOTP || type == OTPType.STEAM) { long time = System.currentTimeMillis() / 1000; long counter = time / this.getPeriod(); @@ -465,6 +496,22 @@ public class Entry { } else if (type == OTPType.HOTP) { currentOTP = TokenCalculator.HOTP(secret, counter, digits, algorithm); return true; + } else if (type == OTPType.MOTP) { + long time = System.currentTimeMillis() / 1000; + long counter = time / this.getPeriod(); + if (counter > last_update || updateNow) { + String currentPin = this.getPin(); + if (currentPin.isEmpty()) { + currentOTP = MOTP_NO_PIN_CODE; + } else { + currentOTP = TokenCalculator.MOTP(currentPin, new String(this.secret)); + } + last_update = counter; + setColor(COLOR_DEFAULT); + return true; + } else { + return false; + } } else { return false; } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Dialogs/ManualEntryDialog.java b/app/src/main/java/org/shadowice/flocke/andotp/Dialogs/ManualEntryDialog.java index 0b0ff63b..7ef6d77a 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Dialogs/ManualEntryDialog.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Dialogs/ManualEntryDialog.java @@ -81,6 +81,7 @@ public class ManualEntryDialog { final LinearLayout periodLayout = inputView.findViewById(R.id.manual_layout_period); final Spinner algorithmInput = inputView.findViewById(R.id.manual_algorithm); final Button tagsInput = inputView.findViewById(R.id.manual_tags); + final Button expandButton = inputView.findViewById(R.id.dialog_expand_button); final ArrayAdapter algorithmAdapter = new ArrayAdapter<>(callingActivity, android.R.layout.simple_expandable_list_item_1, TokenCalculator.HashAlgorithm.values()); final ArrayAdapter typeAdapter = new ArrayAdapter<>(callingActivity, android.R.layout.simple_expandable_list_item_1, Entry.OTPType.values()); @@ -100,6 +101,7 @@ public class ManualEntryDialog { if (type == Entry.OTPType.STEAM) { counterLayout.setVisibility(View.GONE); periodLayout.setVisibility(View.VISIBLE); + expandButton.setVisibility(View.VISIBLE); digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.STEAM_DEFAULT_DIGITS)); periodInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_PERIOD)); @@ -111,6 +113,7 @@ public class ManualEntryDialog { } else if (type == Entry.OTPType.TOTP) { counterLayout.setVisibility(View.GONE); periodLayout.setVisibility(View.VISIBLE); + expandButton.setVisibility(View.VISIBLE); digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS)); digitsInput.setEnabled(isNewEntry); @@ -119,11 +122,19 @@ public class ManualEntryDialog { } else if (type == Entry.OTPType.HOTP) { counterLayout.setVisibility(View.VISIBLE); periodLayout.setVisibility(View.GONE); + expandButton.setVisibility(View.VISIBLE); digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS)); digitsInput.setEnabled(isNewEntry); periodInput.setEnabled(isNewEntry); algorithmInput.setEnabled(isNewEntry); + }else if (type == Entry.OTPType.MOTP) { + counterLayout.setVisibility(View.GONE); + periodLayout.setVisibility(View.VISIBLE); + + digitsInput.setText(String.format(Locale.US, "%d", TokenCalculator.TOTP_DEFAULT_DIGITS)); + expandButton.setVisibility(View.GONE); + algorithmInput.setEnabled(isNewEntry); } } @@ -163,8 +174,6 @@ public class ManualEntryDialog { } }); - final Button expandButton = inputView.findViewById(R.id.dialog_expand_button); - // Dirty fix for the compound drawable to avoid crashes on KitKat expandButton.setCompoundDrawablesWithIntrinsicBounds(null, null, callingActivity.getResources().getDrawable(R.drawable.ic_arrow_down_accent), null); diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/MD5.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/MD5.java new file mode 100644 index 00000000..b1985f57 --- /dev/null +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/MD5.java @@ -0,0 +1,515 @@ +/* + * $Header: /u/users20/santtu/src/java/MD5/RCS/MD5.java,v 1.5 1996/12/12 10:47:02 santtu Exp $ + * + * MD5 in Java JDK Beta-2 + * written Santeri Paavolainen, Helsinki Finland 1996 + * (c) Santeri Paavolainen, Helsinki Finland 1996 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * See http://www.cs.hut.fi/~santtu/java/ for more information on this + * class. + * + * This is rather straight re-implementation of the reference implementation + * given in RFC1321 by RSA. + * + * Passes MD5 test suite as defined in RFC1321. + * + * + * This Java class has been derived from the RSA Data Security, Inc. MD5 + * Message-Digest Algorithm and its reference implementation. + * + * + * Revision 1.6 minor changes for j2me, 2003, Matthias Straub + * + * $Log: MD5.java,v $ + * Revision 1.5 1996/12/12 10:47:02 santtu + * Changed GPL to LGPL + * + * Revision 1.4 1996/12/12 10:30:02 santtu + * Some typos, State -> MD5State etc. + * + * Revision 1.3 1996/04/15 07:28:09 santtu + * Added GPL statemets, and RSA derivate stametemetsnnts. + * + * Revision 1.2 1996/03/04 08:05:48 santtu + * Added offsets to Update method + * + * Revision 1.1 1996/01/07 20:51:59 santtu + * Initial revision + * + */ + +/** + * Contains internal state of the MD5 class + */ +package org.shadowice.flocke.andotp.Utilities; + +class MD5State { + /** + * 128-byte state + */ + int state[]; + + /** + * 64-bit character count (could be true Java long?) + */ + int count[]; + + /** + * 64-byte buffer (512 bits) for storing to-be-hashed characters + */ + byte buffer[]; + + public MD5State() { + buffer = new byte[64]; + count = new int[2]; + state = new int[4]; + + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + + count[0] = count[1] = 0; + } + + /** Create this State as a copy of another state */ + public MD5State (MD5State from) { + this(); + + int i; + + for (i = 0; i < buffer.length; i++) + this.buffer[i] = from.buffer[i]; + + for (i = 0; i < state.length; i++) + this.state[i] = from.state[i]; + + for (i = 0; i < count.length; i++) + this.count[i] = from.count[i]; + } +}; + +/** + * Implementation of RSA's MD5 hash generator + * + * @version $Revision: 1.5 $ + * @author Santeri Paavolainen + */ + +public class MD5 { + /** + * MD5 state + */ + MD5State state; + + /** + * If Final() has been called, finals is set to the current finals + * state. Any Update() causes this to be set to null. + */ + MD5State finals; + + /** + * Padding for Final() + */ + static byte padding[] = { + (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + /** + * Initialize MD5 internal state (object can be reused just by + * calling Init() after every Final() + */ + public synchronized void Init () { + state = new MD5State(); + finals = null; + } + + /** + * Class constructor + */ + public MD5 () { + this.Init(); + } + + /** + * Initialize class, and update hash with ob.toString() + * + * @param ob Object, ob.toString() is used to update hash + * after initialization + */ + public MD5 (Object ob) { + this(); + Update(ob.toString()); + } + + private int rotate_left (int x, int n) { + return (x << n) | (x >>> (32 - n)); + } + + /* I wonder how many loops and hoops you'll have to go through to + get unsigned add for longs in java */ + + private int uadd (int a, int b) { + long aa, bb; + aa = ((long) a) & 0xffffffffL; + bb = ((long) b) & 0xffffffffL; + + aa += bb; + + return (int) (aa & 0xffffffffL); + } + + private int uadd (int a, int b, int c) { + return uadd(uadd(a, b), c); + } + + private int uadd (int a, int b, int c, int d) { + return uadd(uadd(a, b, c), d); + } + + private int FF (int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, ((b & c) | (~b & d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int GG (int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, ((b & d) | (c & ~d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int HH (int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, (b ^ c ^ d), x, ac); + return uadd(rotate_left(a, s) , b); + } + + private int II (int a, int b, int c, int d, int x, int s, int ac) { + a = uadd(a, (c ^ (b | ~d)), x, ac); + return uadd(rotate_left(a, s), b); + } + + private int[] Decode (byte buffer[], int len, int shift) { + int out[]; + int i, j; + + out = new int[16]; + + for (i = j = 0; j < len; i++, j += 4) { + out[i] = ((int) (buffer[j + shift] & 0xff)) | + (((int) (buffer[j + 1 + shift] & 0xff)) << 8) | + (((int) (buffer[j + 2 + shift] & 0xff)) << 16) | + (((int) (buffer[j + 3 + shift] & 0xff)) << 24); + +/* System.out.println("out[" + i + "] = \t" + + ((int) buffer[j + 0 + shift] & 0xff) + "\t|\t" + + ((int) buffer[j + 1 + shift] & 0xff) + "\t|\t" + + ((int) buffer[j + 2 + shift] & 0xff) + "\t|\t" + + ((int) buffer[j + 3 + shift] & 0xff));*/ + } + + return out; + } + + private void Transform (MD5State state, byte buffer[], int shift) { + int + a = state.state[0], + b = state.state[1], + c = state.state[2], + d = state.state[3], + x[]; + + x = Decode(buffer, 64, shift); + + /* Round 1 */ + a = FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ + d = FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ + c = FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ + b = FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ + a = FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ + d = FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ + c = FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ + b = FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ + a = FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ + d = FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ + c = FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ + b = FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ + a = FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ + d = FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ + c = FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ + b = FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ + + /* Round 2 */ + a = GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ + d = GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ + c = GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ + b = GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ + a = GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ + d = GG (d, a, b, c, x[10], 9, 0x2441453); /* 22 */ + c = GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ + b = GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ + a = GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ + d = GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ + c = GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ + b = GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ + a = GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ + d = GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ + c = GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ + b = GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + a = HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ + d = HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ + c = HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ + b = HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ + a = HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ + d = HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ + c = HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ + b = HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ + a = HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ + d = HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ + c = HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ + b = HH (b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ + a = HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ + d = HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ + c = HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ + b = HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + a = II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ + d = II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ + c = II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ + b = II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ + a = II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ + d = II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ + c = II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ + b = II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ + a = II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ + d = II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ + c = II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ + b = II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ + a = II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ + d = II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ + c = II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ + b = II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ + + state.state[0] += a; + state.state[1] += b; + state.state[2] += c; + state.state[3] += d; + } + + /** + * Updates hash with the bytebuffer given (using at maximum length bytes from + * that buffer) + * + * @param stat Which state is updated + * @param buffer Array of bytes to be hashed + * @param offset Offset to buffer array + * @param length Use at maximum `length' bytes (absolute + * maximum is buffer.length) + */ + public void Update (MD5State stat, byte buffer[], int offset, int length) { + int index, partlen, i, start; + +/* System.out.print("Offset = " + offset + "\tLength = " + length + "\t"); + System.out.print("Buffer = "); + for (i = 0; i < buffer.length; i++) + System.out.print((int) (buffer[i] & 0xff) + " "); + System.out.print("\n");*/ + + finals = null; + + /* Length can be told to be shorter, but not inter */ + if ((length - offset)> buffer.length) + length = buffer.length - offset; + + /* compute number of bytes mod 64 */ + index = (int) (stat.count[0] >>> 3) & 0x3f; + + if ((stat.count[0] += (length << 3)) < + (length << 3)) + stat.count[1]++; + + stat.count[1] += length >>> 29; + + partlen = 64 - index; + + if (length >= partlen) { + for (i = 0; i < partlen; i++) + stat.buffer[i + index] = buffer[i + offset]; + + Transform(stat, stat.buffer, 0); + + for (i = partlen; (i + 63) < length; i+= 64) + Transform(stat, buffer, i); + + index = 0; + } else + i = 0; + + /* buffer remaining input */ + if (i < length) { + start = i; + for (; i < length; i++) + stat.buffer[index + i - start] = buffer[i + offset]; + } + } + + /* + * Update()s for other datatypes than byte[] also. Update(byte[], int) + * is only the main driver. + */ + + /** + * Plain update, updates this object + */ + + public void Update (byte buffer[], int offset, int length) { + Update(this.state, buffer, offset, length); + } + + public void Update (byte buffer[], int length) { + Update(this.state, buffer, 0, length); + } + + /** + * Updates hash with given array of bytes + * + * @param buffer Array of bytes to use for updating the hash + */ + public void Update (byte buffer[]) { + Update(buffer, 0, buffer.length); + } + + /** + * Updates hash with a single byte + * + * @param b Single byte to update the hash + */ + public void Update (byte b) { + byte buffer[] = new byte[1]; + buffer[0] = b; + + Update(buffer, 1); + } + + /** + * Update buffer with given string. + * + * @param s String to be update to hash (is used as + * s.getBytes()) + */ + public void Update (String s) { + byte chars[]; + + chars = new byte[s.length()]; + chars=s.getBytes(); + + Update(chars, chars.length); + } + + /** + * Update buffer with a single integer (only & 0xff part is used, + * as a byte) + * + * @param i Integer value, which is then converted to + * byte as i & 0xff + */ + + public void Update (int i) { + Update((byte) (i & 0xff)); + } + + private byte[] Encode (int input[], int len) { + int i, j; + byte out[]; + + out = new byte[len]; + + for (i = j = 0; j < len; i++, j += 4) { + out[j] = (byte) (input[i] & 0xff); + out[j + 1] = (byte) ((input[i] >>> 8) & 0xff); + out[j + 2] = (byte) ((input[i] >>> 16) & 0xff); + out[j + 3] = (byte) ((input[i] >>> 24) & 0xff); + } + + return out; + } + + /** + * Returns array of bytes (16 bytes) representing hash as of the + * current state of this object. Note: getting a hash does not + * invalidate the hash object, it only creates a copy of the real + * state which is finalized. + * + * @return Array of 16 bytes, the hash of all updated bytes + */ + public synchronized byte[] Final () { + byte bits[]; + int index, padlen; + MD5State fin; + + if (finals == null) { + fin = new MD5State(state); + + bits = Encode(fin.count, 8); + + index = (int) ((fin.count[0] >>> 3) & 0x3f); + padlen = (index < 56) ? (56 - index) : (120 - index); + + Update(fin, padding, 0, padlen); + /**/ + Update(fin, bits, 0, 8); + + /* Update() sets finalds to null */ + finals = fin; + } + + return Encode(finals.state, 16); + } + + /** + * Turns array of bytes into string representing each byte as + * unsigned hex number. + * + * @param hash Array of bytes to convert to hex-string + * @return Generated hex string + */ + public static String asHex (byte hash[]) { + StringBuffer buf = new StringBuffer(hash.length * 2); + int i; + + for (i = 0; i < hash.length; i++) { + if (((int) hash[i] & 0xff) < 0x10) + buf.append("0"); + + buf.append(Long.toString((int) hash[i] & 0xff, 16)); + } + + return buf.toString(); + } + + /** + * Returns 32-character hex representation of this objects hash + * + * @return String of this object's hash + */ + public String asHex () { + return asHex(this.Final()); + } +} diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java index 11a5b7ea..023194ce 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java @@ -26,6 +26,7 @@ package org.shadowice.flocke.andotp.Utilities; import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.util.Date; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -115,4 +116,15 @@ public class TokenCalculator { return r; } + + public static String MOTP(String PIN, String secret) + { + Date dateNow = new Date(); + String epoch = "" + (dateNow.getTime()); + epoch = epoch.substring(0, epoch.length() - 4); + String otp = epoch + secret + PIN; + MD5 hash = new MD5(otp); + otp = hash.asHex().substring(0, 6); + return otp; + } } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/UIHelper.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/UIHelper.java index 6650ad15..8cd2e638 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/UIHelper.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/UIHelper.java @@ -48,10 +48,17 @@ public class UIHelper { .show(); } - public static void showKeyboard(Context context, View view) { + public static void showKeyboard(Context context, View view){ + showKeyboard(context,view,false); + } + + public static void showKeyboard(Context context, View view, Boolean showForced) { if (view != null) { InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(view, 0); + if(showForced) + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); + else + imm.showSoftInput(view, 0); } } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java b/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java index 83906356..14b4f8c3 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java @@ -36,11 +36,14 @@ import android.text.Editable; import android.text.InputType; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.method.PasswordTransformationMethod; import android.view.LayoutInflater; +import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.Button; import android.widget.EditText; @@ -66,6 +69,7 @@ import org.shadowice.flocke.andotp.Utilities.EncryptionHelper; import org.shadowice.flocke.andotp.Utilities.EntryThumbnail; import org.shadowice.flocke.andotp.Utilities.Settings; import org.shadowice.flocke.andotp.Utilities.Tools; +import org.shadowice.flocke.andotp.Utilities.UIHelper; import org.shadowice.flocke.andotp.View.ItemTouchHelper.ItemTouchHelperAdapter; import java.text.Collator; @@ -97,6 +101,8 @@ public class EntriesCardAdapter extends RecyclerView.Adapter private TagsAdapter tagsFilterAdapter; private Settings settings; + private static final int ESTABLISH_PIN_MENU_INDEX = 4; + public EntriesCardAdapter(Context context, TagsAdapter tagsFilterAdapter) { this.context = context; this.tagsFilterAdapter = tagsFilterAdapter; @@ -355,6 +361,14 @@ public class EntriesCardAdapter extends RecyclerView.Adapter public void onCounterLongPressed(int position) { setCounter(position); } + + @Override + public void onItemClickListener(int position) { + final Entry entry = displayedEntries.get(position); + if(entry.getType() == Entry.OTPType.MOTP && entry.getPin().isEmpty()){ + establishPIN(position); + } + } }); return viewHolder; @@ -620,6 +634,52 @@ public class EntriesCardAdapter extends RecyclerView.Adapter alert.show(); } + public void establishPIN(final int pos) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + + int marginSmall = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_small); + int marginMedium = context.getResources().getDimensionPixelSize(R.dimen.activity_margin_medium); + + final EditText input = new EditText(context); + input.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + input.setRawInputType(InputType.TYPE_NUMBER_VARIATION_PASSWORD | InputType.TYPE_CLASS_NUMBER); + input.setText(displayedEntries.get(pos).getPin()); + input.setSingleLine(); + input.requestFocus(); + input.setTransformationMethod(new PasswordTransformationMethod()); + UIHelper.showKeyboard(context,input,true); + + FrameLayout container = new FrameLayout(context); + container.setPaddingRelative(marginMedium, marginSmall, marginMedium, 0); + container.addView(input); + + builder.setTitle(R.string.dialog_title_pin) + .setCancelable(false) + .setView(container) + .setPositiveButton(R.string.button_accept, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + int realIndex = getRealIndex(pos); + String newPin = input.getEditableText().toString(); + + displayedEntries.get(pos).setPin(newPin); + Entry e = entries.get(realIndex); + e.setPin(newPin); + e.updateOTP(true); + notifyDataSetChanged(); + UIHelper.hideKeyboard(context,input); + } + }) + .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + UIHelper.hideKeyboard(context,input); + } + }) + .create() + .show(); + } + public void removeItem(final int pos) { AlertDialog.Builder builder = new AlertDialog.Builder(context); @@ -682,6 +742,11 @@ public class EntriesCardAdapter extends RecyclerView.Adapter MenuInflater inflate = popup.getMenuInflater(); inflate.inflate(R.menu.menu_popup, popup.getMenu()); + if (displayedEntries.get(pos).getType() == Entry.OTPType.MOTP){ + MenuItem item = popup.getMenu().getItem(ESTABLISH_PIN_MENU_INDEX); + item.setVisible(true); + } + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { @@ -693,6 +758,9 @@ public class EntriesCardAdapter extends RecyclerView.Adapter } else if(id == R.id.menu_popup_changeImage) { changeThumbnail(pos); return true; + } else if (id == R.id.menu_popup_establishPin) { + establishPIN(pos); + return true; } else if (id == R.id.menu_popup_remove) { removeItem(pos); return true; diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java b/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java index fec6d035..5ceb9b14 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java @@ -154,6 +154,14 @@ public class EntryViewHolder extends RecyclerView.ViewHolder } }); + itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (callback != null) + callback.onItemClickListener(getAdapterPosition()); + } + }); + setTapToReveal(tapToReveal); } @@ -328,6 +336,7 @@ public class EntryViewHolder extends RecyclerView.ViewHolder void onCounterClicked(int position); void onCounterLongPressed(int position); + void onItemClickListener(int position); } /** * Updates the color of OTP to red (if expiring) or default color (if new OTP) diff --git a/app/src/main/res/layout/component_card_compact.xml b/app/src/main/res/layout/component_card_compact.xml index 2fef3704..b3b06071 100644 --- a/app/src/main/res/layout/component_card_compact.xml +++ b/app/src/main/res/layout/component_card_compact.xml @@ -7,6 +7,8 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/activity_margin_xxsmall" android:layout_marginBottom="@dimen/activity_margin_xxsmall" + android:clickable="true" + android:foreground="?android:attr/selectableItemBackground" app:contentPadding="0dp" style="?attr/cardStyle"> diff --git a/app/src/main/res/layout/component_card_default.xml b/app/src/main/res/layout/component_card_default.xml index 5a0556ac..f7410884 100644 --- a/app/src/main/res/layout/component_card_default.xml +++ b/app/src/main/res/layout/component_card_default.xml @@ -7,6 +7,8 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/activity_margin_xsmall" android:layout_marginBottom="@dimen/activity_margin_xsmall" + android:clickable="true" + android:foreground="?android:attr/selectableItemBackground" app:contentPadding="0dp" style="?attr/cardStyle"> diff --git a/app/src/main/res/layout/component_card_full.xml b/app/src/main/res/layout/component_card_full.xml index dde1bae6..e1943bd3 100644 --- a/app/src/main/res/layout/component_card_full.xml +++ b/app/src/main/res/layout/component_card_full.xml @@ -8,6 +8,8 @@ android:layout_marginTop="@dimen/activity_margin_xsmall" android:layout_marginBottom="@dimen/activity_margin_xsmall" app:contentPadding="0dp" + android:clickable="true" + android:foreground="?android:attr/selectableItemBackground" style="?attr/cardStyle"> + + diff --git a/app/src/main/res/values-ar-rSA/strings_main.xml b/app/src/main/res/values-ar-rSA/strings_main.xml index afe0c71c..37e9b1b4 100644 --- a/app/src/main/res/values-ar-rSA/strings_main.xml +++ b/app/src/main/res/values-ar-rSA/strings_main.xml @@ -10,6 +10,7 @@ كافة العلامات بدون علامات رمز كيو آر مِن صورة + اقبل %d ثا @@ -45,6 +46,7 @@ تغيير الصورة حذف Show QR Code + أدخل رمز PIN أخفقت المصادقة، الرجاء إعادة المحاولة ! أخفقت عملية المصادقة، جارٍ إغلاق التطبيق! @@ -73,6 +75,7 @@ QR Code Deprecation notice أدخل كلمة المرور + دبوس أدخل كلمة المرور تأكيد كلمة المرور الرجاء إدخال بيانات الإعتماد الخاصة بجهازك لتشغيل التطبيق. diff --git a/app/src/main/res/values-bg-rBG/strings_main.xml b/app/src/main/res/values-bg-rBG/strings_main.xml index 22e9705a..2ba9f2d1 100644 --- a/app/src/main/res/values-bg-rBG/strings_main.xml +++ b/app/src/main/res/values-bg-rBG/strings_main.xml @@ -10,6 +10,7 @@ Всички маркери Няма маркери QR код от изображение + приемам %d сек @@ -45,6 +46,7 @@ Промяна на изображението Премахване Показване на QR кода + Въведете ПИН код Неуспешно удостоверяване. Моля, опитайте отново! Неуспешно удостоверяване, затваряне на andOTP! @@ -73,6 +75,7 @@ QR код Остаряло известие Въведете парола + PIN Въведете парола Потвърдете паролата Моля, въведете идентификационните данни на устройството си, за да стартирате andOTP. diff --git a/app/src/main/res/values-ca-rES/strings_main.xml b/app/src/main/res/values-ca-rES/strings_main.xml index 709d06f1..8ab95425 100644 --- a/app/src/main/res/values-ca-rES/strings_main.xml +++ b/app/src/main/res/values-ca-rES/strings_main.xml @@ -10,6 +10,7 @@ Totes les etiquetes Sense etiquetes QR code from image + Acceptar %d s @@ -45,6 +46,7 @@ Canvia la imatge Suprimeix Show QR Code + Introduir PIN Error d\'autenticació. Torneu-ho a intentar! L\'autenticació ha fallat, andOTP es tancarà! @@ -73,6 +75,7 @@ QR Code Deprecation notice Introduïu la contrasenya + PIN Introduïu la contrasenya Confirmeu la contrasenya Per favor, introduïu les vostres credencials per a iniciar andOTP. diff --git a/app/src/main/res/values-cs-rCZ/strings_main.xml b/app/src/main/res/values-cs-rCZ/strings_main.xml index 880df42c..701cafee 100644 --- a/app/src/main/res/values-cs-rCZ/strings_main.xml +++ b/app/src/main/res/values-cs-rCZ/strings_main.xml @@ -10,6 +10,7 @@ Všechny štítky Bez štítku QR kód z obrázku + Přijmout %d s @@ -45,6 +46,7 @@ Změnit obrázek Smazat Ukaž QR kód + Zadejte PIN Chyba ověření, zkuste to prosím znovu! Ověření se nezdařilo, zavírám andOTP! @@ -73,6 +75,7 @@ QR kód Oznámení o ukončení podpory Zadejte heslo + PIN Zadejte heslo Potvrďte heslo Prosím zadejte heslo zařízení ke spuštění andOTP. diff --git a/app/src/main/res/values-de-rDE/strings_main.xml b/app/src/main/res/values-de-rDE/strings_main.xml index 7097975a..1aab1a56 100644 --- a/app/src/main/res/values-de-rDE/strings_main.xml +++ b/app/src/main/res/values-de-rDE/strings_main.xml @@ -10,6 +10,7 @@ Alle Marker Keine Marker QR-Code aus Bild + Akzeptiere %d s @@ -45,6 +46,7 @@ Bild ändern Entfernen Zeige QR-Code + PIN einstellen Authentifizierung fehlgeschlagen, bitte erneut versuchen! Authentifizierung fehlgeschlagen, andOTP wird geschlossen! @@ -73,6 +75,7 @@ QR-Code Hinweis Passwort eingeben + PIN Passwort eingeben Passwort bestätigen Bitte geben Sie die Anmeldeinformationen Ihres Geräts ein, um andOTP zu starten. diff --git a/app/src/main/res/values-el-rGR/strings_main.xml b/app/src/main/res/values-el-rGR/strings_main.xml index 32af516a..8d8b1fc8 100644 --- a/app/src/main/res/values-el-rGR/strings_main.xml +++ b/app/src/main/res/values-el-rGR/strings_main.xml @@ -10,6 +10,7 @@ Όλες οι ετικέτες Χωρίς ετικέτες Κώδικας QR από εικόνα + Αποδοχή %d\" @@ -45,6 +46,7 @@ Αλλαγή εικόνας Διαγραφή Show QR Code + Ορίστε το PIN Η ταυτοποίηση απέτυχε. Παρακαλώ προσπάθησε ξανά! Απέτυχε ο έλεγχος ταυτότητας, κλείνει το andOTP! @@ -74,6 +76,7 @@ Deprecation notice Εισάγετε κωδικό Εισάγετε κωδικό + PIN Επιβεβαίωση κωδικού Παρακαλούμε εισαγάγετε τα διαπιστευτήριά σας για να ανοίξετε το andOTP. Σίγουρα θέλετε να αφαιρέσετε το λογαριασμό \"%1$s\"; diff --git a/app/src/main/res/values-es-rES/strings_main.xml b/app/src/main/res/values-es-rES/strings_main.xml index 269e7d78..205158d3 100644 --- a/app/src/main/res/values-es-rES/strings_main.xml +++ b/app/src/main/res/values-es-rES/strings_main.xml @@ -10,6 +10,7 @@ Todas las etiquetas Sin etiquetas Imagen del código QR + Aceptar %d s @@ -45,6 +46,7 @@ Cambiar imagen Eliminar Mostrar código QR + Introducir pin La autentificación ha fallado, por favor inténtelo otra vez! La autenticación ha fallado, cerrando andOTP! @@ -73,6 +75,7 @@ Código QR Aviso de deprecación Introduzca la contraseña + PIN Introduzca la contraseña Confirmar contraseña Por favor, introduce los credenciales del dispositivo para iniciar andOTP. diff --git a/app/src/main/res/values-fa-rIR/strings_main.xml b/app/src/main/res/values-fa-rIR/strings_main.xml index d12c96a6..349e5ca6 100644 --- a/app/src/main/res/values-fa-rIR/strings_main.xml +++ b/app/src/main/res/values-fa-rIR/strings_main.xml @@ -10,6 +10,7 @@ همه تگ‌ها بدون تگ کد QR از تصویر + قبول کنید %d ثانیه @@ -45,6 +46,7 @@ تغییر تصویر حذف نمایش کد QR + پین را تنظیم کنید احراز هویت ناموفق بود، لطفا دوباره تلاش کنید! احراز هویت ناموفق بود، در حال بستن andOTP! @@ -73,6 +75,7 @@ کد QR اخطار استهلاک گذرواژه را وارد کنید + پین گذرواژه را وارد کنید تایید گذرواژه برای شروع andOTP لطفا اعتبارنامه دستگاه خود را وارد کنید. diff --git a/app/src/main/res/values-fr-rFR/strings_main.xml b/app/src/main/res/values-fr-rFR/strings_main.xml index 23d6d333..02fafad4 100644 --- a/app/src/main/res/values-fr-rFR/strings_main.xml +++ b/app/src/main/res/values-fr-rFR/strings_main.xml @@ -10,6 +10,7 @@ Tous les tags Aucun tag QR-code à partir d\'une image + Accepter %d s @@ -45,6 +46,7 @@ Modifier l\'image Supprimer Montrer le QR Code + Définir le code PIN Échec d\'authentification, veuillez réessayer ! Échec d\'authentification, fermeture d\'andOTP ! @@ -73,6 +75,7 @@ QR Code Avis d\'obsolescence Saisir le mot de passe + PIN Saisir le mot de passe Confirmer le mot de passe Veuillez entrer les informations d\'identification du périphérique pour démarrer andOTP. diff --git a/app/src/main/res/values-gl-rES/strings_main.xml b/app/src/main/res/values-gl-rES/strings_main.xml index 4fefd5e0..6bac2297 100644 --- a/app/src/main/res/values-gl-rES/strings_main.xml +++ b/app/src/main/res/values-gl-rES/strings_main.xml @@ -10,6 +10,7 @@ Todas as etiquetas Sen etiquetas Código QR desde imaxe + Aceptar %d s @@ -45,6 +46,7 @@ Cambiar imaxe Eliminar Mostrar código QR + Introducir o pin Fallou a autenticación, por favor inténtao de novo! Fallou a autenticación, pechando andOTP! @@ -73,6 +75,7 @@ Código QR Aviso de abandono Introducir contrasinal + PIN Introducir contrasinal Confirmar contrasinal Introduce as credenciais do dispositivo para iniciar andOTP. diff --git a/app/src/main/res/values-hi-rIN/strings_main.xml b/app/src/main/res/values-hi-rIN/strings_main.xml index d35563b8..83213916 100644 --- a/app/src/main/res/values-hi-rIN/strings_main.xml +++ b/app/src/main/res/values-hi-rIN/strings_main.xml @@ -10,6 +10,7 @@ सभी टैग कोई टैग नहीं छवि से क्यूआर कोड + स्वीकार करना %d सेकेंड @@ -45,6 +46,7 @@ छवि बदलें हटाएं Show QR Code + पिन सेट करें प्रमाणीकरण असफल| कृपया पुन: प्रयास करें! प्रमाणीकरण विफल, समापन andOTP! @@ -73,6 +75,7 @@ QR Code Deprecation notice अपना पासवोर्ड डाले + पिन अपना पासवोर्ड डाले पासवर्ड की पुष्टि करें AndOTP शुरू करने के लिए कृपया अपनी यंत्र साख दर्ज करें। diff --git a/app/src/main/res/values-hu-rHU/strings_main.xml b/app/src/main/res/values-hu-rHU/strings_main.xml index 45b97e73..d8d34970 100644 --- a/app/src/main/res/values-hu-rHU/strings_main.xml +++ b/app/src/main/res/values-hu-rHU/strings_main.xml @@ -10,6 +10,7 @@ Összes címke Nincs címke QR-kód képből + Elfogad %d másodperc @@ -45,6 +46,7 @@ Kép módosítása Eltávolítás Show QR Code + Állítsa be a PIN-kódot A hitelesítés sikertelen, próbálja újra! A hitelesítés sikertelen, az andOTP bezárul! @@ -73,6 +75,7 @@ QR Code Deprecation notice Jelszó megadása + PIN Jelszó megadása Jelszó megerősítése Kérjük, adja meg a készülék hitelesítő adatait az andOTP indításához. diff --git a/app/src/main/res/values-it-rIT/strings_main.xml b/app/src/main/res/values-it-rIT/strings_main.xml index c31d95eb..7a17d7a0 100644 --- a/app/src/main/res/values-it-rIT/strings_main.xml +++ b/app/src/main/res/values-it-rIT/strings_main.xml @@ -10,6 +10,7 @@ Tutti i tag Nessun tag QR code da immagine + Accettare %d s @@ -45,6 +46,7 @@ Cambia Immagine Rimuovi Mostra codice QR + Imposta PIN Autenticazione non riuscita, riprova! Autenticazione non riuscita, andOTP verrà chiuso! @@ -73,6 +75,7 @@ Codice QR Avviso di deprecazione Inserisci la password + PIN Inserisci la password Conferma la password Si prega di inserire le credenziali del dispositivo per avviare andOTP. diff --git a/app/src/main/res/values-ja-rJP/strings_main.xml b/app/src/main/res/values-ja-rJP/strings_main.xml index 42ef7637..8dce59d0 100644 --- a/app/src/main/res/values-ja-rJP/strings_main.xml +++ b/app/src/main/res/values-ja-rJP/strings_main.xml @@ -10,6 +10,7 @@ すべてのタグ タグなし QR コードを画像からスキャン + 受け入れる %d 秒 @@ -45,6 +46,7 @@ 画像を変更 削除 QR コードを表示 + PINを設定 認証に失敗しました、もう一度やり直してください! 認証に失敗しました、 andOTP を終了します! @@ -73,6 +75,7 @@ QR コード サポート廃止の通知 パスワードを入力 + PIN パスワードを入力 パスワードの確認 andOTP を起動するためにデバイス認証情報を入力してください。 diff --git a/app/src/main/res/values-nl-rNL/strings_main.xml b/app/src/main/res/values-nl-rNL/strings_main.xml index 030f2c9c..df6150c4 100644 --- a/app/src/main/res/values-nl-rNL/strings_main.xml +++ b/app/src/main/res/values-nl-rNL/strings_main.xml @@ -10,6 +10,7 @@ Alle labels Geen labels QR-code van afbeelding + Accepteren %d s @@ -45,6 +46,7 @@ Afbeelding wijzigen Verwijderen Show QR Code + PIN instellen Authenticatie mislukt. Probeer opnieuw! Verificatie is mislukt, andOTP wordt afgesloten! @@ -73,6 +75,7 @@ QR Code Deprecation notice Wachtwoord invoeren + PIN Wachtwoord invoeren Wachtwoord bevestigen Voer de referenties van uw apparaat in om te beginnen met andOTP. diff --git a/app/src/main/res/values-pl-rPL/strings_main.xml b/app/src/main/res/values-pl-rPL/strings_main.xml index 03820e7e..01e353f5 100644 --- a/app/src/main/res/values-pl-rPL/strings_main.xml +++ b/app/src/main/res/values-pl-rPL/strings_main.xml @@ -10,6 +10,7 @@ Wszystkie znaczniki Brak znaczników Kod QR z obrazu + Zaakceptuj %d s @@ -45,6 +46,7 @@ Zmień obraz Usuń Pokaż kod QR + Ustaw PIN Uwierzytelnianie nie powiodło się, proszę spróbować ponownie Uwierzytelnianie nie powiodło się, zamykanie andOTP @@ -73,6 +75,7 @@ Kod QR Informacja o wycofaniu Wprowadź hasło + PIN Wprowadź hasło Potwierdź hasło Podaj swoje dane uwierzytelniające, aby uruchomić andOTP. diff --git a/app/src/main/res/values-pt-rBR/strings_main.xml b/app/src/main/res/values-pt-rBR/strings_main.xml index 1ebe4a3c..6752fb0c 100644 --- a/app/src/main/res/values-pt-rBR/strings_main.xml +++ b/app/src/main/res/values-pt-rBR/strings_main.xml @@ -10,6 +10,7 @@ Todos os marcadores Sem marcadores QR code from image + Aceitar %d s @@ -45,6 +46,7 @@ Alterar imagem Remover Show QR Code + Definir PIN Falha na autenticação. Por favor, tente novamente. Falha na autenticação, fechando o aplicativo. @@ -73,6 +75,7 @@ QR Code Deprecation notice Digite a senha + PIN Digite a senha Confirme a senha Por favor, insira credenciais do dispositivo para iniciar andOTP. diff --git a/app/src/main/res/values-ru-rRU/strings_main.xml b/app/src/main/res/values-ru-rRU/strings_main.xml index f9f1f2d0..a48996cd 100644 --- a/app/src/main/res/values-ru-rRU/strings_main.xml +++ b/app/src/main/res/values-ru-rRU/strings_main.xml @@ -10,6 +10,7 @@ Все теги Нет тегов QR код из изображения + принимать %d сек. @@ -45,6 +46,7 @@ Изменить изображение Убрать Показать QR-код + Установить PIN Ошибка аутентификации! Пожалуйста, попробуйте снова! Ошибка аутентификации, andOTP закрывается! @@ -73,6 +75,7 @@ QR-код Уведомление об устаревании Введите пароль + PIN Введите пароль Подтвердите пароль Пожалуйста, подтвердите учетные данные устройства для открытия andOTP. diff --git a/app/src/main/res/values-sl-rSI/strings_main.xml b/app/src/main/res/values-sl-rSI/strings_main.xml index dd58f52f..2087567a 100644 --- a/app/src/main/res/values-sl-rSI/strings_main.xml +++ b/app/src/main/res/values-sl-rSI/strings_main.xml @@ -10,6 +10,7 @@ Vse oznake Ni oznak QR code from image + Sprejmi %d s @@ -45,6 +46,7 @@ Spremeni podobo Odstrani Show QR Code + Nastavite kodo PIN Prišlo je do napake pri preverjanju vaše identitete. Prosimo, poskusite ponovno! Preverjanje pristnosti ni uspelo, andOTP se zapira! @@ -73,6 +75,7 @@ QR Code Deprecation notice Vnesite geslo + PIN Vnesite geslo Potrdite geslo Prosim, vnesite podatke o napravi za zagon andOTP. diff --git a/app/src/main/res/values-sv-rSE/strings_main.xml b/app/src/main/res/values-sv-rSE/strings_main.xml index 8dbf40f6..8d669819 100644 --- a/app/src/main/res/values-sv-rSE/strings_main.xml +++ b/app/src/main/res/values-sv-rSE/strings_main.xml @@ -10,6 +10,7 @@ Alla taggar Inga taggar QR-kod från bild + Acceptera %d s @@ -45,6 +46,7 @@ Ändra bild Ta bort Visa QR-kod + Ställ in PIN-kod Autentisering misslyckades, vänligen försök igen! Autentisering misslyckades, stänger andOTP! @@ -73,6 +75,7 @@ QR-kod Avskrivningsnotis Ange lösenord + PIN Ange lösenord Bekräfta lösenord Ange dina enhetsuppgifter för att starta andOTP. diff --git a/app/src/main/res/values-tr-rTR/strings_main.xml b/app/src/main/res/values-tr-rTR/strings_main.xml index 1f1146b6..10b1cff0 100644 --- a/app/src/main/res/values-tr-rTR/strings_main.xml +++ b/app/src/main/res/values-tr-rTR/strings_main.xml @@ -10,6 +10,7 @@ Tüm etiketler Etiket yok Görüntüden QR kodu + Kabul etmek %d lar(ler) @@ -45,6 +46,7 @@ Görseli değiştir Kaldır QR Kodunu Göster + PIN ayarla Kimlik doğrulama başarısız oldu, lütfen tekrar deneyin! Kimlik doğrulama başarısız oldu, andOTP kapatılıyor! @@ -73,6 +75,7 @@ QR Kodu Destek sonlandırma bildirimi Şifre girin + PIN Şifre Girin Şifreyi doğrula Lütfen andOTP\'yi başlatmak için cihaz kimlik bilgilerinizi girin. diff --git a/app/src/main/res/values-uk-rUA/strings_main.xml b/app/src/main/res/values-uk-rUA/strings_main.xml index d68d15cf..ac026f75 100644 --- a/app/src/main/res/values-uk-rUA/strings_main.xml +++ b/app/src/main/res/values-uk-rUA/strings_main.xml @@ -10,6 +10,7 @@ Усі мітки Немає міток QR code from image + Прийміть %d с @@ -45,6 +46,7 @@ Змінити зображення Видалити Show QR Code + Встановити PIN-код Аутентифікація не пройдена. Будь ласка, спробуйте ще раз! Автентифікація не пройдена, закриття andOTP! @@ -73,6 +75,7 @@ QR Code Deprecation notice Введіть пароль + PIN-код Введіть пароль Підтвердіть пароль Будь ласка, підтвердіть дані вашого пристрою, щоб запустити andOTP. diff --git a/app/src/main/res/values-zh-rCN/strings_main.xml b/app/src/main/res/values-zh-rCN/strings_main.xml index cdc883f0..587f3df3 100644 --- a/app/src/main/res/values-zh-rCN/strings_main.xml +++ b/app/src/main/res/values-zh-rCN/strings_main.xml @@ -10,6 +10,7 @@ 所有标签 无标签 相册中选择二维码 + 接受 %d 秒 @@ -45,6 +46,7 @@ 更改图像 移除 显示二维码 + 设置密码 验证失败,请重试! 验证失败,正在关闭 andOTP! @@ -73,6 +75,7 @@ 二维码 禁用通知 输入密码 + 密码 输入密码 确认密码 请输入您的设备凭据以启动 andOTP。 diff --git a/app/src/main/res/values-zh-rTW/strings_main.xml b/app/src/main/res/values-zh-rTW/strings_main.xml index b2adda8d..69db925e 100644 --- a/app/src/main/res/values-zh-rTW/strings_main.xml +++ b/app/src/main/res/values-zh-rTW/strings_main.xml @@ -10,6 +10,7 @@ 所有標籤 無標籤 從圖片而來的 QR code + 接受 %d 秒 @@ -45,6 +46,7 @@ 變更影像 移除 顯示 QR Code + 設置密碼 認證失敗,請再試一次! 認證失敗,andOTP 正在關閉! @@ -73,6 +75,7 @@ QR Code 棄用通知 請輸入密碼 + 密碼 輸入密碼 確認密碼 請鍵入設備憑證來開啟 andOTP。 diff --git a/app/src/main/res/values/strings_main.xml b/app/src/main/res/values/strings_main.xml index 50a9fed1..ec21ec38 100644 --- a/app/src/main/res/values/strings_main.xml +++ b/app/src/main/res/values/strings_main.xml @@ -11,6 +11,7 @@ All tags No tags QR code from image + Accept %d s @@ -56,6 +57,7 @@ Change image Remove Show QR Code + Enter pin More options @@ -93,6 +95,7 @@ Tokens usage KeyStore error QR Code + PIN Enter password From 6f021386e1e7fe94e53024c01f4818d1ad4d8ba7 Mon Sep 17 00:00:00 2001 From: Santiago Garcia Mantinan <43165226+mantinan@users.noreply.github.com> Date: Mon, 10 Aug 2020 10:04:55 +0200 Subject: [PATCH 2/4] Get back to old defaults. Rewrite MD5 calculator to use Java's md5 implementation Remove MD5.java --- .../Activities/IntroScreenActivity.java | 4 +- .../flocke/andotp/Utilities/MD5.java | 515 ------------------ .../andotp/Utilities/TokenCalculator.java | 19 +- 3 files changed, 19 insertions(+), 519 deletions(-) delete mode 100644 app/src/main/java/org/shadowice/flocke/andotp/Utilities/MD5.java diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Activities/IntroScreenActivity.java b/app/src/main/java/org/shadowice/flocke/andotp/Activities/IntroScreenActivity.java index 9d6c3973..31724ea9 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Activities/IntroScreenActivity.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Activities/IntroScreenActivity.java @@ -210,7 +210,7 @@ public class IntroScreenActivity extends IntroActivity { } }); - selection.setSelection(selectionMapping.indexOfValue(Constants.EncryptionType.KEYSTORE)); + selection.setSelection(selectionMapping.indexOfValue(Constants.EncryptionType.PASSWORD)); return root; } @@ -466,7 +466,7 @@ public class IntroScreenActivity extends IntroActivity { passwordInput.addTextChangedListener(textWatcher); passwordConfirm.addTextChangedListener(textWatcher); - selection.setSelection(selectionMapping.indexOfValue(Constants.AuthMethod.NONE)); + selection.setSelection(selectionMapping.indexOfValue(Constants.AuthMethod.PASSWORD)); return root; } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/MD5.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/MD5.java deleted file mode 100644 index b1985f57..00000000 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/MD5.java +++ /dev/null @@ -1,515 +0,0 @@ -/* - * $Header: /u/users20/santtu/src/java/MD5/RCS/MD5.java,v 1.5 1996/12/12 10:47:02 santtu Exp $ - * - * MD5 in Java JDK Beta-2 - * written Santeri Paavolainen, Helsinki Finland 1996 - * (c) Santeri Paavolainen, Helsinki Finland 1996 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * See http://www.cs.hut.fi/~santtu/java/ for more information on this - * class. - * - * This is rather straight re-implementation of the reference implementation - * given in RFC1321 by RSA. - * - * Passes MD5 test suite as defined in RFC1321. - * - * - * This Java class has been derived from the RSA Data Security, Inc. MD5 - * Message-Digest Algorithm and its reference implementation. - * - * - * Revision 1.6 minor changes for j2me, 2003, Matthias Straub - * - * $Log: MD5.java,v $ - * Revision 1.5 1996/12/12 10:47:02 santtu - * Changed GPL to LGPL - * - * Revision 1.4 1996/12/12 10:30:02 santtu - * Some typos, State -> MD5State etc. - * - * Revision 1.3 1996/04/15 07:28:09 santtu - * Added GPL statemets, and RSA derivate stametemetsnnts. - * - * Revision 1.2 1996/03/04 08:05:48 santtu - * Added offsets to Update method - * - * Revision 1.1 1996/01/07 20:51:59 santtu - * Initial revision - * - */ - -/** - * Contains internal state of the MD5 class - */ -package org.shadowice.flocke.andotp.Utilities; - -class MD5State { - /** - * 128-byte state - */ - int state[]; - - /** - * 64-bit character count (could be true Java long?) - */ - int count[]; - - /** - * 64-byte buffer (512 bits) for storing to-be-hashed characters - */ - byte buffer[]; - - public MD5State() { - buffer = new byte[64]; - count = new int[2]; - state = new int[4]; - - state[0] = 0x67452301; - state[1] = 0xefcdab89; - state[2] = 0x98badcfe; - state[3] = 0x10325476; - - count[0] = count[1] = 0; - } - - /** Create this State as a copy of another state */ - public MD5State (MD5State from) { - this(); - - int i; - - for (i = 0; i < buffer.length; i++) - this.buffer[i] = from.buffer[i]; - - for (i = 0; i < state.length; i++) - this.state[i] = from.state[i]; - - for (i = 0; i < count.length; i++) - this.count[i] = from.count[i]; - } -}; - -/** - * Implementation of RSA's MD5 hash generator - * - * @version $Revision: 1.5 $ - * @author Santeri Paavolainen - */ - -public class MD5 { - /** - * MD5 state - */ - MD5State state; - - /** - * If Final() has been called, finals is set to the current finals - * state. Any Update() causes this to be set to null. - */ - MD5State finals; - - /** - * Padding for Final() - */ - static byte padding[] = { - (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - - /** - * Initialize MD5 internal state (object can be reused just by - * calling Init() after every Final() - */ - public synchronized void Init () { - state = new MD5State(); - finals = null; - } - - /** - * Class constructor - */ - public MD5 () { - this.Init(); - } - - /** - * Initialize class, and update hash with ob.toString() - * - * @param ob Object, ob.toString() is used to update hash - * after initialization - */ - public MD5 (Object ob) { - this(); - Update(ob.toString()); - } - - private int rotate_left (int x, int n) { - return (x << n) | (x >>> (32 - n)); - } - - /* I wonder how many loops and hoops you'll have to go through to - get unsigned add for longs in java */ - - private int uadd (int a, int b) { - long aa, bb; - aa = ((long) a) & 0xffffffffL; - bb = ((long) b) & 0xffffffffL; - - aa += bb; - - return (int) (aa & 0xffffffffL); - } - - private int uadd (int a, int b, int c) { - return uadd(uadd(a, b), c); - } - - private int uadd (int a, int b, int c, int d) { - return uadd(uadd(a, b, c), d); - } - - private int FF (int a, int b, int c, int d, int x, int s, int ac) { - a = uadd(a, ((b & c) | (~b & d)), x, ac); - return uadd(rotate_left(a, s), b); - } - - private int GG (int a, int b, int c, int d, int x, int s, int ac) { - a = uadd(a, ((b & d) | (c & ~d)), x, ac); - return uadd(rotate_left(a, s), b); - } - - private int HH (int a, int b, int c, int d, int x, int s, int ac) { - a = uadd(a, (b ^ c ^ d), x, ac); - return uadd(rotate_left(a, s) , b); - } - - private int II (int a, int b, int c, int d, int x, int s, int ac) { - a = uadd(a, (c ^ (b | ~d)), x, ac); - return uadd(rotate_left(a, s), b); - } - - private int[] Decode (byte buffer[], int len, int shift) { - int out[]; - int i, j; - - out = new int[16]; - - for (i = j = 0; j < len; i++, j += 4) { - out[i] = ((int) (buffer[j + shift] & 0xff)) | - (((int) (buffer[j + 1 + shift] & 0xff)) << 8) | - (((int) (buffer[j + 2 + shift] & 0xff)) << 16) | - (((int) (buffer[j + 3 + shift] & 0xff)) << 24); - -/* System.out.println("out[" + i + "] = \t" + - ((int) buffer[j + 0 + shift] & 0xff) + "\t|\t" + - ((int) buffer[j + 1 + shift] & 0xff) + "\t|\t" + - ((int) buffer[j + 2 + shift] & 0xff) + "\t|\t" + - ((int) buffer[j + 3 + shift] & 0xff));*/ - } - - return out; - } - - private void Transform (MD5State state, byte buffer[], int shift) { - int - a = state.state[0], - b = state.state[1], - c = state.state[2], - d = state.state[3], - x[]; - - x = Decode(buffer, 64, shift); - - /* Round 1 */ - a = FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ - d = FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ - c = FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ - b = FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ - a = FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ - d = FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ - c = FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ - b = FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ - a = FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ - d = FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ - c = FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ - b = FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ - a = FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ - d = FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ - c = FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ - b = FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ - - /* Round 2 */ - a = GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ - d = GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ - c = GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ - b = GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ - a = GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ - d = GG (d, a, b, c, x[10], 9, 0x2441453); /* 22 */ - c = GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ - b = GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ - a = GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ - d = GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ - c = GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ - b = GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ - a = GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ - d = GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ - c = GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ - b = GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ - - /* Round 3 */ - a = HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ - d = HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ - c = HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ - b = HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ - a = HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ - d = HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ - c = HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ - b = HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ - a = HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ - d = HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ - c = HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ - b = HH (b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */ - a = HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ - d = HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ - c = HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ - b = HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ - - /* Round 4 */ - a = II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ - d = II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ - c = II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ - b = II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ - a = II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ - d = II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ - c = II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ - b = II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ - a = II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ - d = II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ - c = II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ - b = II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ - a = II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ - d = II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ - c = II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ - b = II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ - - state.state[0] += a; - state.state[1] += b; - state.state[2] += c; - state.state[3] += d; - } - - /** - * Updates hash with the bytebuffer given (using at maximum length bytes from - * that buffer) - * - * @param stat Which state is updated - * @param buffer Array of bytes to be hashed - * @param offset Offset to buffer array - * @param length Use at maximum `length' bytes (absolute - * maximum is buffer.length) - */ - public void Update (MD5State stat, byte buffer[], int offset, int length) { - int index, partlen, i, start; - -/* System.out.print("Offset = " + offset + "\tLength = " + length + "\t"); - System.out.print("Buffer = "); - for (i = 0; i < buffer.length; i++) - System.out.print((int) (buffer[i] & 0xff) + " "); - System.out.print("\n");*/ - - finals = null; - - /* Length can be told to be shorter, but not inter */ - if ((length - offset)> buffer.length) - length = buffer.length - offset; - - /* compute number of bytes mod 64 */ - index = (int) (stat.count[0] >>> 3) & 0x3f; - - if ((stat.count[0] += (length << 3)) < - (length << 3)) - stat.count[1]++; - - stat.count[1] += length >>> 29; - - partlen = 64 - index; - - if (length >= partlen) { - for (i = 0; i < partlen; i++) - stat.buffer[i + index] = buffer[i + offset]; - - Transform(stat, stat.buffer, 0); - - for (i = partlen; (i + 63) < length; i+= 64) - Transform(stat, buffer, i); - - index = 0; - } else - i = 0; - - /* buffer remaining input */ - if (i < length) { - start = i; - for (; i < length; i++) - stat.buffer[index + i - start] = buffer[i + offset]; - } - } - - /* - * Update()s for other datatypes than byte[] also. Update(byte[], int) - * is only the main driver. - */ - - /** - * Plain update, updates this object - */ - - public void Update (byte buffer[], int offset, int length) { - Update(this.state, buffer, offset, length); - } - - public void Update (byte buffer[], int length) { - Update(this.state, buffer, 0, length); - } - - /** - * Updates hash with given array of bytes - * - * @param buffer Array of bytes to use for updating the hash - */ - public void Update (byte buffer[]) { - Update(buffer, 0, buffer.length); - } - - /** - * Updates hash with a single byte - * - * @param b Single byte to update the hash - */ - public void Update (byte b) { - byte buffer[] = new byte[1]; - buffer[0] = b; - - Update(buffer, 1); - } - - /** - * Update buffer with given string. - * - * @param s String to be update to hash (is used as - * s.getBytes()) - */ - public void Update (String s) { - byte chars[]; - - chars = new byte[s.length()]; - chars=s.getBytes(); - - Update(chars, chars.length); - } - - /** - * Update buffer with a single integer (only & 0xff part is used, - * as a byte) - * - * @param i Integer value, which is then converted to - * byte as i & 0xff - */ - - public void Update (int i) { - Update((byte) (i & 0xff)); - } - - private byte[] Encode (int input[], int len) { - int i, j; - byte out[]; - - out = new byte[len]; - - for (i = j = 0; j < len; i++, j += 4) { - out[j] = (byte) (input[i] & 0xff); - out[j + 1] = (byte) ((input[i] >>> 8) & 0xff); - out[j + 2] = (byte) ((input[i] >>> 16) & 0xff); - out[j + 3] = (byte) ((input[i] >>> 24) & 0xff); - } - - return out; - } - - /** - * Returns array of bytes (16 bytes) representing hash as of the - * current state of this object. Note: getting a hash does not - * invalidate the hash object, it only creates a copy of the real - * state which is finalized. - * - * @return Array of 16 bytes, the hash of all updated bytes - */ - public synchronized byte[] Final () { - byte bits[]; - int index, padlen; - MD5State fin; - - if (finals == null) { - fin = new MD5State(state); - - bits = Encode(fin.count, 8); - - index = (int) ((fin.count[0] >>> 3) & 0x3f); - padlen = (index < 56) ? (56 - index) : (120 - index); - - Update(fin, padding, 0, padlen); - /**/ - Update(fin, bits, 0, 8); - - /* Update() sets finalds to null */ - finals = fin; - } - - return Encode(finals.state, 16); - } - - /** - * Turns array of bytes into string representing each byte as - * unsigned hex number. - * - * @param hash Array of bytes to convert to hex-string - * @return Generated hex string - */ - public static String asHex (byte hash[]) { - StringBuffer buf = new StringBuffer(hash.length * 2); - int i; - - for (i = 0; i < hash.length; i++) { - if (((int) hash[i] & 0xff) < 0x10) - buf.append("0"); - - buf.append(Long.toString((int) hash[i] & 0xff, 16)); - } - - return buf.toString(); - } - - /** - * Returns 32-character hex representation of this objects hash - * - * @return String of this object's hash - */ - public String asHex () { - return asHex(this.Final()); - } -} diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java index 023194ce..083f9ac6 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java @@ -25,6 +25,7 @@ package org.shadowice.flocke.andotp.Utilities; import java.nio.ByteBuffer; import java.security.InvalidKeyException; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Date; @@ -123,8 +124,22 @@ public class TokenCalculator { String epoch = "" + (dateNow.getTime()); epoch = epoch.substring(0, epoch.length() - 4); String otp = epoch + secret + PIN; - MD5 hash = new MD5(otp); - otp = hash.asHex().substring(0, 6); + try { + // Create MD5 Hash + MessageDigest digest = MessageDigest.getInstance("MD5"); + digest.update(otp.getBytes()); + byte messageDigest[] = digest.digest(); + + // Create Hex String + StringBuffer hexString = new StringBuffer(); + for (int i = 0; i < messageDigest.length; i++) + hexString.append(Integer.toHexString(0xFF & messageDigest[i])); + + otp = hexString.substring(0, 6); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + otp=""; + } return otp; } } From 282a5a96a1d866c9330e2553f3349ff0eb912430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santiago=20Garc=C3=ADa=20Manti=C3=B1=C3=A1n?= Date: Thu, 4 Mar 2021 11:00:25 +0100 Subject: [PATCH 3/4] Remove all the translations (Jakob's request) --- app/src/main/res/values-ar-rSA/strings_main.xml | 3 --- app/src/main/res/values-bg-rBG/strings_main.xml | 3 --- app/src/main/res/values-ca-rES/strings_main.xml | 3 --- app/src/main/res/values-cs-rCZ/strings_main.xml | 3 --- app/src/main/res/values-de-rDE/strings_main.xml | 3 --- app/src/main/res/values-el-rGR/strings_main.xml | 3 --- app/src/main/res/values-es-rES/strings_main.xml | 3 --- app/src/main/res/values-fa-rIR/strings_main.xml | 3 --- app/src/main/res/values-fr-rFR/strings_main.xml | 3 --- app/src/main/res/values-gl-rES/strings_main.xml | 3 --- app/src/main/res/values-hi-rIN/strings_main.xml | 3 --- app/src/main/res/values-hu-rHU/strings_main.xml | 3 --- app/src/main/res/values-it-rIT/strings_main.xml | 3 --- app/src/main/res/values-ja-rJP/strings_main.xml | 3 --- app/src/main/res/values-nl-rNL/strings_main.xml | 3 --- app/src/main/res/values-pl-rPL/strings_main.xml | 3 --- app/src/main/res/values-pt-rBR/strings_main.xml | 3 --- app/src/main/res/values-ru-rRU/strings_main.xml | 3 --- app/src/main/res/values-sl-rSI/strings_main.xml | 3 --- app/src/main/res/values-sv-rSE/strings_main.xml | 3 --- app/src/main/res/values-tr-rTR/strings_main.xml | 3 --- app/src/main/res/values-uk-rUA/strings_main.xml | 3 --- app/src/main/res/values-zh-rCN/strings_main.xml | 3 --- app/src/main/res/values-zh-rTW/strings_main.xml | 3 --- 24 files changed, 72 deletions(-) diff --git a/app/src/main/res/values-ar-rSA/strings_main.xml b/app/src/main/res/values-ar-rSA/strings_main.xml index 37e9b1b4..afe0c71c 100644 --- a/app/src/main/res/values-ar-rSA/strings_main.xml +++ b/app/src/main/res/values-ar-rSA/strings_main.xml @@ -10,7 +10,6 @@ كافة العلامات بدون علامات رمز كيو آر مِن صورة - اقبل %d ثا @@ -46,7 +45,6 @@ تغيير الصورة حذف Show QR Code - أدخل رمز PIN أخفقت المصادقة، الرجاء إعادة المحاولة ! أخفقت عملية المصادقة، جارٍ إغلاق التطبيق! @@ -75,7 +73,6 @@ QR Code Deprecation notice أدخل كلمة المرور - دبوس أدخل كلمة المرور تأكيد كلمة المرور الرجاء إدخال بيانات الإعتماد الخاصة بجهازك لتشغيل التطبيق. diff --git a/app/src/main/res/values-bg-rBG/strings_main.xml b/app/src/main/res/values-bg-rBG/strings_main.xml index 2ba9f2d1..22e9705a 100644 --- a/app/src/main/res/values-bg-rBG/strings_main.xml +++ b/app/src/main/res/values-bg-rBG/strings_main.xml @@ -10,7 +10,6 @@ Всички маркери Няма маркери QR код от изображение - приемам %d сек @@ -46,7 +45,6 @@ Промяна на изображението Премахване Показване на QR кода - Въведете ПИН код Неуспешно удостоверяване. Моля, опитайте отново! Неуспешно удостоверяване, затваряне на andOTP! @@ -75,7 +73,6 @@ QR код Остаряло известие Въведете парола - PIN Въведете парола Потвърдете паролата Моля, въведете идентификационните данни на устройството си, за да стартирате andOTP. diff --git a/app/src/main/res/values-ca-rES/strings_main.xml b/app/src/main/res/values-ca-rES/strings_main.xml index 8ab95425..709d06f1 100644 --- a/app/src/main/res/values-ca-rES/strings_main.xml +++ b/app/src/main/res/values-ca-rES/strings_main.xml @@ -10,7 +10,6 @@ Totes les etiquetes Sense etiquetes QR code from image - Acceptar %d s @@ -46,7 +45,6 @@ Canvia la imatge Suprimeix Show QR Code - Introduir PIN Error d\'autenticació. Torneu-ho a intentar! L\'autenticació ha fallat, andOTP es tancarà! @@ -75,7 +73,6 @@ QR Code Deprecation notice Introduïu la contrasenya - PIN Introduïu la contrasenya Confirmeu la contrasenya Per favor, introduïu les vostres credencials per a iniciar andOTP. diff --git a/app/src/main/res/values-cs-rCZ/strings_main.xml b/app/src/main/res/values-cs-rCZ/strings_main.xml index 701cafee..880df42c 100644 --- a/app/src/main/res/values-cs-rCZ/strings_main.xml +++ b/app/src/main/res/values-cs-rCZ/strings_main.xml @@ -10,7 +10,6 @@ Všechny štítky Bez štítku QR kód z obrázku - Přijmout %d s @@ -46,7 +45,6 @@ Změnit obrázek Smazat Ukaž QR kód - Zadejte PIN Chyba ověření, zkuste to prosím znovu! Ověření se nezdařilo, zavírám andOTP! @@ -75,7 +73,6 @@ QR kód Oznámení o ukončení podpory Zadejte heslo - PIN Zadejte heslo Potvrďte heslo Prosím zadejte heslo zařízení ke spuštění andOTP. diff --git a/app/src/main/res/values-de-rDE/strings_main.xml b/app/src/main/res/values-de-rDE/strings_main.xml index 1aab1a56..7097975a 100644 --- a/app/src/main/res/values-de-rDE/strings_main.xml +++ b/app/src/main/res/values-de-rDE/strings_main.xml @@ -10,7 +10,6 @@ Alle Marker Keine Marker QR-Code aus Bild - Akzeptiere %d s @@ -46,7 +45,6 @@ Bild ändern Entfernen Zeige QR-Code - PIN einstellen Authentifizierung fehlgeschlagen, bitte erneut versuchen! Authentifizierung fehlgeschlagen, andOTP wird geschlossen! @@ -75,7 +73,6 @@ QR-Code Hinweis Passwort eingeben - PIN Passwort eingeben Passwort bestätigen Bitte geben Sie die Anmeldeinformationen Ihres Geräts ein, um andOTP zu starten. diff --git a/app/src/main/res/values-el-rGR/strings_main.xml b/app/src/main/res/values-el-rGR/strings_main.xml index 8d8b1fc8..32af516a 100644 --- a/app/src/main/res/values-el-rGR/strings_main.xml +++ b/app/src/main/res/values-el-rGR/strings_main.xml @@ -10,7 +10,6 @@ Όλες οι ετικέτες Χωρίς ετικέτες Κώδικας QR από εικόνα - Αποδοχή %d\" @@ -46,7 +45,6 @@ Αλλαγή εικόνας Διαγραφή Show QR Code - Ορίστε το PIN Η ταυτοποίηση απέτυχε. Παρακαλώ προσπάθησε ξανά! Απέτυχε ο έλεγχος ταυτότητας, κλείνει το andOTP! @@ -76,7 +74,6 @@ Deprecation notice Εισάγετε κωδικό Εισάγετε κωδικό - PIN Επιβεβαίωση κωδικού Παρακαλούμε εισαγάγετε τα διαπιστευτήριά σας για να ανοίξετε το andOTP. Σίγουρα θέλετε να αφαιρέσετε το λογαριασμό \"%1$s\"; diff --git a/app/src/main/res/values-es-rES/strings_main.xml b/app/src/main/res/values-es-rES/strings_main.xml index 205158d3..269e7d78 100644 --- a/app/src/main/res/values-es-rES/strings_main.xml +++ b/app/src/main/res/values-es-rES/strings_main.xml @@ -10,7 +10,6 @@ Todas las etiquetas Sin etiquetas Imagen del código QR - Aceptar %d s @@ -46,7 +45,6 @@ Cambiar imagen Eliminar Mostrar código QR - Introducir pin La autentificación ha fallado, por favor inténtelo otra vez! La autenticación ha fallado, cerrando andOTP! @@ -75,7 +73,6 @@ Código QR Aviso de deprecación Introduzca la contraseña - PIN Introduzca la contraseña Confirmar contraseña Por favor, introduce los credenciales del dispositivo para iniciar andOTP. diff --git a/app/src/main/res/values-fa-rIR/strings_main.xml b/app/src/main/res/values-fa-rIR/strings_main.xml index 349e5ca6..d12c96a6 100644 --- a/app/src/main/res/values-fa-rIR/strings_main.xml +++ b/app/src/main/res/values-fa-rIR/strings_main.xml @@ -10,7 +10,6 @@ همه تگ‌ها بدون تگ کد QR از تصویر - قبول کنید %d ثانیه @@ -46,7 +45,6 @@ تغییر تصویر حذف نمایش کد QR - پین را تنظیم کنید احراز هویت ناموفق بود، لطفا دوباره تلاش کنید! احراز هویت ناموفق بود، در حال بستن andOTP! @@ -75,7 +73,6 @@ کد QR اخطار استهلاک گذرواژه را وارد کنید - پین گذرواژه را وارد کنید تایید گذرواژه برای شروع andOTP لطفا اعتبارنامه دستگاه خود را وارد کنید. diff --git a/app/src/main/res/values-fr-rFR/strings_main.xml b/app/src/main/res/values-fr-rFR/strings_main.xml index 02fafad4..23d6d333 100644 --- a/app/src/main/res/values-fr-rFR/strings_main.xml +++ b/app/src/main/res/values-fr-rFR/strings_main.xml @@ -10,7 +10,6 @@ Tous les tags Aucun tag QR-code à partir d\'une image - Accepter %d s @@ -46,7 +45,6 @@ Modifier l\'image Supprimer Montrer le QR Code - Définir le code PIN Échec d\'authentification, veuillez réessayer ! Échec d\'authentification, fermeture d\'andOTP ! @@ -75,7 +73,6 @@ QR Code Avis d\'obsolescence Saisir le mot de passe - PIN Saisir le mot de passe Confirmer le mot de passe Veuillez entrer les informations d\'identification du périphérique pour démarrer andOTP. diff --git a/app/src/main/res/values-gl-rES/strings_main.xml b/app/src/main/res/values-gl-rES/strings_main.xml index 6bac2297..4fefd5e0 100644 --- a/app/src/main/res/values-gl-rES/strings_main.xml +++ b/app/src/main/res/values-gl-rES/strings_main.xml @@ -10,7 +10,6 @@ Todas as etiquetas Sen etiquetas Código QR desde imaxe - Aceptar %d s @@ -46,7 +45,6 @@ Cambiar imaxe Eliminar Mostrar código QR - Introducir o pin Fallou a autenticación, por favor inténtao de novo! Fallou a autenticación, pechando andOTP! @@ -75,7 +73,6 @@ Código QR Aviso de abandono Introducir contrasinal - PIN Introducir contrasinal Confirmar contrasinal Introduce as credenciais do dispositivo para iniciar andOTP. diff --git a/app/src/main/res/values-hi-rIN/strings_main.xml b/app/src/main/res/values-hi-rIN/strings_main.xml index 83213916..d35563b8 100644 --- a/app/src/main/res/values-hi-rIN/strings_main.xml +++ b/app/src/main/res/values-hi-rIN/strings_main.xml @@ -10,7 +10,6 @@ सभी टैग कोई टैग नहीं छवि से क्यूआर कोड - स्वीकार करना %d सेकेंड @@ -46,7 +45,6 @@ छवि बदलें हटाएं Show QR Code - पिन सेट करें प्रमाणीकरण असफल| कृपया पुन: प्रयास करें! प्रमाणीकरण विफल, समापन andOTP! @@ -75,7 +73,6 @@ QR Code Deprecation notice अपना पासवोर्ड डाले - पिन अपना पासवोर्ड डाले पासवर्ड की पुष्टि करें AndOTP शुरू करने के लिए कृपया अपनी यंत्र साख दर्ज करें। diff --git a/app/src/main/res/values-hu-rHU/strings_main.xml b/app/src/main/res/values-hu-rHU/strings_main.xml index d8d34970..45b97e73 100644 --- a/app/src/main/res/values-hu-rHU/strings_main.xml +++ b/app/src/main/res/values-hu-rHU/strings_main.xml @@ -10,7 +10,6 @@ Összes címke Nincs címke QR-kód képből - Elfogad %d másodperc @@ -46,7 +45,6 @@ Kép módosítása Eltávolítás Show QR Code - Állítsa be a PIN-kódot A hitelesítés sikertelen, próbálja újra! A hitelesítés sikertelen, az andOTP bezárul! @@ -75,7 +73,6 @@ QR Code Deprecation notice Jelszó megadása - PIN Jelszó megadása Jelszó megerősítése Kérjük, adja meg a készülék hitelesítő adatait az andOTP indításához. diff --git a/app/src/main/res/values-it-rIT/strings_main.xml b/app/src/main/res/values-it-rIT/strings_main.xml index 7a17d7a0..c31d95eb 100644 --- a/app/src/main/res/values-it-rIT/strings_main.xml +++ b/app/src/main/res/values-it-rIT/strings_main.xml @@ -10,7 +10,6 @@ Tutti i tag Nessun tag QR code da immagine - Accettare %d s @@ -46,7 +45,6 @@ Cambia Immagine Rimuovi Mostra codice QR - Imposta PIN Autenticazione non riuscita, riprova! Autenticazione non riuscita, andOTP verrà chiuso! @@ -75,7 +73,6 @@ Codice QR Avviso di deprecazione Inserisci la password - PIN Inserisci la password Conferma la password Si prega di inserire le credenziali del dispositivo per avviare andOTP. diff --git a/app/src/main/res/values-ja-rJP/strings_main.xml b/app/src/main/res/values-ja-rJP/strings_main.xml index 8dce59d0..42ef7637 100644 --- a/app/src/main/res/values-ja-rJP/strings_main.xml +++ b/app/src/main/res/values-ja-rJP/strings_main.xml @@ -10,7 +10,6 @@ すべてのタグ タグなし QR コードを画像からスキャン - 受け入れる %d 秒 @@ -46,7 +45,6 @@ 画像を変更 削除 QR コードを表示 - PINを設定 認証に失敗しました、もう一度やり直してください! 認証に失敗しました、 andOTP を終了します! @@ -75,7 +73,6 @@ QR コード サポート廃止の通知 パスワードを入力 - PIN パスワードを入力 パスワードの確認 andOTP を起動するためにデバイス認証情報を入力してください。 diff --git a/app/src/main/res/values-nl-rNL/strings_main.xml b/app/src/main/res/values-nl-rNL/strings_main.xml index df6150c4..030f2c9c 100644 --- a/app/src/main/res/values-nl-rNL/strings_main.xml +++ b/app/src/main/res/values-nl-rNL/strings_main.xml @@ -10,7 +10,6 @@ Alle labels Geen labels QR-code van afbeelding - Accepteren %d s @@ -46,7 +45,6 @@ Afbeelding wijzigen Verwijderen Show QR Code - PIN instellen Authenticatie mislukt. Probeer opnieuw! Verificatie is mislukt, andOTP wordt afgesloten! @@ -75,7 +73,6 @@ QR Code Deprecation notice Wachtwoord invoeren - PIN Wachtwoord invoeren Wachtwoord bevestigen Voer de referenties van uw apparaat in om te beginnen met andOTP. diff --git a/app/src/main/res/values-pl-rPL/strings_main.xml b/app/src/main/res/values-pl-rPL/strings_main.xml index 01e353f5..03820e7e 100644 --- a/app/src/main/res/values-pl-rPL/strings_main.xml +++ b/app/src/main/res/values-pl-rPL/strings_main.xml @@ -10,7 +10,6 @@ Wszystkie znaczniki Brak znaczników Kod QR z obrazu - Zaakceptuj %d s @@ -46,7 +45,6 @@ Zmień obraz Usuń Pokaż kod QR - Ustaw PIN Uwierzytelnianie nie powiodło się, proszę spróbować ponownie Uwierzytelnianie nie powiodło się, zamykanie andOTP @@ -75,7 +73,6 @@ Kod QR Informacja o wycofaniu Wprowadź hasło - PIN Wprowadź hasło Potwierdź hasło Podaj swoje dane uwierzytelniające, aby uruchomić andOTP. diff --git a/app/src/main/res/values-pt-rBR/strings_main.xml b/app/src/main/res/values-pt-rBR/strings_main.xml index 6752fb0c..1ebe4a3c 100644 --- a/app/src/main/res/values-pt-rBR/strings_main.xml +++ b/app/src/main/res/values-pt-rBR/strings_main.xml @@ -10,7 +10,6 @@ Todos os marcadores Sem marcadores QR code from image - Aceitar %d s @@ -46,7 +45,6 @@ Alterar imagem Remover Show QR Code - Definir PIN Falha na autenticação. Por favor, tente novamente. Falha na autenticação, fechando o aplicativo. @@ -75,7 +73,6 @@ QR Code Deprecation notice Digite a senha - PIN Digite a senha Confirme a senha Por favor, insira credenciais do dispositivo para iniciar andOTP. diff --git a/app/src/main/res/values-ru-rRU/strings_main.xml b/app/src/main/res/values-ru-rRU/strings_main.xml index a48996cd..f9f1f2d0 100644 --- a/app/src/main/res/values-ru-rRU/strings_main.xml +++ b/app/src/main/res/values-ru-rRU/strings_main.xml @@ -10,7 +10,6 @@ Все теги Нет тегов QR код из изображения - принимать %d сек. @@ -46,7 +45,6 @@ Изменить изображение Убрать Показать QR-код - Установить PIN Ошибка аутентификации! Пожалуйста, попробуйте снова! Ошибка аутентификации, andOTP закрывается! @@ -75,7 +73,6 @@ QR-код Уведомление об устаревании Введите пароль - PIN Введите пароль Подтвердите пароль Пожалуйста, подтвердите учетные данные устройства для открытия andOTP. diff --git a/app/src/main/res/values-sl-rSI/strings_main.xml b/app/src/main/res/values-sl-rSI/strings_main.xml index 2087567a..dd58f52f 100644 --- a/app/src/main/res/values-sl-rSI/strings_main.xml +++ b/app/src/main/res/values-sl-rSI/strings_main.xml @@ -10,7 +10,6 @@ Vse oznake Ni oznak QR code from image - Sprejmi %d s @@ -46,7 +45,6 @@ Spremeni podobo Odstrani Show QR Code - Nastavite kodo PIN Prišlo je do napake pri preverjanju vaše identitete. Prosimo, poskusite ponovno! Preverjanje pristnosti ni uspelo, andOTP se zapira! @@ -75,7 +73,6 @@ QR Code Deprecation notice Vnesite geslo - PIN Vnesite geslo Potrdite geslo Prosim, vnesite podatke o napravi za zagon andOTP. diff --git a/app/src/main/res/values-sv-rSE/strings_main.xml b/app/src/main/res/values-sv-rSE/strings_main.xml index 8d669819..8dbf40f6 100644 --- a/app/src/main/res/values-sv-rSE/strings_main.xml +++ b/app/src/main/res/values-sv-rSE/strings_main.xml @@ -10,7 +10,6 @@ Alla taggar Inga taggar QR-kod från bild - Acceptera %d s @@ -46,7 +45,6 @@ Ändra bild Ta bort Visa QR-kod - Ställ in PIN-kod Autentisering misslyckades, vänligen försök igen! Autentisering misslyckades, stänger andOTP! @@ -75,7 +73,6 @@ QR-kod Avskrivningsnotis Ange lösenord - PIN Ange lösenord Bekräfta lösenord Ange dina enhetsuppgifter för att starta andOTP. diff --git a/app/src/main/res/values-tr-rTR/strings_main.xml b/app/src/main/res/values-tr-rTR/strings_main.xml index 10b1cff0..1f1146b6 100644 --- a/app/src/main/res/values-tr-rTR/strings_main.xml +++ b/app/src/main/res/values-tr-rTR/strings_main.xml @@ -10,7 +10,6 @@ Tüm etiketler Etiket yok Görüntüden QR kodu - Kabul etmek %d lar(ler) @@ -46,7 +45,6 @@ Görseli değiştir Kaldır QR Kodunu Göster - PIN ayarla Kimlik doğrulama başarısız oldu, lütfen tekrar deneyin! Kimlik doğrulama başarısız oldu, andOTP kapatılıyor! @@ -75,7 +73,6 @@ QR Kodu Destek sonlandırma bildirimi Şifre girin - PIN Şifre Girin Şifreyi doğrula Lütfen andOTP\'yi başlatmak için cihaz kimlik bilgilerinizi girin. diff --git a/app/src/main/res/values-uk-rUA/strings_main.xml b/app/src/main/res/values-uk-rUA/strings_main.xml index ac026f75..d68d15cf 100644 --- a/app/src/main/res/values-uk-rUA/strings_main.xml +++ b/app/src/main/res/values-uk-rUA/strings_main.xml @@ -10,7 +10,6 @@ Усі мітки Немає міток QR code from image - Прийміть %d с @@ -46,7 +45,6 @@ Змінити зображення Видалити Show QR Code - Встановити PIN-код Аутентифікація не пройдена. Будь ласка, спробуйте ще раз! Автентифікація не пройдена, закриття andOTP! @@ -75,7 +73,6 @@ QR Code Deprecation notice Введіть пароль - PIN-код Введіть пароль Підтвердіть пароль Будь ласка, підтвердіть дані вашого пристрою, щоб запустити andOTP. diff --git a/app/src/main/res/values-zh-rCN/strings_main.xml b/app/src/main/res/values-zh-rCN/strings_main.xml index 587f3df3..cdc883f0 100644 --- a/app/src/main/res/values-zh-rCN/strings_main.xml +++ b/app/src/main/res/values-zh-rCN/strings_main.xml @@ -10,7 +10,6 @@ 所有标签 无标签 相册中选择二维码 - 接受 %d 秒 @@ -46,7 +45,6 @@ 更改图像 移除 显示二维码 - 设置密码 验证失败,请重试! 验证失败,正在关闭 andOTP! @@ -75,7 +73,6 @@ 二维码 禁用通知 输入密码 - 密码 输入密码 确认密码 请输入您的设备凭据以启动 andOTP。 diff --git a/app/src/main/res/values-zh-rTW/strings_main.xml b/app/src/main/res/values-zh-rTW/strings_main.xml index 69db925e..b2adda8d 100644 --- a/app/src/main/res/values-zh-rTW/strings_main.xml +++ b/app/src/main/res/values-zh-rTW/strings_main.xml @@ -10,7 +10,6 @@ 所有標籤 無標籤 從圖片而來的 QR code - 接受 %d 秒 @@ -46,7 +45,6 @@ 變更影像 移除 顯示 QR Code - 設置密碼 認證失敗,請再試一次! 認證失敗,andOTP 正在關閉! @@ -75,7 +73,6 @@ QR Code 棄用通知 請輸入密碼 - 密碼 輸入密碼 確認密碼 請鍵入設備憑證來開啟 andOTP。 From 8235a930d73b17b8690cfe695de72da04b0aae04 Mon Sep 17 00:00:00 2001 From: Santiago Garcia Mantinan <43165226+mantinan@users.noreply.github.com> Date: Mon, 15 Mar 2021 11:12:36 +0100 Subject: [PATCH 4/4] Commmit changes provided by Jakob on https://github.com/andOTP/andOTP/files/6136564/motp_fixes.patch.txt --- .../flocke/andotp/Database/Entry.java | 33 +++++++---- .../andotp/Dialogs/ManualEntryDialog.java | 25 +++++++- .../andotp/Utilities/TokenCalculator.java | 24 ++++---- .../andotp/View/EntriesCardAdapter.java | 57 +++++++++---------- .../flocke/andotp/View/EntryViewHolder.java | 9 --- 5 files changed, 84 insertions(+), 64 deletions(-) diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java b/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java index 5427e683..63b52dc7 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Database/Entry.java @@ -26,6 +26,7 @@ package org.shadowice.flocke.andotp.Database; import android.net.Uri; import org.apache.commons.codec.binary.Base32; +import org.apache.commons.codec.binary.Hex; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -173,7 +174,7 @@ public class Entry { this.label = label; if(type == OTPType.MOTP) { this.secret = secret.getBytes(); - }else{ + } else { this.secret = new Base32().decode(secret.toUpperCase()); } @@ -311,14 +312,22 @@ public class Entry { case STEAM: type = "steam"; break; + case MOTP: + type = "motp"; + break; default: return null; } Uri.Builder builder = new Uri.Builder() .scheme("otpauth") .authority(type) - .appendPath(this.label) - .appendQueryParameter("secret", new Base32().encodeAsString(this.secret)); + .appendPath(this.label); + + if (this.type == OTPType.MOTP) + builder.appendQueryParameter("secret", new String(this.secret)); + else + builder.appendQueryParameter("secret", new Base32().encodeAsString(this.secret)); + if (this.issuer != null) { builder.appendQueryParameter("issuer", this.issuer); } @@ -361,7 +370,10 @@ public class Entry { } public String getSecretEncoded() { - return new String(new Base32().encode(secret)); + if (type == OTPType.MOTP) + return new String(secret); + else + return new String(new Base32().encode(secret)); } public void setSecret(byte[] secret) { @@ -478,10 +490,6 @@ public class Entry { public void setListId(long newId) { listId = newId; } - - public boolean updateOTP() { - return updateOTP(false); - } public boolean updateOTP(boolean updateNow) { if (type == OTPType.TOTP || type == OTPType.STEAM) { @@ -512,7 +520,7 @@ public class Entry { if (currentPin.isEmpty()) { currentOTP = MOTP_NO_PIN_CODE; } else { - currentOTP = TokenCalculator.MOTP(currentPin, new String(this.secret)); + currentOTP = TokenCalculator.MOTP(currentPin, new String(this.secret), time); } last_update = counter; setColor(COLOR_DEFAULT); @@ -589,9 +597,12 @@ public class Entry { return color; } - public static boolean validateSecret(String secret) { + public static boolean validateSecret(String secret, OTPType type) { try { - new Base32().decode(secret.toUpperCase()); + if (type == OTPType.MOTP) + Hex.decodeHex(secret); + else + new Base32().decode(secret.toUpperCase()); } catch (Exception e) { return false; } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Dialogs/ManualEntryDialog.java b/app/src/main/java/org/shadowice/flocke/andotp/Dialogs/ManualEntryDialog.java index 89f0a640..41bd5beb 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Dialogs/ManualEntryDialog.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Dialogs/ManualEntryDialog.java @@ -202,13 +202,13 @@ public class ManualEntryDialog { positiveButton.setOnClickListener(view -> { //Replace spaces with empty characters String secret = secretInput.getText().toString().replaceAll("\\s+",""); + Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem(); - if (!Entry.validateSecret(secret)) { + if (!Entry.validateSecret(secret, type)) { secretInput.setError(callingActivity.getString(R.string.error_invalid_secret)); return; } - Entry.OTPType type = (Entry.OTPType) typeInput.getSelectedItem(); TokenCalculator.HashAlgorithm algorithm = (TokenCalculator.HashAlgorithm) algorithmInput.getSelectedItem(); int digits = Integer.parseInt(digitsInput.getText().toString()); @@ -259,6 +259,27 @@ public class ManualEntryDialog { if (updateCallback != null) updateCallback.onUpdate(); } + } else if (type == Entry.OTPType.MOTP) { + if (isNewEntry) { + Entry newEntry; + + newEntry = new Entry(type, secret, issuer, label, tagsAdapter.getActiveTags()); + newEntry.updateOTP(false); + newEntry.setLastUsed(System.currentTimeMillis()); + + adapter.addEntry(newEntry); + } else { + oldEntry.setIssuer(issuer, true); + oldEntry.setLabel(label); + oldEntry.setTags(tagsAdapter.getActiveTags()); + + oldEntry.updateOTP(false); + + if (updateCallback != null) + updateCallback.onUpdate(); + } + + callingActivity.refreshTags(); } dialog.dismiss(); diff --git a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java index 083f9ac6..7e157c29 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/Utilities/TokenCalculator.java @@ -23,11 +23,12 @@ package org.shadowice.flocke.andotp.Utilities; +import org.apache.commons.codec.binary.Hex; + import java.nio.ByteBuffer; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.Date; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -118,28 +119,25 @@ public class TokenCalculator { return r; } - public static String MOTP(String PIN, String secret) + public static String MOTP(String PIN, String secret, long epoch) { - Date dateNow = new Date(); - String epoch = "" + (dateNow.getTime()); - epoch = epoch.substring(0, epoch.length() - 4); - String otp = epoch + secret + PIN; + String epochText = String.valueOf(epoch / 10); + String hashText = epochText + secret + PIN; + String otp = ""; + try { // Create MD5 Hash MessageDigest digest = MessageDigest.getInstance("MD5"); - digest.update(otp.getBytes()); - byte messageDigest[] = digest.digest(); + digest.update(hashText.getBytes()); + byte[] messageDigest = digest.digest(); // Create Hex String - StringBuffer hexString = new StringBuffer(); - for (int i = 0; i < messageDigest.length; i++) - hexString.append(Integer.toHexString(0xFF & messageDigest[i])); - + String hexString = Hex.encodeHexString(messageDigest); otp = hexString.substring(0, 6); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); - otp=""; } + return otp; } } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java b/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java index 0808304b..ec4f4039 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/EntriesCardAdapter.java @@ -39,11 +39,10 @@ import android.text.TextUtils; import android.text.TextWatcher; import android.text.method.PasswordTransformationMethod; import android.view.LayoutInflater; -import android.view.Menu; import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.Filter; @@ -312,15 +311,21 @@ public class EntriesCardAdapter extends RecyclerView.Adapter public void onCardSingleClicked(final int position, final String text) { switch (settings.getTapSingle()) { case REVEAL: + establishPinIfNeeded(position); cardTapToRevealHandler(position); break; case COPY: + establishPinIfNeeded(position); copyHandler(position, text, false); break; case COPY_BACKGROUND: + establishPinIfNeeded(position); copyHandler(position, text, true); break; default: + // If tap-to-reveal is disabled a single tab still needs to establish the PIN + if (!settings.getTapToReveal()) + establishPinIfNeeded(position); break; } } @@ -329,12 +334,15 @@ public class EntriesCardAdapter extends RecyclerView.Adapter public void onCardDoubleClicked(final int position, final String text) { switch (settings.getTapDouble()) { case REVEAL: + establishPinIfNeeded(position); cardTapToRevealHandler(position); break; case COPY: + establishPinIfNeeded(position); copyHandler(position, text, false); break; case COPY_BACKGROUND: + establishPinIfNeeded(position); copyHandler(position, text, true); break; default: @@ -351,19 +359,18 @@ public class EntriesCardAdapter extends RecyclerView.Adapter public void onCounterLongPressed(int position) { setCounter(position); } - - @Override - public void onItemClickListener(int position) { - final Entry entry = displayedEntries.get(position); - if(entry.getType() == Entry.OTPType.MOTP && entry.getPin().isEmpty()){ - establishPIN(position); - } - } }); return viewHolder; } + private void establishPinIfNeeded(int position) { + final Entry entry = displayedEntries.get(position); + + if (entry.getType() == Entry.OTPType.MOTP && entry.getPin().isEmpty()) + establishPIN(position); + } + private void copyHandler(final int position, final String text, final boolean dropToBackground) { Tools.copyToClipboard(context, text); updateLastUsedAndFrequency(position, getRealIndex(position)); @@ -620,7 +627,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter input.setSingleLine(); input.requestFocus(); input.setTransformationMethod(new PasswordTransformationMethod()); - UIHelper.showKeyboard(context,input,true); + UIHelper.showKeyboard(context, input, true); FrameLayout container = new FrameLayout(context); container.setPaddingRelative(marginMedium, marginSmall, marginMedium, 0); @@ -629,26 +636,18 @@ public class EntriesCardAdapter extends RecyclerView.Adapter builder.setTitle(R.string.dialog_title_pin) .setCancelable(false) .setView(container) - .setPositiveButton(R.string.button_accept, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - int realIndex = getRealIndex(pos); - String newPin = input.getEditableText().toString(); + .setPositiveButton(R.string.button_accept, (dialogInterface, i) -> { + int realIndex = getRealIndex(pos); + String newPin = input.getEditableText().toString(); - displayedEntries.get(pos).setPin(newPin); - Entry e = entries.get(realIndex); - e.setPin(newPin); - e.updateOTP(true); - notifyDataSetChanged(); - UIHelper.hideKeyboard(context,input); - } - }) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - UIHelper.hideKeyboard(context,input); - } + displayedEntries.get(pos).setPin(newPin); + Entry e = entries.getEntry(realIndex); + e.setPin(newPin); + e.updateOTP(true); + notifyItemChanged(pos); + UIHelper.hideKeyboard(context, input); }) + .setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> UIHelper.hideKeyboard(context, input)) .create() .show(); } diff --git a/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java b/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java index f06d4e3a..ef578348 100644 --- a/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java +++ b/app/src/main/java/org/shadowice/flocke/andotp/View/EntryViewHolder.java @@ -151,14 +151,6 @@ public class EntryViewHolder extends RecyclerView.ViewHolder ); } }); - - itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (callback != null) - callback.onItemClickListener(getAdapterPosition()); - } - }); } @FunctionalInterface @@ -362,7 +354,6 @@ public class EntryViewHolder extends RecyclerView.ViewHolder void onCounterClicked(int position); void onCounterLongPressed(int position); - void onItemClickListener(int position); } /** * Updates the color of OTP to red (if expiring) or default color (if new OTP)