diff --git a/Guardian/Generators/OneTimePasswordGenerator.swift b/Guardian/Generators/OneTimePasswordGenerator.swift index 7d844e6..f14dbe6 100644 --- a/Guardian/Generators/OneTimePasswordGenerator.swift +++ b/Guardian/Generators/OneTimePasswordGenerator.swift @@ -82,17 +82,13 @@ struct OneTimePasswordGenerator: TOTP, HOTP { var c = UInt64(counter).bigEndian let buffer = Data(bytes: &c, count: MemoryLayout.size); let digestData = hmac.sign(buffer) - let hash = digestData.withUnsafeBytes { (bytes: UnsafePointer) -> UInt32 in - let last = bytes.advanced(by: hmac.digestLength - 1) - let offset = last.pointee & 0x0f - let start = bytes.advanced(by: Int(offset)) - let value = start.withMemoryRebound(to: UInt32.self, capacity: 1) { $0 } - var hash = UInt32(bigEndian: value.pointee) - hash &= 0x7fffffff - hash = hash % UInt32(pow(10, Float(self.parameters.digits))) - return hash - } - + let length = MemoryLayout.size + // digestData.count - 1 will always be >0, because digestData depends on algorythm and can be only 20, 32, or 64. + let offset = Int(digestData[digestData.count - 1] & 0x0f) + // offset is always <=15, length is always 4, so prefix will always be within digestData count. + var hash = digestData.dropFirst(offset).prefix(length).reduce(0, { $0 << 8 | UInt32($1) }) + hash &= 0x7fffffff + hash = hash % UInt32(pow(10, Float(self.parameters.digits))) return Int(hash) } diff --git a/GuardianApp/State.swift b/GuardianApp/State.swift index 41b1069..b2e0efc 100644 --- a/GuardianApp/State.swift +++ b/GuardianApp/State.swift @@ -28,9 +28,9 @@ struct GuardianState: Codable { let identifier: String let localIdentifier: String - let token: String let keyTag: String let otp: OTPParameters? + let userId: String func save() throws { let encoder = JSONEncoder() diff --git a/GuardianApp/ViewController.swift b/GuardianApp/ViewController.swift index 7f4d6bd..424e973 100644 --- a/GuardianApp/ViewController.swift +++ b/GuardianApp/ViewController.swift @@ -93,7 +93,7 @@ class ViewController: UIViewController, QRCodeReaderViewControllerDelegate { case .failure(let cause): self.showError("Enroll failed", cause) case .success(let enrollment): - AppDelegate.state = GuardianState(identifier: enrollment.id, localIdentifier: enrollment.localIdentifier, token: enrollment.deviceToken, keyTag: signingKey.tag, otp: enrollment.totp) + AppDelegate.state = GuardianState(identifier: enrollment.id, localIdentifier: enrollment.localIdentifier, keyTag: signingKey.tag, otp: enrollment.totp, userId: enrollment.userId) } self.updateView() } @@ -119,7 +119,7 @@ class ViewController: UIViewController, QRCodeReaderViewControllerDelegate { if let enrollment = AppDelegate.state { let request = Guardian .api(forDomain: AppDelegate.guardianDomain) - .device(forEnrollmentId: enrollment.identifier, token: enrollment.token) + .device(forEnrollmentId: enrollment.identifier, userId: enrollment.userId, signingKey: enrollment.signingKey) .delete() debugPrint(request) request.start { [unowned self] result in