summaryrefslogtreecommitdiffstats
path: root/internal/cryptoutil
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-09-30 21:50:36 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-09-30 21:50:36 -0700
commitc2ca26a918b7054199234e8459d84ee2fd260759 (patch)
treea44f8dad1ca70eb25d4dc12bf17e136fd0711e04 /internal/cryptoutil
parentFix a small issue with updating the block index (diff)
downloadroseh.moe-c2ca26a918b7054199234e8459d84ee2fd260759.tar.zst
Allow appending to notes
Right now it's n^2 which is a big problem (to be fixed later)
Diffstat (limited to 'internal/cryptoutil')
-rw-r--r--internal/cryptoutil/cryptoutil.go26
-rw-r--r--internal/cryptoutil/cryptoutil_test.go20
2 files changed, 29 insertions, 17 deletions
diff --git a/internal/cryptoutil/cryptoutil.go b/internal/cryptoutil/cryptoutil.go
index b269803..0429b02 100644
--- a/internal/cryptoutil/cryptoutil.go
+++ b/internal/cryptoutil/cryptoutil.go
@@ -9,8 +9,10 @@ import (
"crypto/rand"
"crypto/sha512"
"crypto/subtle"
+ "encoding/binary"
"encoding/hex"
"errors"
+ "io"
)
const (
@@ -101,23 +103,31 @@ func (h PasswordHash) CheckPassword(password string) (RawKey, error) {
return key, nil
}
-// Sign generates an HMAC-SHA512 signature and appends it to msg.
-func (k HMACKey) Sign(msg []byte) SignedMessage {
+func (k HMACKey) mac(out, msg []byte, info string) []byte {
mac := hmac.New(sha512.New, k)
+ buf := make([]byte, 0, binary.MaxVarintLen64)
+ mac.Write(binary.AppendUvarint(buf, uint64(len(info))))
+ io.WriteString(mac, info)
mac.Write(msg)
- return mac.Sum(msg)
+ return mac.Sum(out)
+}
+
+// Sign generates an HMAC-SHA512 signature and appends it to msg. The info and
+// additionalData are also authenticated, but are not included in the returned
+// signed message.
+func (k HMACKey) Sign(msg []byte, info string) SignedMessage {
+ return k.mac(msg, msg, info)
}
// Verify checks whether the given message has a valid signature, and returns
-// the raw message if it does.
-func (k HMACKey) Verify(msg SignedMessage) ([]byte, bool) {
+// the raw message if it does. The additionalData must match the data passed
+// to Sign.
+func (k HMACKey) Verify(msg SignedMessage, info string) ([]byte, bool) {
if len(msg) < certSize {
return nil, false
}
msg, sig := msg[:len(msg)-certSize], msg[len(msg)-certSize:]
- mac := hmac.New(sha512.New, k)
- mac.Write(msg)
- if !hmac.Equal(sig, mac.Sum(nil)) {
+ if !hmac.Equal(sig, k.mac(nil, msg, info)) {
return nil, false
}
return msg, true
diff --git a/internal/cryptoutil/cryptoutil_test.go b/internal/cryptoutil/cryptoutil_test.go
index 1670eff..0e0560c 100644
--- a/internal/cryptoutil/cryptoutil_test.go
+++ b/internal/cryptoutil/cryptoutil_test.go
@@ -31,8 +31,8 @@ func TestPassword(t *testing.T) {
func TestSignature(t *testing.T) {
key := HMACKey(mustHex(t, "669e06ec457778b9a8133edb0a87ea82c6b141ffbbc63c038da96258175eb35c"))
msg := []byte("test message")
- signedMsg := key.Sign(msg)
- got, ok := key.Verify(signedMsg)
+ signedMsg := key.Sign(msg, "info")
+ got, ok := key.Verify(signedMsg, "info")
if !ok {
t.Fatalf("Verify(%x) rejected the message", signedMsg)
}
@@ -64,14 +64,14 @@ func TestEncrypt(t *testing.T) {
}} {
t.Run(tc.desc, func(t *testing.T) {
encryptedMsg := new(bytes.Buffer)
- w := key.NewWriter(encryptedMsg, nil)
+ w := key.NewWriter(encryptedMsg, []byte("additional data"))
if _, err := w.Write(tc.msg); err != nil {
t.Fatalf("EncryptingWriter.Write(%q) failed: %s", tc.msg, err)
}
if err := w.Close(); err != nil {
t.Fatalf("EncryptingWriter.Close() failed: %s", err)
}
- got, err := io.ReadAll(key.NewReader(bytes.NewReader(encryptedMsg.Bytes()), nil))
+ got, err := io.ReadAll(key.NewReader(bytes.NewReader(encryptedMsg.Bytes()), []byte("additional data")))
if err != nil {
t.Fatalf("DecryptingReader.Read(%x) failed: %s", encryptedMsg, err)
}
@@ -98,14 +98,14 @@ func TestDeriveKey(t *testing.T) {
}
msg := []byte("test message")
encryptedMsg := new(bytes.Buffer)
- w := key.NewWriter(encryptedMsg, nil)
+ w := key.NewWriter(encryptedMsg, []byte("additional data"))
if _, err := w.Write(msg); err != nil {
t.Fatalf("EncryptingWriter.Write(%q) failed: %s", msg, err)
}
if err := w.Close(); err != nil {
t.Fatalf("EncryptingWriter.Close() failed: %s", err)
}
- got, err := io.ReadAll(key.NewReader(encryptedMsg, nil))
+ got, err := io.ReadAll(key.NewReader(encryptedMsg, []byte("additional data")))
if err != nil {
t.Fatalf("DecryptingReader.Read(%x) failed: %s", encryptedMsg, err)
}
@@ -121,8 +121,9 @@ func BenchmarkEncrypt(b *testing.B) {
msg[i] = byte(i)
}
encryptedMsg := bytes.NewBuffer(make([]byte, 0, 35+len(msg)+16*(len(msg)+segmentSize-1)/segmentSize /* ?? */))
+ additionalData := []byte("additional data")
for b.Loop() {
- w := key.NewWriter(encryptedMsg, nil)
+ w := key.NewWriter(encryptedMsg, additionalData)
if _, err := w.Write(msg); err != nil {
b.Fatal(err)
}
@@ -140,7 +141,8 @@ func BenchmarkDecrypt(b *testing.B) {
msg[i] = byte(i)
}
encryptedMsg := new(bytes.Buffer)
- w := key.NewWriter(encryptedMsg, nil)
+ additionalData := []byte("additional data")
+ w := key.NewWriter(encryptedMsg, additionalData)
if _, err := w.Write(msg); err != nil {
b.Fatal(err)
}
@@ -149,7 +151,7 @@ func BenchmarkDecrypt(b *testing.B) {
}
decryptedMsg := make([]byte, len(msg))
for b.Loop() {
- r := key.NewReader(bytes.NewReader(encryptedMsg.Bytes()), nil)
+ r := key.NewReader(bytes.NewReader(encryptedMsg.Bytes()), additionalData)
if _, err := io.ReadFull(r, decryptedMsg); err != nil {
b.Fatal(err)
}