From c2ca26a918b7054199234e8459d84ee2fd260759 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Tue, 30 Sep 2025 21:50:36 -0700 Subject: Allow appending to notes Right now it's n^2 which is a big problem (to be fixed later) --- internal/api/api.go | 9 ++++++--- internal/api/errorcode_string.go | 9 +++++---- internal/cryptoutil/cryptoutil.go | 26 ++++++++++++++++++-------- internal/cryptoutil/cryptoutil_test.go | 20 +++++++++++--------- 4 files changed, 40 insertions(+), 24 deletions(-) (limited to 'internal') diff --git a/internal/api/api.go b/internal/api/api.go index 7c8472a..b925a7a 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -11,6 +11,7 @@ const ( Unauthenticated // missing credentials PermissionDenied // invalid credentials, or login required BadRequest // incorrect request format (try gob) + InvalidArgument // one or more arguments was invalid NotFound // requested resource was not found Internal // server encountered an unexpected error ) @@ -35,12 +36,14 @@ type ListNotesResponse struct { Notes []string } -type CreateNoteRequestStream struct { - Chunk []byte +type CreateNoteRequest struct { + ContinuationToken []byte + Chunk []byte } type CreateNoteResponse struct { - Name string + Name string + ContinuationToken []byte } type ReadNoteRequest struct { diff --git a/internal/api/errorcode_string.go b/internal/api/errorcode_string.go index 2b4a294..5ff2ff0 100644 --- a/internal/api/errorcode_string.go +++ b/internal/api/errorcode_string.go @@ -12,13 +12,14 @@ func _() { _ = x[Unauthenticated-1] _ = x[PermissionDenied-2] _ = x[BadRequest-3] - _ = x[NotFound-4] - _ = x[Internal-5] + _ = x[InvalidArgument-4] + _ = x[NotFound-5] + _ = x[Internal-6] } -const _ErrorCode_name = "OkUnauthenticatedPermissionDeniedBadRequestNotFoundInternal" +const _ErrorCode_name = "OkUnauthenticatedPermissionDeniedBadRequestInvalidArgumentNotFoundInternal" -var _ErrorCode_index = [...]uint8{0, 2, 17, 33, 43, 51, 59} +var _ErrorCode_index = [...]uint8{0, 2, 17, 33, 43, 58, 66, 74} func (i ErrorCode) String() string { if i < 0 || i >= ErrorCode(len(_ErrorCode_index)-1) { 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) } -- cgit v1.3.1