一次性密码(One Time Password)简称OTP,是不能重复使用的密码,即使被攻击者截获,也无法使用该密码通过身份验证,能够有效的增强数字系统的安全性。

什么是一次性密码(One Time Password)

一次性密码(One Time Password)简称OTP,是一种无需记忆、便捷输入、不能重复使用的密码,能够有效解决用户因密码泄露导致的安全问题,还可以减少因用户忘记密码而必须进行重置密码的繁琐操作。一次性密码通常是通过短信、电子邮件发送给用户,或者是由通用的身份验证应用程序生成并展示给用户,通常是4到8位的数字、字母或数字字母组合字符串,用户只需要在需要进行身份认证时输入收到的字符串,即可完成身份认证。

一次性密码的实现方式

一次性密码有两种不同的实现方式,其一为基于时间的一次性密码(Time-based One-Time Password)简称TOTP,另一种为基于哈希的一次性密码(Hash-based One-Time Password)简称HOTP。

1.基于时间的一次性密码(Time-based One-Time Password)

基于时间的一次性密码(Time-based One-Time Password)简称TOTP,也被称为时间同步动态密码,是一种基于时间和密钥的一次性密码算法,TOTP的优势在于利用了当前时间作为动态因素,使得身份验证应用程序可以在没有网络连接的情况下生成一次性密码,TOTP的缺点时对时间的同步要求较高,并且需要在一定的时间窗口内进行密码验证,超过时间窗口则密码会失效。

2.基于哈希的一次性密码(Hash-based One-Time Password)

基于哈希的一次性密码(Hash-based One-Time Password)简称HOTP,是一种基于密钥和计数器的一次性密码算法,当用户请求一个新的密码时,计数器会自动增加,然后使用哈希函数和密钥生成一个新的密码,这种方法的优点是不依赖时间,因此没有超时时间窗口的问题,在密码生成后的任意时间都可以进行身份认证,相应的缺点是需要保证身份验证应用程序中计数器的值与身份验证服务器中计数器的值保持一致。

3.一次性密码的获取方式

一次性密码可以由服务器生成,通过短信或电子邮件的方式发送给用户,这两种方式的优点是方便直观,无需用户保管密钥信息,缺点是依赖手机网络或电子邮件系统,容易受到短信劫持攻击或电子邮件劫持攻击。 一次性密码还可以通过配置身份验证应用程序来实现一次性密码的生成,有效防止了劫持攻击,但是需要用户妥善保管密钥信息,防止由于密钥泄露导致的安全问题。

在系统中添加一次性密码支持

为了方便开发人员在系统中添加一次性密码支持,有效提高系统安全性,在工具包中提供了一次性密码工具,简化开发人员的工作。

1.依赖引用

最新版本为1.2.2,使用时请替换${version}为对应的版本号 Maven:

<dependency>
    <groupId>org.nervousync</groupId>
	<artifactId>utils-jdk11</artifactId>
    <version>${version}</version>
</dependency>

Gradle:

Manual: compileOnly group: 'org.nervousync', name: 'utils-jdk11', version: '${version}'
Short: compileOnly 'org.nervousync:utils-jdk11:${version}'

SBT:

libraryDependencies += "org.nervousync" % "utils-jdk11" % "${version}" % "provided"

Ivy:

<dependency org="org.nervousync" name="utils-jdk11" rev="${version}"/>

2.生成随机密钥

调用 org.nervousync.utils.OTPUtils 的 generateRandomKey 静态方法生成随机密钥字符串,返回值为Base32编码的随机密钥。

generateRandomKey的参数:

参数名 数据类型 备注
algorithm 字符串 安全随机数算法,默认值为SHA1PRNG
seed 字符串 Base64编码的密钥种子字符串,默认值为TmVydm91c3luY0RlZmF1bHRTZWNyZXRTZWVk
size int 密钥的字节数组长度,默认值为10

3.一次性密码的生成与验证

3.1 基于时间的一次性密码(Time-based One-Time Password)

由于用户与服务器可能处于不同的时区,因此使用基于时间的一次性密码前,需要校正时间偏移,保证在以后的密码验证时快速计算并验证一次性密码。 首先需要将生成的随机密钥通过文本或二维码的方式展示给用户,用户在身份验证应用程序中添加保存随机密钥,然后用户将身份验证应用程序生成的一次性密码发送给服务器,服务器根据随机密钥和用户发回的一次性密码计算时间偏移,并将时间偏移与随机密钥一起妥善保存,在以后的身份认证中,可以通过保存的随机密钥和时间偏移来验证用户输入的一次性密码是否有效。

时间偏移计算:

调用 org.nervousync.utils.OTPUtils 的 calculateFixedTime 静态方法计算时间偏移值,返回值为计算出的时间偏移值(单位:毫秒)

calculateFixedTime的参数:

参数名 数据类型 备注
calcType OTPUtils.CalcType 密码算法类型枚举值,支持算法包括HmacSHA1、HmacSHA256、HmacSHA512,默认值为HmacSHA1
secret 字符串 Base32编码的随机密钥
authCode int 用户填写的一次性密码
syncCount int 一次性密码有效时间(单位:秒),默认值为30

一次性密码生成:

调用 org.nervousync.utils.OTPUtils 的 generateTOTPCode 静态方法生成一次性密码,返回值为生成的一次性密码。

generateTOTPCode的参数:

参数名 数据类型 备注
calcType OTPUtils.CalcType 密码算法类型枚举值,支持算法包括HmacSHA1、HmacSHA256、HmacSHA512,默认值为HmacSHA1
secret 字符串 Base32编码的随机密钥
fixedTime long 用户的时间偏移值
syncCount int 一次性密码有效时间(单位:秒),默认值为30

一次性密码验证:

调用 org.nervousync.utils.OTPUtils 的 validateTOTPCode 静态方法验证一次性密码,返回值为验证结果。

validateTOTPCode的参数:

参数名 数据类型 备注
authCode int 用户填写的一次性密码
calcType OTPUtils.CalcType 密码算法类型枚举值,支持算法包括HmacSHA1、HmacSHA256、HmacSHA512,默认值为HmacSHA1
secret 字符串 Base32编码的随机密钥
fixedTime long 用户的时间偏移值
syncCount int 一次性密码有效时间(单位:秒),默认值为30
fixWindow int 允许的有效时间窗口偏移值,默认值为3

3.2 基于哈希的一次性密码(Hash-based One-Time Password)

一次性密码生成:

调用 org.nervousync.utils.OTPUtils 的 generateHOTPCode 静态方法生成一次性密码,返回值为生成的一次性密码。

generateHOTPCode的参数:

参数名 数据类型 备注
calcType OTPUtils.CalcType 密码算法类型枚举值,支持算法包括HmacSHA1、HmacSHA256、HmacSHA512,默认值为HmacSHA1
secret 字符串 Base32编码的随机密钥
randomCode long 计数器值

一次性密码验证:

调用 org.nervousync.utils.OTPUtils 的 validateHOTPCode 静态方法验证一次性密码,返回值为验证结果。

validateHOTPCode的参数:

参数名 数据类型 备注
authCode int 用户填写的一次性密码
calcType OTPUtils.CalcType 密码算法类型枚举值,支持算法包括HmacSHA1、HmacSHA256、HmacSHA512,默认值为HmacSHA1
secret 字符串 Base32编码的随机密钥
randomCode long 计数器值

版权信息

转载请注明出处:https://blog.51cto.com/commandos