"""
	HMAC_CTX(ctx::CTX, key::Vector{UInt8}) where CTX<:SHA_CTX

Construct an empty HMAC_CTX context.
"""
struct HMAC_CTX{CTX <: SHA_CTX}
	context::CTX
	outer::Vector{UInt8}

	function HMAC_CTX(ctx::CTX, key::Vector{UInt8}, blocksize::Integer = blocklen(CTX)) where CTX
		if length(key) > blocksize
			_ctx = CTX()
			update!(_ctx, key)
			key = digest!(_ctx)
		end

		pad = blocksize - length(key)
		pad > 0 && (key = [key; fill(0x00, pad)])

		update!(ctx, key .⊻ 0x36)
		new{CTX}(ctx, key .⊻ 0x5c)
	end
end

function update!(ctx::HMAC_CTX, data, datalen = length(data))
	update!(ctx.context, data, datalen)
end

function digest!(ctx::HMAC_CTX{CTX}) where CTX
	digest = digest!(ctx.context)
	_ctx = CTX()
	update!(_ctx, ctx.outer)
	update!(_ctx, digest)
	digest!(_ctx)
end

