关于双重认证

2021-09-01 • 预计阅读时间 2 分钟

双重认证其实又叫多重要素验证.用户获得授权的时候需要提供两种以上的认证才可以.双重认证(英语:Two-factor authenticatio,缩写为2FA),又译为双重验证、双因子认证、双因素认证、二元认证,又称两步骤验证(2-Step Verification,又译两步验证),是多重要素验证中的一个特例,使用两种不同的元素,合并在一起,来确认用户的身份。

近些年在日常使用中遇到最多就是短信验证了.之前银行转账时候的u盾,都属于这个范畴.目前很多网站都支持双重认证,这些很多是支持基于基于时间的一次性密码算法(TOTP)每30秒或者60秒生成一组6位数字.并且客户端的时间要和服务器时间的误差在可控范围内.这种方案不需要联网,协议公开,不需要专用设备.

本来想找个支持2FA的网站列表……目前来看是没有.不过还是有点规律的,跟开发者相关的网站基本上都支持……国外的基本都支持.国内这几年由于手机实名等原因吧,手机短信验证某种程度上代替了基于TOTP2FA认证方式.

身份验证器推荐

Microsoft Authenticator App 算是目前最值得推荐的了……

其他的资料

TOTP的实现

TOTP目前比较通用的都是基于HmacSHA1来生成的.

package org.wentao.security.totp;

import org.apache.commons.codec.binary.Base32;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class TOTPAuthenticator {

    public boolean verifyCode(String secret, int code, int variance)
            throws InvalidKeyException, NoSuchAlgorithmException {
        long timeIndex = System.currentTimeMillis() / 1000 / 30;
        byte[] secretBytes = new Base32().decode(secret);
        for (int i = -variance; i <= variance; i++) {
            long calcCode = getCode(secretBytes, timeIndex + i);
            System.out.println("server side code is " + calcCode);
            return calcCode == code;
        }
        return false;
    }

    public long getCode(byte[] secret, long timeIndex)
            throws NoSuchAlgorithmException, InvalidKeyException {
        SecretKeySpec signKey = new SecretKeySpec(secret, "HmacSHA1");
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putLong(timeIndex);
        byte[] timeBytes = buffer.array();
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(signKey);
        byte[] hash = mac.doFinal(timeBytes);
        int offset = hash[19] & 0xf;
        long truncatedHash = hash[offset] & 0x7f;
        for (int i = 1; i < 4; i++) {
            truncatedHash <<= 8;
            truncatedHash |= hash[offset + i] & 0xff;
        }
        return truncatedHash %= 1000000;
    }
}

这个支持30秒内的有效时间.

dev2FA

wentao

写点代码,解决点问题。

使用Traefik处理一些复杂的路由规则

利用Authelia实现SSO