{"id":27218469,"url":"https://github.com/mattrubin/onetimepassword","last_synced_at":"2025-04-10T05:38:17.819Z","repository":{"id":18515783,"uuid":"21712934","full_name":"mattrubin/OneTimePassword","owner":"mattrubin","description":"🔑 A small library for generating TOTP and HOTP one-time passwords on iOS.","archived":false,"fork":false,"pushed_at":"2024-08-19T14:15:31.000Z","size":1212,"stargazers_count":347,"open_issues_count":19,"forks_count":107,"subscribers_count":12,"default_branch":"develop","last_synced_at":"2025-03-29T10:47:21.098Z","etag":null,"topics":["2fa","hotp","ios","one-time-passwords","otp","swift","totp","two-factor-authentication"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mattrubin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.txt","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-07-10T22:49:19.000Z","updated_at":"2025-01-29T06:20:21.000Z","dependencies_parsed_at":"2024-01-07T21:02:53.956Z","dependency_job_id":"ae6f1ea7-de60-46e7-8bc1-9579a484133c","html_url":"https://github.com/mattrubin/OneTimePassword","commit_stats":{"total_commits":1354,"total_committers":8,"mean_commits":169.25,"dds":0.008862629246676468,"last_synced_commit":"66f284e22c170ffcc2c9dcf055a1efeb260c766d"},"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattrubin%2FOneTimePassword","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattrubin%2FOneTimePassword/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattrubin%2FOneTimePassword/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mattrubin%2FOneTimePassword/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mattrubin","download_url":"https://codeload.github.com/mattrubin/OneTimePassword/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248165299,"owners_count":21058319,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2fa","hotp","ios","one-time-passwords","otp","swift","totp","two-factor-authentication"],"created_at":"2025-04-10T05:38:17.108Z","updated_at":"2025-04-10T05:38:17.797Z","avatar_url":"https://github.com/mattrubin.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OneTimePassword\n### TOTP and HOTP one-time passwords for iOS\n\n[![Xcode CI status](https://github.com/mattrubin/OneTimePassword/actions/workflows/xcode.yml/badge.svg)](https://github.com/mattrubin/OneTimePassword/actions/workflows/xcode.yml)\n[![SPM CI status](https://github.com/mattrubin/OneTimePassword/actions/workflows/spm.yml/badge.svg)](https://github.com/mattrubin/OneTimePassword/actions/workflows/spm.yml)\n[![Carthage CI status](https://github.com/mattrubin/OneTimePassword/actions/workflows/carthage.yml/badge.svg)](https://github.com/mattrubin/OneTimePassword/actions/workflows/carthage.yml)\n[![Code Coverage](https://img.shields.io/codecov/c/github/mattrubin/OneTimePassword/develop.svg)](https://codecov.io/gh/mattrubin/OneTimePassword)\n[![Swift 5.x](https://img.shields.io/badge/swift-5.x-orange.svg)](#usage)\n![Platforms: iOS, macOS, watchOS](https://img.shields.io/badge/platforms-iOS%20%7C%20macOS%20%7C%20watchOS-blue.svg)\n[![MIT License](https://img.shields.io/badge/license-MIT-lightgray.svg)](LICENSE.md)\n\nThe 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.\n\n[Authenticator]: https://mattrubin.me/authenticator/\n[RFC 6238]: https://tools.ietf.org/html/rfc6238\n[RFC 4226]: https://tools.ietf.org/html/rfc4226\n[otpauth]: https://github.com/google/google-authenticator/wiki/Key-Uri-Format\n\n\n## Installation\n\n### [Carthage][]\n\nAdd the following line to your [Cartfile][]:\n\n````config\ngithub \"mattrubin/OneTimePassword\" ~\u003e 4.0\n````\n\nThen run `carthage update OneTimePassword` to install the latest version of the framework.\n\nBe sure to check the Carthage README file for the latest instructions on [adding frameworks to an application][carthage-instructions].\n\n[Carthage]: https://github.com/Carthage/Carthage\n[Cartfile]: https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile\n[carthage-instructions]: https://github.com/Carthage/Carthage/blob/master/README.md#adding-frameworks-to-an-application\n\n### [SPM][]\n\nAdd the following line to the `dependencies` section of your [package manifest][Package.swift]:\n\n```swift\n.package(url: \"https://github.com/mattrubin/OneTimePassword.git\", from: \"4.0.0\"),\n```\n\nThen add `\"OneTimePassword\"` to the dependencies array of any target which should be linked with this library.\n\n[SPM]: https://swift.org/package-manager/\n[Package.swift]: https://github.com/apple/swift-package-manager/tree/master/Documentation\n\n## Usage\n\n\u003e 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].\n\n[swift-5]: https://github.com/mattrubin/OneTimePassword/tree/swift-5\n[swift-4.2]: https://github.com/mattrubin/OneTimePassword/tree/swift-4.2\n[swift-4]: https://github.com/mattrubin/OneTimePassword/tree/swift-4\n[swift-3]: https://github.com/mattrubin/OneTimePassword/tree/swift-3\n[swift-2.3]: https://github.com/mattrubin/OneTimePassword/tree/swift-2.3\n[objc]: https://github.com/mattrubin/OneTimePassword/tree/objc\n[releases]: https://github.com/mattrubin/OneTimePassword/releases\n\n### Create a Token\n\nThe [`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.\n\n[Generator]: ./Sources/Generator.swift\n[Token]: ./Sources/Token.swift\n\nTo initialize a token with an `otpauth://` url:\n\n````swift\nif let token = Token(url: url) {\n    print(\"Password: \\(token.currentPassword)\")\n} else {\n    print(\"Invalid token URL\")\n}\n````\n\nTo create a generator and a token from user input:\n\n\u003e 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.\n\n````swift\nlet name = \"...\"\nlet issuer = \"...\"\nlet secretString = \"...\"\n\nguard let secretData = MF_Base32Codec.data(fromBase32String: secretString),\n    !secretData.isEmpty else {\n        print(\"Invalid secret\")\n        return nil\n}\n\nguard let generator = Generator(\n    factor: .timer(period: 30),\n    secret: secretData,\n    algorithm: .sha1,\n    digits: 6) else {\n        print(\"Invalid generator parameters\")\n        return nil\n}\n\nlet token = Token(name: name, issuer: issuer, generator: generator)\nreturn token\n````\n\n### Generate a One-Time Password\n\nTo generate the current password:\n\n````swift\nlet password = token.currentPassword\n````\n\nTo generate the password at a specific point in time:\n\n````swift\nlet time = Date(timeIntervalSince1970: ...)\ndo {\n    let passwordAtTime = try token.generator.password(at: time)\n    print(\"Password at time: \\(passwordAtTime)\")\n} catch {\n    print(\"Cannot generate password for invalid time \\(time)\")\n}\n````\n\n### Persistence\n\nToken persistence is managed by the [`Keychain`][Keychain] class, which represents the iOS system keychain.\n\n````swift\nlet keychain = Keychain.sharedInstance\n````\n\nThe [`PersistentToken`][PersistentToken] struct represents a `Token` that has been saved to the keychain, and associates a `token` with a keychain-provided data `identifier`.\n\n[Keychain]: ./Sources/Keychain.swift\n[PersistentToken]: ./Sources/PersistentToken.swift\n\nTo save a token to the keychain:\n\n````swift\ndo {\n    let persistentToken = try keychain.add(token)\n    print(\"Saved to keychain with identifier: \\(persistentToken.identifier)\")\n} catch {\n    print(\"Keychain error: \\(error)\")\n}\n````\n\nTo retrieve a token from the keychain:\n\n````swift\ndo {\n    if let persistentToken = try keychain.persistentToken(withIdentifier: identifier) {\n        print(\"Retrieved token: \\(persistentToken.token)\")\n    }\n    // Or...\n    let persistentTokens = try keychain.allPersistentTokens()\n    print(\"All tokens: \\(persistentTokens.map({ $0.token }))\")\n} catch {\n    print(\"Keychain error: \\(error)\")\n}\n````\n\nTo update a saved token in the keychain:\n\n````swift\ndo {\n    let updatedPersistentToken = try keychain.update(persistentToken, with: token)\n    print(\"Updated token: \\(updatedPersistentToken)\")\n} catch {\n    print(\"Keychain error: \\(error)\")\n}\n````\n\nTo delete a token from the keychain:\n\n````swift\ndo {\n    try keychain.delete(persistentToken)\n    print(\"Deleted token.\")\n} catch {\n    print(\"Keychain error: \\(error)\")\n}\n````\n\n\n## License\n\nOneTimePassword was created by [Matt Rubin][] and the [OneTimePassword authors](AUTHORS.txt) and is released under the [MIT License](LICENSE.md).\n\n[Matt Rubin]: https://mattrubin.me\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattrubin%2Fonetimepassword","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmattrubin%2Fonetimepassword","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmattrubin%2Fonetimepassword/lists"}