仿新浪微盾客户端项目简介四

上节我们说到我们主要的算法是在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算法后值,起到一个不产生重复值的效果,提高威盾的安全性。

posted on 2014-03-04 07:26  laozhu1124  阅读(1471)  评论(0编辑  收藏  举报

淘宝免费计数器