Skip to content

Commit 5a5a52e

Browse files
authored
Update approval_sig.go
1 parent db05eeb commit 5a5a52e

1 file changed

Lines changed: 14 additions & 60 deletions

File tree

internal/receipt/approval_sig.go

Lines changed: 14 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@ import (
55
"encoding/base64"
66
"errors"
77
"fmt"
8-
"os"
9-
"path/filepath"
10-
"runtime"
118
"strings"
9+
10+
"ix-agent-notary/internal/crypto"
1211
)
1312

1413
type ApprovalSigValidationOptions struct {
15-
// Strict fails if an approval exists but is missing a signature, or has an invalid signature.
1614
Strict bool
1715

18-
// PublicKeyPath overrides key resolution and uses this pubkey for verification.
16+
// PublicKeyPath is the highest-precedence verification source.
1917
// Expected format: base64url (no padding) encoded 32-byte ed25519 public key.
2018
PublicKeyPath string
19+
20+
// PublicKeyDir is an optional directory containing <key_id>.pub files.
21+
// If unset, default lookup falls back to keys/ then keys/dev/ relative to cwd.
22+
PublicKeyDir string
2123
}
2224

2325
type ApprovalSigCheck struct {
@@ -29,7 +31,6 @@ type ApprovalSigCheck struct {
2931
func ValidateApprovalSignatures(r Receipt, opts ApprovalSigValidationOptions) (*ApprovalSigCheck, error) {
3032
pol, ok := r["policy"].(map[string]any)
3133
if !ok {
32-
// schema should prevent this; keep defensive
3334
if opts.Strict {
3435
return nil, errors.New("approval sig: missing policy object")
3536
}
@@ -52,23 +53,12 @@ func ValidateApprovalSignatures(r Receipt, opts ApprovalSigValidationOptions) (*
5253
return &ApprovalSigCheck{Skipped: true}, nil
5354
}
5455

55-
// No approvals is fine even in strict mode.
5656
if len(apprs) == 0 {
5757
return &ApprovalSigCheck{Skipped: false, Total: 0, Verified: 0}, nil
5858
}
5959

6060
check := &ApprovalSigCheck{Skipped: false, Total: len(apprs), Verified: 0}
6161

62-
// Optional override: one pubkey for all approvals (demo-friendly).
63-
var overridePub ed25519.PublicKey
64-
if strings.TrimSpace(opts.PublicKeyPath) != "" {
65-
pub, err := loadEd25519PublicKeyBase64URLFile(opts.PublicKeyPath)
66-
if err != nil {
67-
return nil, err
68-
}
69-
overridePub = pub
70-
}
71-
7262
for i, a := range apprs {
7363
obj, ok := a.(map[string]any)
7464
if !ok {
@@ -125,14 +115,13 @@ func ValidateApprovalSignatures(r Receipt, opts ApprovalSigValidationOptions) (*
125115
return nil, fmt.Errorf("approval sig: approvals[%d] signature size invalid (got %d)", i, len(sigBytes))
126116
}
127117

128-
var pub ed25519.PublicKey
129-
if overridePub != nil {
130-
pub = overridePub
131-
} else {
132-
pub, err = resolveEd25519PublicKeyByKeyID(keyID)
133-
if err != nil {
134-
return nil, fmt.Errorf("approval sig: approvals[%d] resolve pubkey: %w", i, err)
135-
}
118+
pub, _, err := crypto.ResolveEd25519PublicKey(crypto.ResolvePublicKeyOptions{
119+
KeyID: keyID,
120+
PublicKeyPath: opts.PublicKeyPath,
121+
SearchDirs: receiptPublicKeySearchDirs(opts.PublicKeyDir),
122+
})
123+
if err != nil {
124+
return nil, fmt.Errorf("approval sig: approvals[%d] resolve pubkey: %w", i, err)
136125
}
137126

138127
if !ed25519.Verify(pub, payload, sigBytes) {
@@ -142,44 +131,9 @@ func ValidateApprovalSignatures(r Receipt, opts ApprovalSigValidationOptions) (*
142131
check.Verified++
143132
}
144133

145-
// If strict, require that every approval is signed+valid.
146134
if opts.Strict && check.Verified != check.Total {
147135
return nil, fmt.Errorf("approval sig: strict mode requires all approvals be signed (%d/%d verified)", check.Verified, check.Total)
148136
}
149137

150138
return check, nil
151139
}
152-
153-
func resolveEd25519PublicKeyByKeyID(keyID string) (ed25519.PublicKey, error) {
154-
root, err := repoRootForReceiptPackage()
155-
if err != nil {
156-
return nil, err
157-
}
158-
p := filepath.Join(root, "keys", "dev", keyID+".pub")
159-
return loadEd25519PublicKeyBase64URLFile(p)
160-
}
161-
162-
func loadEd25519PublicKeyBase64URLFile(path string) (ed25519.PublicKey, error) {
163-
b, err := os.ReadFile(path)
164-
if err != nil {
165-
return nil, fmt.Errorf("approval sig: read pubkey: %w", err)
166-
}
167-
168-
raw, err := base64.RawURLEncoding.DecodeString(strings.TrimSpace(string(b)))
169-
if err != nil {
170-
return nil, fmt.Errorf("approval sig: decode pubkey (base64url): %w", err)
171-
}
172-
if len(raw) != ed25519.PublicKeySize {
173-
return nil, fmt.Errorf("approval sig: pubkey must be %d bytes (got %d)", ed25519.PublicKeySize, len(raw))
174-
}
175-
return ed25519.PublicKey(raw), nil
176-
}
177-
178-
func repoRootForReceiptPackage() (string, error) {
179-
// This file is: <root>/internal/receipt/approval_sig.go
180-
_, file, _, ok := runtime.Caller(0)
181-
if !ok {
182-
return "", errors.New("approval sig: runtime.Caller failed")
183-
}
184-
return filepath.Clean(filepath.Join(filepath.Dir(file), "..", "..")), nil
185-
}

0 commit comments

Comments
 (0)