OTP认知
动态口令(OTP,One-Time Password)又称一次性密码,是使用密码技术实现的在客户端和服务器之间通过共享秘密的一种认证技术,是一种强认证技术,是增强目前静态口令认证的一种非常方便技术手段,是一种重要的双因素认证技术,动态口令认证技术包括客户端用于生成口令产生器的,动态令牌,是一个硬件设备,和用于管理令牌及口令认证的后台动态口令认证系统组成。
一、OTP历史溯源
动态口令(OTP)有一个同名确不同翻译的前辈,一次性密码(OTP, One-Time Pad),也叫密电本,是一种应用于军事领域的谍报技术,即对通信信息使用预先约定的一次性密电本进行加密和解密,使用后的密电本部分丢弃不再使用,能够做到一次一密。如果看过一些国内的谍战电视剧可能会对在二战时期,日本轰炸重庆中的一个号称“独臂大盗”的日本间谍有印象的话,他同日军通电使用的就是一次性密码技术,使用诺贝尔获奖的小说《The Good Earth》进行谍报编码,最后是被称为美国密码之父的赫伯特·亚德利破获。而目前在安全强认证领域使用的OTP动态密码技术,源于最早由RSA公司于1986年开发的RSA SecureID产品,动态密码并不是一次性密码技术,而是动态一次性口令技术。目前,国际上动态口令OTP有2大主流算法,一个是RSA SecurID ,一个是OATH组织的OTP算法。如果在国内来说的话,另一个是国密的OTP密码算法。RSA SecurID使用AES对称算法,OATH使用HMAC算法,国密算法使用的国密SM1(对称)和SM3(HASH)算法。
二、OTP认证原理与同步方法
动态口令的基本认证原理是在认证双方共享密钥,也称种子密钥,并使用的同一个种子密钥对某一个事件计数、或时间值、或者是异步挑战数进行密码算法计算,使用的算法有对称算法、HASH、HMAC,之后比较计算值是否一致进行认证。可以做到一次一个动态口令,使用后作废,口令长度通常为6-8个数字,使用方便,与通常的静态口令认证方式类似,使用方便与系统集成好,因此OTP动态口令技术的应用非常普遍,可以应用于多种系统渠道使用,如:Web应用、手机应用、电话应用、ATM自助终端等。
动态口令的同步机制有3种,即时间型、事件型和挑战与应答型,目前应用最多的是时间型动态口令,挑战与应答型动态口令的应用也逐渐增多,并且动态口令逐渐变为多种同步类型复合的机制发展,如时间+挑战与应答型。
目前在信息系统中使用的增强型认证技术包括:
1 USBKey: 申请PKI证书。
2 动态口令卡:打印好的密码刮刮卡。
3 动态短信:使用电信通道下发口令。
4 IC卡/SIM卡:内置与用户身份相关的信息。
5 生物特征:采用独一无二的生物特征来验证身份,如指纹。
6 动态令牌:动态口令生成器和认证系统。
现在直接上代码实现OTP动态密码:
private static final int[] DIGITS_POWER
= {1,10,100,1000,10000,100000,1000000,10000000,100000000};
public static byte[] hmac_sha1(byte[] keyBytes, byte[] text)throws NoSuchAlgorithmException, InvalidKeyException{
try {//ֵ
Mac hmacSha1;
try {
hmacSha1 = Mac.getInstance("HmacSHA1");
} catch (NoSuchAlgorithmException nsae) {
hmacSha1 = Mac.getInstance("HMAC-SHA-1");
}
SecretKeySpec macKey =new SecretKeySpec(keyBytes, "RAW");
hmacSha1.init(macKey);
return hmacSha1.doFinal(text);
} catch (GeneralSecurityException gse) {
throw new UndeclaredThrowableException(gse);
}
}
public static String generateOTP(byte[] secret,long movingFactor,int codeDigits)throws NoSuchAlgorithmException, InvalidKeyException
{
StringBuffer result = new StringBuffer("");
byte[] text = new byte[6];
for (int i =text.length-1; i >=0; i--) {
text[i] = (byte) (movingFactor & 0xff ); //
movingFactor >>= 6;
}
byte[] hash = hmac_sha1(secret, text); //Step 1: Generate an HMAC-SHA-1 value
int offset =( hash[hash.length - 1] & 0xf)+3; //
int binary =
((hash[offset] & 0x7f) << 24)
| ((hash[offset - 1] & 0xff) << 16)
| ((hash[offset - 2] & 0xff) << 8)
| (hash[offset - 3] & 0xff); //Generate a 4-byte string
int otp = binary % DIGITS_POWER[codeDigits-1];
result .append(Integer.toString(otp));
while (result.length() < codeDigits) {
result.insert(0, "0"); //Compute an HOTP value
}
return result.toString();
}
测试: