import Foundation #if canImport(CryptoKit) import CryptoKit #else import Crypto #endif extension Message { static var length: Int { SHA256.byteCount + Content.length } init(decodeFrom data: T) where T.Element == UInt8 { let count = SHA256.byteCount self.mac = Data(data.prefix(count)) self.content = .init(decodeFrom: Array(data.dropFirst(count))) } func isValid(using key: SymmetricKey) -> Bool { HMAC.isValidAuthenticationCode(mac, authenticating: content.encoded, using: key) } } extension Message.Content { func authenticate(using key: SymmetricKey) -> Message { let mac = HMAC.authenticationCode(for: encoded, using: key) return .init(mac: Data(mac.map { $0 }), content: self) } func authenticateAndSerialize(using key: SymmetricKey) -> Data { let encoded = self.encoded let mac = HMAC.authenticationCode(for: encoded, using: key) return Data(mac.map { $0 }) + encoded } }