Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mattrubin/OneTimePassword
🔑 A small library for generating TOTP and HOTP one-time passwords on iOS.
https://github.com/mattrubin/OneTimePassword
2fa hotp ios one-time-passwords otp swift totp two-factor-authentication
Last synced: 3 months ago
JSON representation
🔑 A small library for generating TOTP and HOTP one-time passwords on iOS.
- Host: GitHub
- URL: https://github.com/mattrubin/OneTimePassword
- Owner: mattrubin
- License: mit
- Created: 2014-07-10T22:49:19.000Z (over 10 years ago)
- Default Branch: develop
- Last Pushed: 2024-01-20T06:32:25.000Z (10 months ago)
- Last Synced: 2024-07-21T23:46:41.698Z (4 months ago)
- Topics: 2fa, hotp, ios, one-time-passwords, otp, swift, totp, two-factor-authentication
- Language: Swift
- Homepage:
- Size: 1.16 MB
- Stars: 334
- Watchers: 13
- Forks: 102
- Open Issues: 25
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.md
- Authors: AUTHORS.txt
Awesome Lists containing this project
README
# OneTimePassword
### TOTP and HOTP one-time passwords for iOS[![Xcode CI status](https://github.com/mattrubin/OneTimePassword/actions/workflows/xcode.yml/badge.svg)](https://github.com/mattrubin/OneTimePassword/actions/workflows/xcode.yml)
[![SPM CI status](https://github.com/mattrubin/OneTimePassword/actions/workflows/spm.yml/badge.svg)](https://github.com/mattrubin/OneTimePassword/actions/workflows/spm.yml)
[![Carthage CI status](https://github.com/mattrubin/OneTimePassword/actions/workflows/carthage.yml/badge.svg)](https://github.com/mattrubin/OneTimePassword/actions/workflows/carthage.yml)
[![Code Coverage](https://img.shields.io/codecov/c/github/mattrubin/OneTimePassword/develop.svg)](https://codecov.io/gh/mattrubin/OneTimePassword)
[![Swift 5.x](https://img.shields.io/badge/swift-5.x-orange.svg)](#usage)
![Platforms: iOS, macOS, watchOS](https://img.shields.io/badge/platforms-iOS%20%7C%20macOS%20%7C%20watchOS-blue.svg)
[![MIT License](https://img.shields.io/badge/license-MIT-lightgray.svg)](LICENSE.md)The OneTimePassword library is the core of [Authenticator][]. It can generate both [time-based][RFC 6238] and [counter-based][RFC 4226] one-time passwords as standardized in [RFC 4226][] and [RFC 6238][]. It can also read and generate the ["otpauth://" URLs][otpauth] commonly used to set up OTP tokens, and can save and load tokens to and from the iOS secure keychain.
[Authenticator]: https://mattrubin.me/authenticator/
[RFC 6238]: https://tools.ietf.org/html/rfc6238
[RFC 4226]: https://tools.ietf.org/html/rfc4226
[otpauth]: https://github.com/google/google-authenticator/wiki/Key-Uri-Format## Installation
### [Carthage][]
Add the following line to your [Cartfile][]:
````config
github "mattrubin/OneTimePassword" ~> 4.0
````Then run `carthage update OneTimePassword` to install the latest version of the framework.
Be sure to check the Carthage README file for the latest instructions on [adding frameworks to an application][carthage-instructions].
[Carthage]: https://github.com/Carthage/Carthage
[Cartfile]: https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile
[carthage-instructions]: https://github.com/Carthage/Carthage/blob/master/README.md#adding-frameworks-to-an-application### [SPM][]
Add the following line to the `dependencies` section of your [package manifest][Package.swift]:
```swift
.package(url: "https://github.com/mattrubin/OneTimePassword.git", from: "4.0.0"),
```Then add `"OneTimePassword"` to the dependencies array of any target which should be linked with this library.
[SPM]: https://swift.org/package-manager/
[Package.swift]: https://github.com/apple/swift-package-manager/tree/master/Documentation## Usage
> The [latest version][swift-5] of OneTimePassword compiles with Swift 5. To use OneTimePassword with earlier versions of Swift, check out the [`swift-4.2`][swift-4.2], [`swift-4`][swift-4], [`swift-3`][swift-3], and [`swift-2.3`][swift-2.3] branches. To use OneTimePassword in an Objective-C based project, check out the [`objc` branch][objc] and the [1.x releases][releases].
[swift-5]: https://github.com/mattrubin/OneTimePassword/tree/swift-5
[swift-4.2]: https://github.com/mattrubin/OneTimePassword/tree/swift-4.2
[swift-4]: https://github.com/mattrubin/OneTimePassword/tree/swift-4
[swift-3]: https://github.com/mattrubin/OneTimePassword/tree/swift-3
[swift-2.3]: https://github.com/mattrubin/OneTimePassword/tree/swift-2.3
[objc]: https://github.com/mattrubin/OneTimePassword/tree/objc
[releases]: https://github.com/mattrubin/OneTimePassword/releases### Create a Token
The [`Generator`][Generator] struct contains the parameters necessary to generate a one-time password. The [`Token`][Token] struct associates a `generator` with a `name` and an `issuer` string.
[Generator]: ./Sources/Generator.swift
[Token]: ./Sources/Token.swiftTo initialize a token with an `otpauth://` url:
````swift
if let token = Token(url: url) {
print("Password: \(token.currentPassword)")
} else {
print("Invalid token URL")
}
````To create a generator and a token from user input:
> This example assumes the user provides the secret as a Base32-encoded string. To use the decoding function seen below, add `import Base32` to the top of your Swift file.
````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
````### Generate a One-Time Password
To generate the current password:
````swift
let password = token.currentPassword
````To generate the password at a specific point in time:
````swift
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)")
}
````### Persistence
Token persistence is managed by the [`Keychain`][Keychain] class, which represents the iOS system keychain.
````swift
let keychain = Keychain.sharedInstance
````The [`PersistentToken`][PersistentToken] struct represents a `Token` that has been saved to the keychain, and associates a `token` with a keychain-provided data `identifier`.
[Keychain]: ./Sources/Keychain.swift
[PersistentToken]: ./Sources/PersistentToken.swiftTo save a token to the keychain:
````swift
do {
let persistentToken = try keychain.add(token)
print("Saved to keychain with identifier: \(persistentToken.identifier)")
} catch {
print("Keychain error: \(error)")
}
````To retrieve a token from the keychain:
````swift
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)")
}
````To update a saved token in the keychain:
````swift
do {
let updatedPersistentToken = try keychain.update(persistentToken, with: token)
print("Updated token: \(updatedPersistentToken)")
} catch {
print("Keychain error: \(error)")
}
````To delete a token from the keychain:
````swift
do {
try keychain.delete(persistentToken)
print("Deleted token.")
} catch {
print("Keychain error: \(error)")
}
````## License
OneTimePassword was created by [Matt Rubin][] and the [OneTimePassword authors](AUTHORS.txt) and is released under the [MIT License](LICENSE.md).
[Matt Rubin]: https://mattrubin.me