OneTimePassword
TOTP 和 HOTP 一次性密码 for iOS
The OneTimePassword 库是 Authenticator 的核心。它可以根据 RFC 4226 和 RFC 6238 制定标准生成基于时间的和基于计数器的一次性密码。它还可以读取和生成用于设置 OTP 令牌的常用“otpauth://” URL,并将令牌保存和加载到 iOS 中的安全密钥链。
安装
Carthage
将以下行添加到您的 Cartfile
github "mattrubin/OneTimePassword" ~> 3.2
接着运行 carthage update OneTimePassword
安装框架的最新版本。
请务必查阅Carthage的README文件,获取有关如何在应用程序中添加框架的最新说明,请参阅在应用程序中添加框架。
CocoaPods
将以下行添加到您的Podfile
pod 'OneTimePassword', '~> 3.2'
OneTimePassword,像所有用Swift编写的pod一样,只能作为框架进行集成。请确保在Podfile或目标中添加use_frameworks!
来选择框架而不是静态库。
然后运行pod install
以安装框架的最新版本。
用法
OneTimePassword的最新版本可以用Swift 4.2或Swift 5编译,可以使用Swift编译器的兼容模式与Swift 4或Swift 5项目相关联。要使用较早版本的Swift使用OneTimePassword,请查看代码库中的
swift-4
,swift-3
和swift-2.3
分支。要在一个基于Objective-C的项目中使用OneTimePassword,请查看objc
分支和1.x版本。
创建令牌
包含生成一次性密码所需的参数的Generator
结构。将generator
与具有相应name
和issuer
字符串的Token
结构相关联。
要从otpauth://
URL初始化令牌
if let token = Token(url: url) {
print("Password: \(token.currentPassword)")
} else {
print("Invalid token URL")
}
从用户输入创建生成器与令牌
此示例假定用户以Base32编码字符串的形式提供密钥。要使用下面的解码函数,请将
import Base32
添加到Swift文件的顶部。
let name = "..."
let issuer = "..."
let secretString = "..."
guard let secretData = MF_Base32Codec.data(fromBase32String: secretString),
!secretData.isEmpty else {
print("Invalid secret")
return nil
}
guard let generator = Generator(
factor: .timer(period: 30),
secret: secretData,
algorithm: .sha1,
digits: 6) else {
print("Invalid generator parameters")
return nil
}
let token = Token(name: name, issuer: issuer, generator: generator)
return token
生成一次性密码
生成当前密码
let password = token.currentPassword
在特定时间点生成密码
let time = Date(timeIntervalSince1970: ...)
do {
let passwordAtTime = try token.generator.password(at: time)
print("Password at time: \(passwordAtTime)")
} catch {
print("Cannot generate password for invalid time \(time)")
}
持久性
令牌持久性由表示iOS系统密钥库的Keychain
类管理。
let keychain = Keychain.sharedInstance
PersistentToken
结构体表示已保存在密钥库中的Token
,并将一个token
与密钥库提供的具有数据标识符
关联。
将令牌保存到密钥库
do {
let persistentToken = try keychain.add(token)
print("Saved to keychain with identifier: \(persistentToken.identifier)")
} catch {
print("Keychain error: \(error)")
}
从密钥库检索令牌
do {
if let persistentToken = try keychain.persistentToken(withIdentifier: identifier) {
print("Retrieved token: \(persistentToken.token)")
}
// Or...
let persistentTokens = try keychain.allPersistentTokens()
print("All tokens: \(persistentTokens.map({ $0.token }))")
} catch {
print("Keychain error: \(error)")
}
更新密钥库中保存的令牌
do {
let updatedPersistentToken = try keychain.update(persistentToken, with: token)
print("Updated token: \(updatedPersistentToken)")
} catch {
print("Keychain error: \(error)")
}
从密钥库中删除令牌
do {
try keychain.delete(persistentToken)
print("Deleted token.")
} catch {
print("Keychain error: \(error)")
}
许可
OneTimePassword 由 Matt Rubin 和 OneTimePassword 作者 创建,并按照 MIT 许可证 发布。