Last active
December 1, 2020 12:52
-
-
Save mntone/ea5fb9909ce1a078959464629ebc7a9c to your computer and use it in GitHub Desktop.
何かの残骸。正しく動作しません。ただ,クラス実装は何かに流用できる可能性があります。🌟under MIT license
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import CommonCrypto | |
import CryptoKit | |
import Foundation | |
protocol PinCodeFactory { | |
mutating func update(by timeStep: Int32) | |
mutating func update(by timeStep: Int32, at baseTime: Int32) | |
mutating func update(using counter: Int64) | |
mutating func getPincode(to digits: Int) -> Int32 | |
} | |
extension PinCodeFactory { | |
mutating func update(by timeStep: Int32) { | |
update(by: timeStep, at: 0) | |
} | |
mutating func update(by timeStep: Int32, at baseTime: Int32) { | |
let x = (Date().timeIntervalSince1970 - Double(baseTime)) / Double(timeStep) | |
update(using: Int64(x)) | |
} | |
} | |
func makePinCodeFactory(_ algorithm: OneTimePasswordAlgorithm, using key: String) -> PinCodeFactory { | |
if #available(iOS 13.0, macOS 10.15, watchOS 6.0, *) { | |
switch algorithm { | |
case .MD5: | |
return MD5PinCodeFactory(key) | |
case .SHA1: | |
return SHA1PinCodeFactory(key) | |
case .SHA256: | |
return SHA256PinCodeFactory(key) | |
case .SHA384: | |
return SHA384PinCodeFactory(key) | |
case .SHA512: | |
return SHA512PinCodeFactory(key) | |
} | |
} else { | |
switch algorithm { | |
case .MD5: | |
return MD5CompatibilityPinCodeFactory(key) | |
case .SHA1: | |
return SHA1CompatibilityPinCodeFactory(key) | |
case .SHA256: | |
return SHA256CompatibilityPinCodeFactory(key) | |
case .SHA384: | |
return SHA384CompatibilityPinCodeFactory(key) | |
case .SHA512: | |
return SHA512CompatibilityPinCodeFactory(key) | |
} | |
} | |
} | |
private let DIGITS_POWER: [Int32] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000] | |
// --- | |
// iOS: 13.0- | |
// macOS: 10.15.x, 11.0- | |
// watchOS: 6.0- | |
// --- | |
@available(iOS 13.0, macOS 10.15, watchOS 6.0, *) | |
protocol PinCodeFactoryImplementation { | |
associatedtype H: HashFunction | |
var factory: HMAC<H> { get set } | |
init(_ key: SymmetricKey) | |
} | |
@available(iOS 13.0, macOS 10.15, watchOS 6.0, *) | |
extension PinCodeFactoryImplementation { | |
init(_ data: Data) { | |
let symetricKey = SymmetricKey(data: data) | |
self.init(symetricKey) | |
} | |
init(_ string: String) { | |
let data = string.data(using: .utf8)! | |
self.init(data) | |
} | |
mutating func update(using counter: Int64) { | |
factory.update(data: counter.bigEndian.toData()) | |
} | |
func getPincode(to digits: Int) -> Int32 { | |
let hash = factory.finalize() | |
let binary = hash.withUnsafeBytes { hash -> Int32 in | |
let offset = Int(hash[hash.count - 1] & 0x0F) | |
var buffer = [UInt8](repeating: 0, count: 4) | |
return buffer.withUnsafeMutableBytes { p in | |
hash.copyBytes(to: p, from: offset..<offset + 4) | |
return Int32(bigEndian: p.load(as: Int32.self)) & 0x7FFFFFFF | |
} | |
} | |
if digits >= 10 { | |
return binary | |
} else { | |
return binary % DIGITS_POWER[digits] | |
} | |
} | |
} | |
@available(iOS 13.0, macOS 10.15, watchOS 6.0, *) | |
final class MD5PinCodeFactory: PinCodeFactory, PinCodeFactoryImplementation { | |
var factory: HMAC<Insecure.MD5> | |
init(_ key: SymmetricKey) { | |
self.factory = HMAC<Insecure.MD5>(key: key) | |
} | |
} | |
@available(iOS 13.0, macOS 10.15, watchOS 6.0, *) | |
final class SHA1PinCodeFactory: PinCodeFactory, PinCodeFactoryImplementation { | |
var factory: HMAC<Insecure.SHA1> | |
init(_ key: SymmetricKey) { | |
self.factory = HMAC<Insecure.SHA1>(key: key) | |
} | |
} | |
@available(iOS 13.0, macOS 10.15, watchOS 6.0, *) | |
final class SHA256PinCodeFactory: PinCodeFactory, PinCodeFactoryImplementation { | |
var factory: HMAC<SHA256> | |
init(_ key: SymmetricKey) { | |
self.factory = HMAC<SHA256>(key: key) | |
} | |
} | |
@available(iOS 13.0, macOS 10.15, watchOS 6.0, *) | |
final class SHA384PinCodeFactory: PinCodeFactory, PinCodeFactoryImplementation { | |
var factory: HMAC<SHA384> | |
init(_ key: SymmetricKey) { | |
self.factory = HMAC<SHA384>(key: key) | |
} | |
} | |
@available(iOS 13.0, macOS 10.15, watchOS 6.0, *) | |
final class SHA512PinCodeFactory: PinCodeFactory, PinCodeFactoryImplementation { | |
var factory: HMAC<SHA512> | |
init(_ key: SymmetricKey) { | |
self.factory = HMAC<SHA512>(key: key) | |
} | |
} | |
// --- | |
// iOS: -12.x | |
// macOS: -10.14.x | |
// watchOS: -5.x | |
// --- | |
@available(iOS, introduced: 2.0, deprecated: 13.0) | |
@available(macOS, introduced: 10.4, deprecated: 10.15) | |
@available(watchOS, deprecated: 6.0) | |
protocol PinCodeFactoryCompatibilityImplementation { | |
var context: CCHmacContext { get set } | |
var algorithm: CCHmacAlgorithm { get } | |
var length: Int { get } | |
init(_ data: Data) | |
} | |
@available(iOS, introduced: 2.0, deprecated: 13.0) | |
@available(macOS, introduced: 10.4, deprecated: 10.15) | |
@available(watchOS, deprecated: 6.0) | |
extension PinCodeFactoryCompatibilityImplementation { | |
init(_ string: String) { | |
let data = string.data(using: .utf8)! | |
self.init(data) | |
} | |
mutating func update(using counter: Int64) { | |
withUnsafeBytes(of: counter) { | |
CCHmacUpdate(&context, $0.baseAddress, MemoryLayout<Int64>.size) | |
} | |
} | |
mutating func getPincode(to digits: Int) -> Int32 { | |
var hash = Array<UInt8>(repeating: 0, count: length) | |
CCHmacFinal(&context, &hash) | |
let offset = Int(hash[length - 1] & 0x0F) | |
var buffer = [UInt8](repeating: 0, count: 4) | |
let binary = buffer.withUnsafeMutableBytes { p -> Int32 in | |
hash.copyBytes(to: p, from: offset..<offset + 4) | |
return Int32(bigEndian: p.load(as: Int32.self)) & 0x7FFFFFFF | |
} | |
if digits >= 10 { | |
return binary | |
} else { | |
return binary % DIGITS_POWER[digits] | |
} | |
} | |
} | |
@available(iOS, introduced: 2.0, deprecated: 13.0) | |
@available(macOS, introduced: 10.4, deprecated: 10.15) | |
@available(watchOS, deprecated: 6.0) | |
final class MD5CompatibilityPinCodeFactory: PinCodeFactory, PinCodeFactoryCompatibilityImplementation { | |
var context = CCHmacContext() | |
var algorithm: CCHmacAlgorithm { CCHmacAlgorithm(kCCHmacAlgMD5) } | |
var length: Int { Int(CC_MD5_DIGEST_LENGTH) } | |
init(_ data: Data) { | |
let ptr = data.withUnsafeBytes { $0.baseAddress! } | |
CCHmacInit(&context, algorithm, ptr, data.count) | |
} | |
} | |
@available(iOS, introduced: 2.0, deprecated: 13.0) | |
@available(macOS, introduced: 10.4, deprecated: 10.15) | |
@available(watchOS, deprecated: 6.0) | |
final class SHA1CompatibilityPinCodeFactory: PinCodeFactory, PinCodeFactoryCompatibilityImplementation { | |
var context = CCHmacContext() | |
var algorithm: CCHmacAlgorithm { CCHmacAlgorithm(kCCHmacAlgSHA1) } | |
var length: Int { Int(CC_SHA1_DIGEST_LENGTH) } | |
init(_ data: Data) { | |
let ptr = data.withUnsafeBytes { $0.baseAddress! } | |
CCHmacInit(&context, algorithm, ptr, data.count) | |
} | |
} | |
@available(iOS, introduced: 2.0, deprecated: 13.0) | |
@available(macOS, introduced: 10.4, deprecated: 10.15) | |
@available(watchOS, deprecated: 6.0) | |
final class SHA256CompatibilityPinCodeFactory: PinCodeFactory, PinCodeFactoryCompatibilityImplementation { | |
var context = CCHmacContext() | |
var algorithm: CCHmacAlgorithm { CCHmacAlgorithm(kCCHmacAlgSHA256) } | |
var length: Int { Int(CC_SHA256_DIGEST_LENGTH) } | |
init(_ data: Data) { | |
let ptr = data.withUnsafeBytes { $0.baseAddress! } | |
CCHmacInit(&context, algorithm, ptr, data.count) | |
} | |
} | |
@available(iOS, introduced: 2.0, deprecated: 13.0) | |
@available(macOS, introduced: 10.4, deprecated: 10.15) | |
@available(watchOS, deprecated: 6.0) | |
final class SHA384CompatibilityPinCodeFactory: PinCodeFactory, PinCodeFactoryCompatibilityImplementation { | |
var context = CCHmacContext() | |
var algorithm: CCHmacAlgorithm { CCHmacAlgorithm(kCCHmacAlgSHA384) } | |
var length: Int { Int(CC_SHA384_DIGEST_LENGTH) } | |
init(_ data: Data) { | |
let ptr = data.withUnsafeBytes { $0.baseAddress! } | |
CCHmacInit(&context, algorithm, ptr, data.count) | |
} | |
} | |
@available(iOS, introduced: 2.0, deprecated: 13.0) | |
@available(macOS, introduced: 10.4, deprecated: 10.15) | |
@available(watchOS, deprecated: 6.0) | |
final class SHA512CompatibilityPinCodeFactory: PinCodeFactory, PinCodeFactoryCompatibilityImplementation { | |
var context = CCHmacContext() | |
var algorithm: CCHmacAlgorithm { CCHmacAlgorithm(kCCHmacAlgSHA512) } | |
var length: Int { Int(CC_SHA512_DIGEST_LENGTH) } | |
init(_ data: Data) { | |
let ptr = data.withUnsafeBytes { $0.baseAddress! } | |
CCHmacInit(&context, algorithm, ptr, data.count) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment