import Foundation /// SHA-1 (RFC 3174) — pure Swift streaming. Legacy post-house compatibility. public struct SHA1 { private var h0: UInt32 = 0x67452301 private var h1: UInt32 = 0xEFCDAB89 private var h2: UInt32 = 0x98BADCFE private var h3: UInt32 = 0x10325476 private var h4: UInt32 = 0xC3D2E1F0 private var buffer = [UInt8]() private var totalLength: UInt64 = 0 public init() {} public mutating func update(_ data: Data) { totalLength += UInt64(data.count) buffer.append(contentsOf: data) var offset = 0 while buffer.count - offset >= 64 { processBlock(Array(buffer[offset.. 0 { buffer.removeFirst(offset) } } @inline(__always) private static func rotl(_ x: UInt32, _ n: UInt32) -> UInt32 { (x << n) | (x >> (32 - n)) } private mutating func processBlock(_ block: [UInt8]) { var w = [UInt32](repeating: 0, count: 80) for i in 0..<16 { w[i] = UInt32(block[i * 4]) << 24 | UInt32(block[i * 4 + 1]) << 16 | UInt32(block[i * 4 + 2]) << 8 | UInt32(block[i * 4 + 3]) } for i in 16..<80 { w[i] = Self.rotl(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1) } var a = h0, b = h1, c = h2, d = h3, e = h4 for i in 0..<80 { let (f, k): (UInt32, UInt32) switch i { case 0..<20: (f, k) = ((b & c) | (~b & d), 0x5A827999) case 20..<40: (f, k) = (b ^ c ^ d, 0x6ED9EBA1) case 40..<60: (f, k) = ((b & c) | (b & d) | (c & d), 0x8F1BBCDC) default: (f, k) = (b ^ c ^ d, 0xCA62C1D6) } let temp = Self.rotl(a, 5) &+ f &+ e &+ k &+ w[i] e = d d = c c = Self.rotl(b, 30) b = a a = temp } h0 = h0 &+ a h1 = h1 &+ b h2 = h2 &+ c h3 = h3 &+ d h4 = h4 &+ e } public mutating func finalize() -> Data { let bitLength = totalLength * 8 var padding: [UInt8] = [0x80] let remainder = (buffer.count + 1) % 64 let zeros = remainder <= 56 ? 56 - remainder : 120 - remainder padding.append(contentsOf: [UInt8](repeating: 0, count: zeros)) // Length big-endian. for shift in stride(from: 56, through: 0, by: -8) { padding.append(UInt8((bitLength >> UInt64(shift)) & 0xFF)) } buffer.append(contentsOf: padding) var offset = 0 while buffer.count - offset >= 64 { processBlock(Array(buffer[offset..> 24) & 0xFF)) out.append(UInt8((v >> 16) & 0xFF)) out.append(UInt8((v >> 8) & 0xFF)) out.append(UInt8(v & 0xFF)) } return out } public static func hexString(_ data: Data) -> String { var sha = SHA1() sha.update(data) return sha.finalize().map { String(format: "%02x", $0) }.joined() } }