OTP/OTPKit/OTPGenerator.swift

46 lines
1.4 KiB
Swift

//
// OTPGenerator.swift
// OTPKit
//
// Created by Shadowfacts on 8/21/21.
//
import Foundation
import CryptoKit
public struct OTPGenerator {
private init() {}
public static func generate(key: OTPKey, counter: Int64) -> String {
let data = withUnsafeBytes(of: counter.bigEndian) {
Data($0)
}
let mac = HMAC<Insecure.SHA1>.authenticationCode(for: data, using: SymmetricKey(data: key.secret))
let uint32Code = mac.withUnsafeBytes { (ptr) -> UInt32 in
let offset = Int(ptr.last! & 0x0F)
let offsetPtr = ptr.baseAddress!.advanced(by: offset)
return offsetPtr.assumingMemoryBound(to: UInt32.self).pointee.bigEndian & 0x7FFFFFFF
}
let truncated = uint32Code % UInt32(pow(10, Double(key.digits)))
var s = truncated.description
if s.count < key.digits {
s = String(repeating: "0", count: key.digits - s.count) + s
}
return s
}
public static func generate(key: TOTPKey) -> TOTPCode {
let now = Date()
let counter = Int64(now.timeIntervalSince1970 / Double(key.period))
let start = Date(timeIntervalSince1970: Double(counter * Int64(key.period)))
let code = generate(key: key, counter: counter)
return TOTPCode(code: code, validFrom: start, validInterval: key.period)
}
}