Skip to content

Commit 8d93a50

Browse files
gcmsgclaude
andcommitted
fix: add nil checks to Sign/SignEnvelope, atomic keypair write
- Sign() now returns (string, error) with nil private key check - SignEnvelope() now returns error with nil envelope check - SaveKeypair() uses write-then-rename for atomic file operations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 34cb91f commit 8d93a50

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

envelope/envelope_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ func TestSignEnvelope_VerifyEnvelope_RoundTrip(t *testing.T) {
143143

144144
env := New("alice", "bob", protocol.ProtocolA2A, []byte("hello"))
145145
env.Nonce = "test-nonce"
146-
identity.SignEnvelope(env, kp.PrivateKey)
146+
if err := identity.SignEnvelope(env, kp.PrivateKey); err != nil {
147+
t.Fatalf("SignEnvelope: %v", err)
148+
}
147149

148150
if env.Signature == "" {
149151
t.Fatal("expected non-empty signature")

identity/keypair.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,19 @@ func (kp *Keypair) PublicKeyString() string {
3939
}
4040

4141
// SaveKeypair writes the private key seed to a file (32 bytes, base64-encoded).
42+
// Uses atomic write-then-rename to prevent corruption from interrupted writes.
4243
func SaveKeypair(kp *Keypair, path string) error {
4344
seed := kp.PrivateKey.Seed()
4445
encoded := base64.StdEncoding.EncodeToString(seed)
45-
return os.WriteFile(path, []byte(encoded), 0600)
46+
tmpPath := path + ".tmp"
47+
if err := os.WriteFile(tmpPath, []byte(encoded), 0600); err != nil {
48+
return fmt.Errorf("write keypair temp file: %w", err)
49+
}
50+
if err := os.Rename(tmpPath, path); err != nil {
51+
_ = os.Remove(tmpPath)
52+
return fmt.Errorf("rename keypair file: %w", err)
53+
}
54+
return nil
4655
}
4756

4857
// LoadKeypair reads a keypair from a seed file.

identity/sign.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ import (
77
)
88

99
// Sign creates an Ed25519 signature over the data.
10-
func Sign(privKey ed25519.PrivateKey, data []byte) string {
10+
func Sign(privKey ed25519.PrivateKey, data []byte) (string, error) {
11+
if privKey == nil {
12+
return "", fmt.Errorf("private key is nil")
13+
}
1114
sig := ed25519.Sign(privKey, data)
12-
return base64.StdEncoding.EncodeToString(sig)
15+
return base64.StdEncoding.EncodeToString(sig), nil
1316
}
1417

1518
// Verify checks an Ed25519 signature.
@@ -33,9 +36,16 @@ type SignableEnvelope interface {
3336
}
3437

3538
// SignEnvelope signs the envelope's payload and sets the signature field.
36-
func SignEnvelope(env SignableEnvelope, privKey ed25519.PrivateKey) {
37-
sig := Sign(privKey, env.SigningPayload())
39+
func SignEnvelope(env SignableEnvelope, privKey ed25519.PrivateKey) error {
40+
if env == nil {
41+
return fmt.Errorf("envelope is nil")
42+
}
43+
sig, err := Sign(privKey, env.SigningPayload())
44+
if err != nil {
45+
return fmt.Errorf("sign envelope: %w", err)
46+
}
3847
env.SetSignature(sig)
48+
return nil
3949
}
4050

4151
// VerifyEnvelope verifies the envelope's signature.

0 commit comments

Comments
 (0)