关于双重认证
2021-09-01 • 预计阅读时间 2 分钟
2021-09-01 • 预计阅读时间 2 分钟
双重认证其实又叫多重要素验证.用户获得授权的时候需要提供两种以上的认证才可以.双重认证(英语:Two-factor authenticatio
,缩写为2FA
),又译为双重验证、双因子认证、双因素认证、二元认证,又称两步骤验证(2-Step Verification
,又译两步验证),是多重要素验证中的一个特例,使用两种不同的元素,合并在一起,来确认用户的身份。
近些年在日常使用中遇到最多就是短信验证了.之前银行转账时候的u盾,都属于这个范畴.目前很多网站都支持双重认证,这些很多是支持基于基于时间的一次性密码算法(TOTP)每30秒或者60秒生成一组6位数字.并且客户端的时间要和服务器时间的误差在可控范围内.这种方案不需要联网,协议公开,不需要专用设备.
本来想找个支持2FA
的网站列表……目前来看是没有.不过还是有点规律的,跟开发者相关的网站基本上都支持……国外的基本都支持.国内这几年由于手机实名等原因吧,手机短信验证某种程度上代替了基于TOTP
的2FA
认证方式.
Microsoft Authenticator App 算是目前最值得推荐的了……
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秒内的有效时间.