上节我们说到我们主要的算法是在Google的一个开源项目Google Authenticator 修改的。那么我们窥探一下Google Authenticator的全貌。
我们通过源代码来了解,上代码:
首先是一些噼里啪啦的定义的常量,变量。
private static final int PASS_CODE_LENGTH = 6;
static final int INTERVAL = 30;
private static final int ADJACENT_INTERVALS = 1;
private static final int PIN_MODULO = (int) Math.pow(10, PASS_CODE_LENGTH); // pow是求10的PASS_CODE_LENGTH次方
private final Signer signer;
private final int codeLength;
private final int intervalPeriod;
public boolean isCreated;
public long timeOffset;
private Handler handler;
这些所谓的常量了,定义了他产生的的长度和时间。从这些定义的常量我们可以得出来这么的结果。他是每30秒的中的时间了产生了一个不同的code,并且他产生的值是在000000-100000中的值。下面变量主要是判断他是否创建了,并且由handler来异步处理相应的结果。
下面源代码是一个接口和四个构造函数方法的重载。
interface Signer {
byte[] sign(byte[] data) throws GeneralSecurityException;
}
public PasscodeGenerator(Mac mac) {
this(mac, PASS_CODE_LENGTH, INTERVAL);
}
public PasscodeGenerator(final Mac mac, int passCodeLength, int interval) {
this(new Signer() {
public byte[] sign(byte[] data) {
return mac.doFinal(data);
}
}, passCodeLength, interval);
}
public PasscodeGenerator(final Mac mac, int passCodeLength, int interval,
Handler handler) {
this(mac, passCodeLength, interval);
this.handler = handler;
}
public PasscodeGenerator(Signer signer, int passCodeLength, int interval) {
this.signer = signer;
this.codeLength = passCodeLength;
this.intervalPeriod = interval;
}
这个接口是实现观察者模式,能将byte数组转换成签名后到底byte的数组了。而不同的构造函数,无非是实现方法层面的多态,传递不同的参数,得到的处理结果.
下面的源代码做的归根结底,就是这么一件事情,能够根据传递进来的时间类型来产生了相应的值输出了,当然了,这又有一些的复杂的逻辑判断了,使其不产生了相应重复的数字。
private String padOutput(int value) {
String result = Integer.toString(value);
for (int i = result.length(); i < codeLength; i++) {
result = "0" + result;
}
return result;
}
public String generateTimeoutCode(boolean isCreated ,long timeOffset)
throws GeneralSecurityException {
this.timeOffset = timeOffset;
this.isCreated = isCreated;
return generateResponseCode(clock.getCurrentInterval());
}
public String generateResponseCode(long challenge)
throws GeneralSecurityException {
byte[] value = ByteBuffer.allocate(8).putLong(challenge).array();
return generateResponseCode(value);
}
public String generateResponseCode(byte[] challenge)
throws GeneralSecurityException {
byte[] hash = signer.sign(challenge);
int offset = hash[hash.length - 1] & 0xF;
int truncatedHash = hashToInt(hash, offset) & 0x7FFFFFFF;
int pinValue = truncatedHash % PIN_MODULO;
return padOutput(pinValue);
}
private int hashToInt(byte[] bytes, int start) {
DataInput input = new DataInputStream(new ByteArrayInputStream(bytes,
start, bytes.length - start));
int val;
try {
val = input.readInt();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return val;
}
public boolean verifyResponseCode(long challenge, String response)
throws GeneralSecurityException {
String expectedResponse = generateResponseCode(challenge);
return expectedResponse.equals(response);
}
public boolean verifyTimeoutCode(String timeoutCode)
throws GeneralSecurityException {
return verifyTimeoutCode(timeoutCode, ADJACENT_INTERVALS,
ADJACENT_INTERVALS);
}
public boolean verifyTimeoutCode(String timeoutCode, int pastIntervals,
int futureIntervals) throws GeneralSecurityException {
long currentInterval = clock.getCurrentInterval();
String expectedResponse = generateResponseCode(currentInterval);
if (expectedResponse.equals(timeoutCode)) {
return true;
}
for (int i = 1; i <= pastIntervals; i++) {
String pastResponse = generateResponseCode(currentInterval - i);
if (pastResponse.equals(timeoutCode)) {
return true;
}
}
for (int i = 1; i <= futureIntervals; i++) {
String futureResponse = generateResponseCode(currentInterval + i);
if (futureResponse.equals(timeoutCode)) {
return true;
}
}
return false;
}
下面的源代码,是通过了colock对象来产生相应值。
private IntervalClock clock = new IntervalClock() {
public long getCurrentInterval() {
long currentTimeSeconds = (System.currentTimeMillis() - timeOffset) / 1000;
long count = currentTimeSeconds / getIntervalPeriod();
if (isCreated) {
long i = getIntervalPeriod()
- (currentTimeSeconds % getIntervalPeriod());
Message msg = new Message();
msg.what = MainActivity.UPDATE_COUNTDOWN;
msg.arg1 = (int) i;
handler.sendMessage(msg);
}
return count;
}
public int getIntervalPeriod() {
return intervalPeriod;
}
};
interface IntervalClock {
int getIntervalPeriod();
long getCurrentInterval();
}
观察源代码,我们可以清晰开出来,相应时间的毫秒通过整除,求摸这些基本的变化,来得到最终的6位时间格式的值。
总之,通过这个类,能够得到了hopt算法后值,起到一个不产生重复值的效果,提高威盾的安全性。
时间: 2024-09-17 04:16:06