mirror of
https://github.com/kopia/kopia.git
synced 2026-01-26 07:18:02 -05:00
55 lines
1.4 KiB
Go
55 lines
1.4 KiB
Go
// Package hmac contains utilities for dealing with HMAC checksums.
|
|
package hmac
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"io"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/kopia/kopia/internal/gather"
|
|
)
|
|
|
|
// Append computes HMAC-SHA256 checksum for a given block of bytes and appends it.
|
|
func Append(input gather.Bytes, secret []byte, output *gather.WriteBuffer) {
|
|
h := hmac.New(sha256.New, secret)
|
|
|
|
input.WriteTo(output) //nolint:errcheck
|
|
input.WriteTo(h) //nolint:errcheck
|
|
|
|
var hash [sha256.Size]byte
|
|
|
|
output.Write(h.Sum(hash[:0])) //nolint:errcheck
|
|
}
|
|
|
|
// VerifyAndStrip verifies that given block of bytes has correct HMAC-SHA256 checksum and strips it.
|
|
func VerifyAndStrip(input gather.Bytes, secret []byte, output *gather.WriteBuffer) error {
|
|
if input.Length() < sha256.Size {
|
|
return errors.New("invalid data - too short")
|
|
}
|
|
|
|
p := input.Length() - sha256.Size
|
|
|
|
h := hmac.New(sha256.New, secret)
|
|
r := input.Reader()
|
|
|
|
if _, err := io.CopyN(io.MultiWriter(h, output), r, int64(p)); err != nil {
|
|
return errors.Wrap(err, "error hashing")
|
|
}
|
|
|
|
var sigBuf, actualSignature [sha256.Size]byte
|
|
validSignature := h.Sum(sigBuf[:0])
|
|
|
|
n, err := r.Read(actualSignature[:])
|
|
if err != nil || n != sha256.Size {
|
|
return errors.Wrap(err, "error reading signature")
|
|
}
|
|
|
|
if hmac.Equal(validSignature, actualSignature[:]) {
|
|
return nil
|
|
}
|
|
|
|
return errors.New("invalid data - corrupted")
|
|
}
|