Is there no (sane) way to initialize a HashedAuthenticationCode from an external representation?

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?

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

Gotcha, I completely missed that overload - thanks for the clarification!