Skip to content

Commit be30d04

Browse files
schighclaude
andcommitted
Rename Sign/DidSign to Watermark/HasWatermark
Rename methods and files to avoid confusion with cryptographic signing. The watermark mechanism folds GUID bytes into a SHA256 hash for tracing purposes and is not a cryptographic primitive. - Sign() -> Watermark() - DidSign() -> HasWatermark() - signer.go -> watermark.go - signer_test.go -> watermark_test.go - Update test messages and README Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3080a94 commit be30d04

4 files changed

Lines changed: 89 additions & 87 deletions

File tree

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,24 +136,24 @@ g := guid.MustNew()
136136
g[0], g[1] = 'a', 'b'
137137
```
138138

139-
### Signing
139+
### Watermarking
140140

141-
A GUID can watermark data by folding its bytes into a SHA256 hash. This is not cryptographic signing. It is a lightweight mechanism for associating a GUID with a piece of data.
141+
A GUID can watermark data by folding its bytes into a SHA256 hash. This is not cryptographic signing. It is a lightweight tracing mechanism for associating a GUID with a piece of data.
142142

143143
```go
144144
g := guid.MustNew()
145145
data := []byte("some payload")
146146

147-
sig := g.Sign(data)
148-
fmt.Printf("Signature: %s\n", sig) // hex-encoded
147+
wm := g.Watermark(data)
148+
fmt.Printf("Watermark: %s\n", wm) // hex-encoded
149149

150-
// verify
151-
if g.DidSign(string(sig)) {
150+
// check
151+
if g.HasWatermark(string(wm)) {
152152
fmt.Println("verified")
153153
}
154154
```
155155

156-
Note: `Sign` uses bitwise OR to fold GUID bytes into the hash. Multiple GUIDs can appear to have signed the same data (false positives are possible). This is suitable for tagging and tracing, not for authentication.
156+
Note: `Watermark` uses bitwise OR to fold GUID bytes into the hash. Multiple GUIDs can appear to match the same watermarked data (false positives are possible). This is suitable for tagging and tracing, not for authentication.
157157

158158
### Custom Generator
159159

signer_test.go

Lines changed: 0 additions & 74 deletions
This file was deleted.

signer.go renamed to watermark.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
"encoding/hex"
66
)
77

8-
// Sign applies the GUID's metadata to a SHA256 hash of the input data
9-
func (g GUID) Sign(in []byte) []byte {
8+
// Watermark folds the GUID's bytes into a SHA256 hash of the input data.
9+
// This is not cryptographic signing. It is a lightweight tracing mechanism
10+
// for associating a GUID with a piece of data.
11+
func (g GUID) Watermark(in []byte) []byte {
1012
// cant digest what we don't have
1113
if len(in) == 0 {
1214
return nil
@@ -34,10 +36,10 @@ func (g GUID) Sign(in []byte) []byte {
3436
return out
3537
}
3638

37-
// DidSign returns true when this GUID was used to sign the hex string
38-
// This function will return false immediately if the input string is either not
39-
// hex-encoded or generated from a SHA256 hash
40-
func (g GUID) DidSign(in string) bool {
39+
// HasWatermark returns true when this GUID's bytes are present in the
40+
// given hex-encoded hash. Returns false if the input is not valid hex
41+
// or not SHA256-sized.
42+
func (g GUID) HasWatermark(in string) bool {
4143
sum, err := hex.DecodeString(in)
4244
if err != nil {
4345
return false

watermark_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package guid
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestGUID_Watermark(t *testing.T) {
8+
// Watermark should return nil for empty input
9+
g := MustNew()
10+
if wm := g.Watermark(nil); wm != nil {
11+
t.Fatalf("expected nil for empty input, got %s", wm)
12+
}
13+
if wm := g.Watermark([]byte{}); wm != nil {
14+
t.Fatalf("expected nil for empty input, got %s", wm)
15+
}
16+
17+
// Watermark should produce consistent output
18+
data := []byte("music television")
19+
wm1 := g.Watermark(data)
20+
wm2 := g.Watermark(data)
21+
if string(wm1) != string(wm2) {
22+
t.Fatalf("expected consistent watermarks, got %s and %s", wm1, wm2)
23+
}
24+
25+
// Watermark output should be 64 hex chars (SHA256 = 32 bytes = 64 hex)
26+
if len(wm1) != 64 {
27+
t.Fatalf("expected watermark length 64, got %d", len(wm1))
28+
}
29+
30+
// Different data should produce different watermarks
31+
wm3 := g.Watermark([]byte("live mice sit on us"))
32+
if string(wm1) == string(wm3) {
33+
t.Fatal("expected different watermarks for different data")
34+
}
35+
36+
// Different GUIDs should produce different watermarks for same data
37+
g2 := MustNew()
38+
wm4 := g2.Watermark(data)
39+
if string(wm1) == string(wm4) {
40+
t.Fatal("expected different watermarks from different GUIDs")
41+
}
42+
}
43+
44+
func TestGUID_HasWatermark(t *testing.T) {
45+
g := MustNew()
46+
data := []byte("test data")
47+
wm := g.Watermark(data)
48+
49+
// GUID should verify its own watermark
50+
if !g.HasWatermark(string(wm)) {
51+
t.Fatal("expected HasWatermark to return true for own watermark")
52+
}
53+
54+
// HasWatermark should return false for invalid hex
55+
if g.HasWatermark("not-hex") {
56+
t.Fatal("expected HasWatermark to return false for non-hex input")
57+
}
58+
59+
// HasWatermark should return false for wrong-length hex
60+
if g.HasWatermark("abcd") {
61+
t.Fatal("expected HasWatermark to return false for short hex")
62+
}
63+
64+
// HasWatermark should return false for tampered data
65+
if g.HasWatermark("aaa0000000000000000000000000000000000000000000000000000000000000") {
66+
t.Fatal("expected HasWatermark to return false for tampered data")
67+
}
68+
69+
// TestGUID watermark round trip
70+
testWm := TestGUID.Watermark([]byte("hello"))
71+
if !TestGUID.HasWatermark(string(testWm)) {
72+
t.Fatal("TestGUID failed to verify its own watermark")
73+
}
74+
}

0 commit comments

Comments
 (0)