zoukankan      html  css  js  c++  java
  • 仿新浪微盾客户端项目简介四

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

  • 相关阅读:
    [Shoi2007]Vote 善意的投票
    [CQOI2015]任务查询系统
    [SDOI2013]森林
    HttpClient 教程 (二)
    /system改成可写
    Netbeans 6.8 + apktool_2.0.0b9 动态调试smali文件
    把中文版NetBeans改成英文版
    ZjDroid工具介绍及脱壳详细示例
    grep过滤搜索
    android Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)
  • 原文地址:https://www.cnblogs.com/manuosex/p/3578140.html
Copyright © 2011-2022 走看看