Implement bank transfer app flows

This commit is contained in:
2026-06-08 00:03:57 +05:00
parent ef877217ad
commit 9b281d48a7
127 changed files with 8008 additions and 90 deletions
+38
View File
@@ -0,0 +1,38 @@
import CommonCrypto
import Foundation
enum PinHash {
private static let iterations: UInt32 = 100_000
private static let keyLength = 32 // 256 bits
static func generateSalt() -> Data {
var salt = Data(count: 16)
_ = salt.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, 16, $0.baseAddress!) }
return salt
}
static func hash(_ input: String, salt: Data) -> String {
var derivedKey = Data(count: keyLength)
let inputData = Data(input.utf8)
_ = derivedKey.withUnsafeMutableBytes { derivedPtr in
inputData.withUnsafeBytes { inputPtr in
salt.withUnsafeBytes { saltPtr in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
inputPtr.baseAddress, inputData.count,
saltPtr.baseAddress, salt.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
iterations,
derivedPtr.baseAddress, keyLength
)
}
}
}
return derivedKey.base64EncodedString()
}
static func verify(_ input: String, against storedHash: String, salt: Data) -> Bool {
hash(input, salt: salt) == storedHash
}
}
+51
View File
@@ -0,0 +1,51 @@
import CryptoKit
import Foundation
enum Totp {
// timeStep offsets the counter by N periods use -1/+1 to handle clock skew at window boundaries.
static func generate(_ base32Secret: String, digits: Int = 6, period: Int = 30, timeStep: Int = 0) -> String {
let counter = Int64(Date().timeIntervalSince1970) / Int64(period) + Int64(timeStep)
guard let keyBytes = base32Decode(base32Secret.uppercased()) else { return String(repeating: "0", count: digits) }
let otp = hotp(key: keyBytes, counter: counter, digits: digits)
return String(format: "%0\(digits)d", otp)
}
private static func hotp(key: [UInt8], counter: Int64, digits: Int) -> Int {
var counterBigEndian = counter.bigEndian
let counterData = withUnsafeBytes(of: &counterBigEndian) { Data($0) }
let hmac = HMAC<Insecure.SHA1>.authenticationCode(
for: counterData,
using: SymmetricKey(data: Data(key))
)
let hash = Array(hmac)
let offset = Int(hash[hash.count - 1] & 0x0F)
let truncated = (Int(hash[offset]) & 0x7F) << 24
| Int(hash[offset + 1]) << 16
| Int(hash[offset + 2]) << 8
| Int(hash[offset + 3])
let modulus = Int(pow(10.0, Double(digits)))
return truncated % modulus
}
private static func base32Decode(_ input: String) -> [UInt8]? {
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
var bits = 0
var bitCount = 0
var result: [UInt8] = []
for char in input where char != "=" {
guard let idx = alphabet.firstIndex(of: char) else { return nil }
let value = alphabet.distance(from: alphabet.startIndex, to: idx)
bits = (bits << 5) | value
bitCount += 5
if bitCount >= 8 {
bitCount -= 8
result.append(UInt8((bits >> bitCount) & 0xFF))
}
}
return result
}
}