{"id":15684253,"url":"https://github.com/tgymnich/otpkit","last_synced_at":"2025-05-07T15:50:20.661Z","repository":{"id":124646464,"uuid":"198316506","full_name":"tgymnich/OTPKit","owner":"tgymnich","description":"🔐 Swift package to generate HOTP and TOTP tokens and save them to the keychain","archived":false,"fork":false,"pushed_at":"2024-12-01T03:38:09.000Z","size":110,"stargazers_count":11,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-31T11:35:35.978Z","etag":null,"topics":["2fa","hotp","keychain","otp","package","swift","totp","totp-tokens"],"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/tgymnich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-22T23:32:03.000Z","updated_at":"2025-01-19T12:34:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"37cd5954-c868-4b7c-8bda-591bd7474bb1","html_url":"https://github.com/tgymnich/OTPKit","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tgymnich%2FOTPKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tgymnich%2FOTPKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tgymnich%2FOTPKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tgymnich%2FOTPKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tgymnich","download_url":"https://codeload.github.com/tgymnich/OTPKit/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252910664,"owners_count":21823882,"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","keychain","otp","package","swift","totp","totp-tokens"],"created_at":"2024-10-03T17:13:33.151Z","updated_at":"2025-05-07T15:50:20.609Z","avatar_url":"https://github.com/tgymnich.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OTPKit\n![Swift](https://github.com/TG908/OTPKit/workflows/Swift/badge.svg)\n[![codecov](https://codecov.io/gh/tgymnich/OTPKit/branch/master/graph/badge.svg?token=TALY1DNJWN)](https://codecov.io/gh/tgymnich/OTPKit)\n\nA little swift package to generate HOTP and TOTP tokens and save them to the keychain. Featuring a combine publisher that publishes new tokens.\n\n# SwiftPM\n```swift\n// swift-tools-version:5.0\nimport PackageDescription\n\nlet package = Package(\n  name: \"MyTool\",\n  dependencies: [\n    .package(url: \"https://github.com/tgymnich/OTPKit.git\", .from: \"1.0.0\"),\n  ],\n  targets: [\n    .target(name: \"MyTool\", dependencies: [\"OTPKit\"]),\n  ]\n)\n```\n\n# Features\n- Create TOTP and HOTP tokens 🔑\n- `NotificationCenter` notifications for current tokens 📻\n- Combine Publisher for newly current tokens 📡\n- Save and load accounts from Keychain 🔒\n\n# Usage\n\n## Accounts\n\n### Creating an Account from an URL\n```swift\nlet url = URL(string: \"otpauth://totp/foo?secret=wew3k6ztd7kuh5ucg4pejqi4swwrrneh72ad2sdovikfatzbc5huto2j\u0026algorithm=SHA256\u0026digits=6\u0026period=30\")!\nlet account = Account\u003cTOTP\u003e(from: url)\n\nprint(account?.otpGenerator.code()) // Prints the TOTP code for the current time.\n```\n\n### Saving and loading of accounts from the Keychain\n```swift\nlet keychain = Keychain(service: \"ch.gymni.test.otpauth\")\n\nlet url = URL(string: \"otpauth://totp/foo?secret=wew3k6ztd7kuh5ucg4pejqi4swwrrneh72ad2sdovikfatzbc5huto2j\u0026algorithm=SHA256\u0026digits=6\u0026period=30\")!\nlet totp = TOTP(algorithm: .sha256, secret: \"wew3k6ztd7kuh5ucg4pejqi4swwrrneh72ad2sdovikfatzbc5huto2j\".base32DecodedData! , digits: 6, period: 30)\nlet account = Account(label: \"foo\", otp: totp)\ntry account.save(to: keychain)\n\nlet accounts = try? Account.loadAll(from: keychain)\n```\n\n### Deleting all accounts from keychain\n```swift\nlet keychain = Keychain(service: \"ch.gymni.test.otpauth\")\ntry! keychain.removeAll()\n```\n\n\n## Generating TOTP codes\n\n### For a specific Date\n```swift\nlet date = Date(timeIntervalSince1970: 1234)\nlet totp = TOTP(algorithm: .sha256, secret: \"01234567890\".data(using: .ascii)!, digits: 6, period: 30)\nlet code = totp.code(for: date)\n```\n\n### For the current period\n```swift\nlet totp = TOTP(algorithm: .sha256, secret: \"01234567890\".data(using: .ascii)!, digits: 6, period: 30)\nlet code = totp.code()\n```\n\n### For a custom period\n```swift\nlet period: UInt64 = 1234\nlet totp = TOTP(algorithm: .sha256, secret: \"01234567890\".data(using: .ascii)!, digits: 6, period: 30)\nlet code = totp.code(for: period)\n```\n\n### Using NotificationCenter\n```swift\nlet totp = TOTP(algorithm: .sha256, secret: \"01234567890\".data(using: .ascii)!, digits: 6, period: 30)\nNotificationCenter.default.addObserver(forName: .didGenerateNewOTPCode, object: totp, queue: .main) { notification in\n   let code = notification.userInfo?[TOTP.UserInfoKeys.code] as? String\n}\n```\n\n### Using a Combine Publisher\n```swift\nlet totp = TOTP(algorithm: .sha256, secret: \"01234567890\".data(using: .ascii)!, digits: 6, period: TOTPPublisherTests.period)\nlet pub = TOTP.TOTPPublisher(totp: totp)\n    .sink { code in\n        print(code)\n   }\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftgymnich%2Fotpkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftgymnich%2Fotpkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftgymnich%2Fotpkit/lists"}