package net.coding.program.login.auth;
import android.net.Uri;
import android.util.Log;
import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* Created by chenchao on 15/7/1.
*/
public class AuthInfo implements Serializable {
public static final String LOCAL_TAG = "AuthInfo";
public static final String PARAM_SECRET = "secret";
private static final String PARAM_ISSUER = "issuer";
private static final TotpCounter mTotpCounter = new TotpCounter(PasscodeGenerator.INTERVAL);
private final String scheme;
private final String path;
private final String authority;
private final String issuer;
private final String secret;
TotpClock clock;
TotpCounter counter = new TotpCounter(PasscodeGenerator.INTERVAL);
private String uriString;
public AuthInfo(String uriString, TotpClock clock) {
this.uriString = uriString;
Uri uri = Uri.parse(uriString);
scheme = uri.getScheme();
path = uri.getPath();
authority = uri.getAuthority();
issuer = uri.getQueryParameter(PARAM_ISSUER);
this.secret = uri.getQueryParameter(PARAM_SECRET);
this.clock = clock;
}
public static boolean isAuthUrl(String uriString) {
Uri uri = Uri.parse(uriString);
return uri.getScheme() != null &&
uri.getPath() != null &&
uri.getAuthority() != null &&
uri.getQueryParameter(PARAM_ISSUER) != null &&
uri.getQueryParameter(PARAM_SECRET) != null &&
"totp".equals(uri.getAuthority());
}
public static TotpCounter getTotpCountet() {
return mTotpCounter;
}
static Signer getSigningOracle(String secret) {
try {
byte[] keyBytes = decodeKey(secret);
final Mac mac = Mac.getInstance("HMACSHA1");
mac.init(new SecretKeySpec(keyBytes, ""));
// Create a signer object out of the standard Java MAC implementation.
return new Signer() {
@Override
public byte[] sign(byte[] data) {
return mac.doFinal(data);
}
};
} catch (Base32String.DecodingException error) {
Log.e(LOCAL_TAG, error.getMessage());
} catch (NoSuchAlgorithmException error) {
Log.e(LOCAL_TAG, error.getMessage());
} catch (InvalidKeyException error) {
Log.e(LOCAL_TAG, error.getMessage());
}
return null;
}
private static byte[] decodeKey(String secret) throws Base32String.DecodingException {
return Base32String.decode(secret);
}
public String getUriString() {
return uriString;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AuthInfo info = (AuthInfo) o;
if (scheme != null ? !scheme.equals(info.scheme) : info.scheme != null) return false;
if (path != null ? !path.equals(info.path) : info.path != null) return false;
if (authority != null ? !authority.equals(info.authority) : info.authority != null)
return false;
if (issuer != null ? !issuer.equals(info.issuer) : info.issuer != null) return false;
return !(secret != null ? !secret.equals(info.secret) : info.secret != null);
}
@Override
public int hashCode() {
int result = scheme != null ? scheme.hashCode() : 0;
result = 31 * result + (path != null ? path.hashCode() : 0);
result = 31 * result + (authority != null ? authority.hashCode() : 0);
result = 31 * result + (issuer != null ? issuer.hashCode() : 0);
result = 31 * result + (secret != null ? secret.hashCode() : 0);
return result;
}
// 其它的都相同,只有密钥不同
public boolean equalsAccount(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AuthInfo info = (AuthInfo) o;
if (scheme != null ? !scheme.equals(info.scheme) : info.scheme != null) return false;
if (path != null ? !path.equals(info.path) : info.path != null) return false;
if (authority != null ? !authority.equals(info.authority) : info.authority != null)
return false;
if (issuer != null ? !issuer.equals(info.issuer) : info.issuer != null) return false;
return !(secret != null ? secret.equals(info.secret) : info.secret != null);
}
public String getCode() {
String code = "";
try {
Signer signer = getSigningOracle(secret);
long state = counter.getValueAtTime(Utilities.millisToSeconds(clock.currentTimeMillis()));
PasscodeGenerator pcg = new PasscodeGenerator(signer);
code = pcg.generateResponseCode(state);
} catch (Exception e) {
}
return code;
}
public String getCompany() {
return issuer;
}
public String getAccountName() {
String name = path;
if (path.startsWith("/")) {
name = path.substring(1);
}
return name;
}
}