MPLewis
(Mike Lewis)
1
Unless I'm missing something obvious, it looks like the open-source implementation of HashedAuthenticationCode has no public initializers, meaning that trying to generate an authentication code and storing it somewhere for later verification requires creating a dummy value and then overwriting the underlying memory.
For instance, this is the only way I could figure to add Decodable conformance:
extension HashedAuthenticationCode: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
// This at least needs checks for data length before copying below
let data = try container.decode(Data.self)
let newSelf = HMAC<H>.authenticationCode(for: [], using: .init(data: []))
newSelf.withUnsafeBytes { bufferPointer in
let mutableBufferPointer = UnsafeMutableRawBufferPointer(mutating: bufferPointer)
data.copyBytes(to: mutableBufferPointer)
}
self = newSelf
}
}
Is there really no better way to decode a stored authentication tag to compare against a value being computed now?
lukasa
(Cory Benfield)
2
To answer your initial question: no, there is not. This is intentional: the type system does not want you to confuse a MAC you calculated for one you saved somewhere else.
However, your underlying question was:
And the answer here is "yes, there is". HashedAuthenticationCode has an implementation of public static func == where the right hand side is any DataProtocol. So long as you have a type conforming to DataProtocol, you can just ask whether the HashedAuthenticationCode is equal to it. Swift Crypto will take care of doing constant-time comparison.
3 Likes
MPLewis
(Mike Lewis)
3
Gotcha, I completely missed that overload - thanks for the clarification!