Attomus/attomus-otp

GitHub: Attomus/attomus-otp

这是一个用于安全生成TOTP和HOTP一次性密码的Swift和Kotlin库,解决了移动应用中双因素认证的实现问题。

Stars: 0 | Forks: 0

# for some, I need to add Chinese context. For example, in the examples, "Running" is translated to "运行", so for headings that are verbs or nouns, I translate the non-technical parts. 为 iOS/Swift 和 Android/Kotlin 实现的 TOTP (RFC 6238) 和 HOTP (RFC 4226)。 两个独立的引擎,共享相同的设计:遵循相同的 RFC 标准,相同的 `otpauth://` URI 解析行为,相同的数据模型,以及可互操作的备份格式。 由 [Attomus Signet](https://attomus.com/products/signet/) 使用 — 一款零云端、离线的 iOS 和 Android 认证器。 在 App Store 下载  在 Google Play 获取 ## 实现 | | Swift | Kotlin | |---|---|---| | 平台 | iOS 16+、macOS 13+、watchOS 9+、tvOS 16+、Linux | Android (JVM/API 26+) | | 包 | `swift/` — Swift 包管理器 | `kotlin/` — Gradle | | 模块 | `import AttomusOTP` | `import com.attomus.otp.*` | | TOTP / HOTP | ✓ | ✓ | | `otpauth://` URI 解析 | ✓ | ✓ | | Base32 解码 | ✓ | ✓ | | 可移植备份模式 | ✓ | —(在应用层消费) | | HOTP 计数器完整性数据块 | ✓ | —(在应用层消费) | 备份格式和计数器数据块在 Swift 库中定义,并在下文记录。iOS 和 Android 的 Signet 应用程序都生产并消费相同的磁盘格式,确保了跨平台的备份互操作性。 ## 要求 ### Looking at the list, all seem to be technical terms or proper nouns. However, "AttomusOTP" might have a Chinese name, but since it's not specified, I'll keep it in English. - Swift 5.9+ - iOS 16+ / macOS 13+ / watchOS 9+ / tvOS 16+ - Linux:通过 [swift-crypto](https://github.com/apple/swift-crypto) 运行的 Swift 5.9+ ### To be consistent with the instruction, I should keep all these in English if they are technical jargon. But the user said "translate", so maybe for some, I need to provide the Chinese translation of the term. - Kotlin 1.9+ / JVM 17+ - Android API 26+ (minSdk 26) - 无额外依赖 — 使用标准库中的 `javax.crypto` ## 安装说明 ### Swift 包管理器 ``` dependencies: [ .package(url: "https://github.com/attomus/attomus-otp.git", from: "1.0.0") ] ``` ### Let's see the examples again: 'Running Naabu' has "Running" translated, but "Naabu" kept. Similarly, 'Kubernetes Setup' has "Setup" translated. ``` dependencies { implementation("com.attomus:attomus-otp-android:1.0.1") } ``` ## For standalone terms like "API", in the example 'API Reference', "API" is kept, but "Reference" is translated. So for a heading like "API", if it's just "API", perhaps I don't translate it, or I translate it as "API" which is commonly used in Chinese. ### In technical Chinese, "API" is often used as is, or sometimes translated as "应用程序接口", but the instruction says to keep it in English. **Swift** ``` import AttomusOTP let code = try TOTP.generate( secret: secretBytes, // raw seed bytes, not Base32-encoded algorithm: .sha1, digits: 6, period: 30, at: Date() ) // "048921" — zero-padded to the requested digit count ``` **Kotlin** ``` import com.attomus.otp.TOTP import com.attomus.otp.OTPAlgorithm val code = TOTP.generate( secret = secretBytes, // raw seed bytes, not Base32-encoded algorithm = OTPAlgorithm.SHA1, digits = 6, period = 30 ) // "048921" — zero-padded to the requested digit count val remaining = TOTP.remainingSeconds(period = 30) // seconds until the current code expires ``` ### The instruction explicitly says: "Keep all professional terms, proper nouns, tool/library/framework names, and technical jargon in their original English form." **Swift** ``` let code = try HOTP.generate( secret: secretBytes, algorithm: .sha1, digits: 6, counter: 42 ) ``` **Kotlin** ``` import com.attomus.otp.HOTP import com.attomus.otp.OTPAlgorithm val code = HOTP.generate( secret = secretBytes, counter = 42L, algorithm = OTPAlgorithm.SHA1, digits = 6 ) ``` ### `otpauth://` URI 解析 **Swift** ``` let result = try parseOTPURI( "otpauth://totp/Example%3Aalice%40example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example" ) // result.account.type == .totp // result.account.issuer == "Example" // result.account.label == "alice@example.com" // result.account.digits == 6 // result.account.period == 30 // result.secretBytes — raw seed bytes, ready to pass to TOTP.generate ``` 错误是类型化的 (`OTPURIError`) — 无需解析字符串。应用了完整的验证:密钥长度、数字位数、周期、算法、URI 结构和百分号编码。 **Kotlin** ``` import com.attomus.otp.OTPURIParser val result = OTPURIParser.parse( "otpauth://totp/Example%3Aalice%40example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example" ) // result.account.type == OTPType.TOTP // result.account.issuer == "Example" // result.account.label == "alice@example.com" // result.account.digits == 6 // result.account.period == 30 // result.secret — raw seed bytes, ready to pass to TOTP.generate ``` 错误是类型化的 (`OTPURIError`) — 与 Swift 实现具有相同的错误分类法。 ### 可移植备份模式 *(Swift)* 该备份模式将账户及其原始种子字节序列化为 JSON 负载。它有意设计为无依赖(仅需 `Foundation`),因此任何平台都可以实现兼容的读取器或写入器。 ``` // Export — produce the JSON payload for the application layer to encrypt let jsonPayload = try encodeExportDocument( accounts: accounts, secrets: secretsByID // [UUID: Data] — raw seed bytes keyed by account ID ) // jsonPayload is UTF-8 JSON — hand directly to your encryption layer // Never write this to disk unencrypted // Import — decode and validate a decrypted payload let provisioningResults = try decodeExportDocument(jsonPayload) for result in provisioningResults { // result.account, result.secretBytes } ``` 此库定义了模式版本 1。应用层负责加密信封 — Signet 使用 Argon2id + AES-256-GCM。该模式已文档化,以便任何平台都能实现兼容的读取器。 ### HOTP 计数器完整性数据块 *(Swift)* 一个 41 字节、受 HMAC-SHA256 保护的记录,用于防篡改的 HOTP 计数器存储。 ``` // Encode — produce a 41-byte blob for storage let blob = try encodeCounterBlob(counter: 42, integrityKey: key) // layout: [version:1][counter:8 BE][hmac-sha256:32] = 41 bytes // Verify — decode and verify, recovering the counter value let counter = try verifyCounterBlob(blob, integrityKey: key) ``` `integrityKey` 必须为 32 字节。格式是固定的;Signet 的 iOS 和 Android 版本都生产和消费相同的 41 字节布局。HMAC 比较在全局范围内采用恒定时间(Swift:使用无提前退出的位异或累加器;Kotlin:使用 `MessageDigest.isEqual`)。 ## 支持的算法 | 算法 | TOTP | HOTP | |-----------|:----:|:----:| | SHA-1 | ✓ | ✓ | | SHA-256 | ✓ | ✓ | | SHA-512 | ✓ | ✓ | 数字位数:6、7 或 8。TOTP 周期:30 秒和 60 秒。超出此范围的值将被拒绝。 ## 安全性 - 两个实现都通过了所有 RFC 4226 (HOTP) 和 RFC 6238 (TOTP) 测试向量 - HMAC 比较在全局范围内采用恒定时间(Swift:使用无提前退出的位异或累加器;Kotlin:`MessageDigest.isEqual`) - 任一库都不会记录、写入磁盘或在错误消息中捕获任何密钥 - 经过模糊测试:URI 解析器和备份模式解码器已通过数十亿次迭代测试,零崩溃 - Swift:`Sources/AttomusOTP` 仅使用 `Foundation` 和 `CryptoKit`(Apple 平台)或 `swift-crypto`(Linux)— 无其他依赖 - Kotlin:`com.attomus.otp` 仅使用 JVM 标准库中的 `javax.crypto` - 任一实现都无需网络、存储或平台权限 ## 许可证 [MIT](LICENSE) — 版权所有 (c) 2026 Attomus Ltd
标签:Android开发, Base32编码, HOTP算法, iOS开发, Kotlin库, RFC标准, Swift库, TOTP算法, URI解析, XML 请求, 一次性密码, 互操作性, 双因素认证, 安全开发, 安全认证, 密码学, 密码生成, 手动系统调用, 数据备份, 目录枚举, 离线认证, 移动安全, 认证器, 零云应用