import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
+import android.content.res.Resources;
import android.net.Uri;
import com.google.android.apps.authenticator.Base32String;
public class Token {
public static class TokenUriInvalidException extends Exception {
private static final long serialVersionUID = -1108624734612362345L;
+ private static int errorResourceID = 0;
+ public TokenUriInvalidException(int id) {
+ this.errorResourceID = id;
+ }
+ public int getErrorResourceID() {
+ return this.errorResourceID;
+ }
}
public static enum TokenType {
private long mLastCode;
private Token(Uri uri) throws TokenUriInvalidException {
- if (!uri.getScheme().equals("otpauth"))
- throw new TokenUriInvalidException();
+ String scheme = uri.getScheme();
+ String authority = uri.getAuthority();
+ String path = uri.getPath();
+
+ if (scheme == null)
+ throw new TokenUriInvalidException(R.string.error_no_scheme);
+ if (authority == null)
+ throw new TokenUriInvalidException(R.string.error_no_authority);
+ if (path == null)
+ throw new TokenUriInvalidException(R.string.error_no_path);
- if (uri.getAuthority().equals("totp"))
+ if (!scheme.equals("otpauth"))
+ throw new TokenUriInvalidException(R.string.error_invalid_scheme);
+
+ if (authority.equals("totp"))
mType = TokenType.TOTP;
- else if (uri.getAuthority().equals("hotp"))
+ else if (authority.equals("hotp"))
mType = TokenType.HOTP;
else
- throw new TokenUriInvalidException();
-
- String path = uri.getPath();
- if (path == null)
- throw new TokenUriInvalidException();
+ throw new TokenUriInvalidException(R.string.error_invalid_authority);
// Strip the path of its leading '/'
for (int i = 0; path.charAt(i) == '/'; i++)
path = path.substring(1);
if (path.length() == 0)
- throw new TokenUriInvalidException();
+ throw new TokenUriInvalidException(R.string.error_invalid_path);
int i = path.indexOf(':');
mIssuerExt = i < 0 ? "" : path.substring(0, i);
try {
Mac.getInstance("Hmac" + mAlgorithm);
} catch (NoSuchAlgorithmException e1) {
- throw new TokenUriInvalidException();
+ throw new TokenUriInvalidException(R.string.error_no_algorithm);
}
try {
d = "6";
mDigits = Integer.parseInt(d);
if (mDigits != 6 && mDigits != 8)
- throw new TokenUriInvalidException();
+ throw new TokenUriInvalidException(R.string.error_invalid_digits);
} catch (NumberFormatException e) {
- throw new TokenUriInvalidException();
+ throw new TokenUriInvalidException(R.string.error_invalid_number);
}
switch (mType) {
c = "0";
mCounter = Long.parseLong(c) - 1;
} catch (NumberFormatException e) {
- throw new TokenUriInvalidException();
+ throw new TokenUriInvalidException(R.string.error_invalid_counter);
}
break;
case TOTP:
p = "30";
mPeriod = Integer.parseInt(p);
} catch (NumberFormatException e) {
- throw new TokenUriInvalidException();
+ throw new TokenUriInvalidException(R.string.error_invalid_period);
}
break;
}
String s = uri.getQueryParameter("secret");
mSecret = Base32String.decode(s);
} catch (DecodingException e) {
- throw new TokenUriInvalidException();
+ throw new TokenUriInvalidException(R.string.error_invalid_secret);
}
}
long time = System.currentTimeMillis();
if (mType == TokenType.TOTP)
- return (int) (time % (mPeriod * 1000) / mPeriod);
+ return 1000 - (int) (time % (mPeriod * 1000) / mPeriod);
long state = (time - mLastCode) / 60;
- return (int) (state > 1000 ? 1000 : state);
+ return 1000 - (int) (state > 1000 ? 1000 : state);
}
public Uri toUri() {