154 lines
3.7 KiB
Go
154 lines
3.7 KiB
Go
package signing_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/forgeo/forgebucket/internal/domain/signing"
|
|
)
|
|
|
|
func TestGenerateAndSign(t *testing.T) {
|
|
ks, err := signing.Generate()
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
if ks.KeyID() == "" {
|
|
t.Fatal("expected non-empty key ID")
|
|
}
|
|
if ks.PublicKeyPEM() == "" {
|
|
t.Fatal("expected non-empty public key PEM")
|
|
}
|
|
}
|
|
|
|
func TestSignAndVerify(t *testing.T) {
|
|
ks, err := signing.Generate()
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
|
|
content := []byte("hello, forgebucket artifact")
|
|
bundle, err := ks.Sign(42, "binary.tar.gz", content)
|
|
if err != nil {
|
|
t.Fatalf("Sign: %v", err)
|
|
}
|
|
|
|
if bundle.MediaType != "application/vnd.forgebucket.signature.bundle+json" {
|
|
t.Errorf("unexpected media type: %s", bundle.MediaType)
|
|
}
|
|
if bundle.Payload.ArtifactID != 42 {
|
|
t.Errorf("artifact ID mismatch: got %d", bundle.Payload.ArtifactID)
|
|
}
|
|
if bundle.Payload.Name != "binary.tar.gz" {
|
|
t.Errorf("name mismatch: got %s", bundle.Payload.Name)
|
|
}
|
|
if bundle.Payload.Digest == "" {
|
|
t.Error("expected non-empty digest")
|
|
}
|
|
if bundle.Signature == "" {
|
|
t.Error("expected non-empty signature")
|
|
}
|
|
|
|
bundleJSON, err := json.Marshal(bundle)
|
|
if err != nil {
|
|
t.Fatalf("marshal bundle: %v", err)
|
|
}
|
|
|
|
result, err := ks.Verify(bundleJSON)
|
|
if err != nil {
|
|
t.Fatalf("Verify: %v", err)
|
|
}
|
|
if !result.Valid {
|
|
t.Error("expected valid=true")
|
|
}
|
|
if !result.KeyMatches {
|
|
t.Error("expected keyMatchesServer=true")
|
|
}
|
|
if result.Digest != bundle.Payload.Digest {
|
|
t.Errorf("digest mismatch: %s vs %s", result.Digest, bundle.Payload.Digest)
|
|
}
|
|
}
|
|
|
|
func TestVerifyTamperedSignature(t *testing.T) {
|
|
ks, _ := signing.Generate()
|
|
content := []byte("artifact content")
|
|
bundle, err := ks.Sign(1, "file.bin", content)
|
|
if err != nil {
|
|
t.Fatalf("Sign: %v", err)
|
|
}
|
|
|
|
// Tamper: valid base64 but not a valid ECDSA signature over this payload.
|
|
// "Z2FyYmFnZQ==" decodes to "garbage" which is not a valid DER ECDSA sig.
|
|
bundle.Signature = "Z2FyYmFnZQ=="
|
|
|
|
bundleJSON, _ := json.Marshal(bundle)
|
|
result, err := ks.Verify(bundleJSON)
|
|
if err != nil {
|
|
t.Fatalf("Verify should not error on invalid sig: %v", err)
|
|
}
|
|
if result.Valid {
|
|
t.Error("expected valid=false for tampered signature")
|
|
}
|
|
}
|
|
|
|
func TestVerifyWrongKey(t *testing.T) {
|
|
ks1, _ := signing.Generate()
|
|
ks2, _ := signing.Generate()
|
|
|
|
content := []byte("artifact")
|
|
bundle, err := ks1.Sign(10, "tool", content)
|
|
if err != nil {
|
|
t.Fatalf("Sign: %v", err)
|
|
}
|
|
|
|
bundleJSON, _ := json.Marshal(bundle)
|
|
|
|
// Verify with ks2 — key won't match.
|
|
result, err := ks2.Verify(bundleJSON)
|
|
if err != nil {
|
|
t.Fatalf("Verify: %v", err)
|
|
}
|
|
// Cryptographic signature is still valid (uses embedded pub key), but key doesn't match server.
|
|
if !result.Valid {
|
|
t.Error("signature itself should still be cryptographically valid")
|
|
}
|
|
if result.KeyMatches {
|
|
t.Error("expected keyMatchesServer=false when signed by a different key")
|
|
}
|
|
}
|
|
|
|
func TestNewFromPEM(t *testing.T) {
|
|
ks1, err := signing.Generate()
|
|
if err != nil {
|
|
t.Fatalf("Generate: %v", err)
|
|
}
|
|
|
|
pemStr, err := ks1.PrivateKeyPEM()
|
|
if err != nil {
|
|
t.Fatalf("PrivateKeyPEM: %v", err)
|
|
}
|
|
|
|
ks2, err := signing.New(pemStr)
|
|
if err != nil {
|
|
t.Fatalf("New from PEM: %v", err)
|
|
}
|
|
|
|
if ks1.KeyID() != ks2.KeyID() {
|
|
t.Errorf("key IDs differ: %s vs %s", ks1.KeyID(), ks2.KeyID())
|
|
}
|
|
|
|
// Sign with ks1, verify with ks2 (same underlying key).
|
|
bundle, _ := ks1.Sign(5, "bin", []byte("data"))
|
|
bundleJSON, _ := json.Marshal(bundle)
|
|
|
|
result, err := ks2.Verify(bundleJSON)
|
|
if err != nil {
|
|
t.Fatalf("Verify: %v", err)
|
|
}
|
|
if !result.Valid {
|
|
t.Error("expected valid=true")
|
|
}
|
|
if !result.KeyMatches {
|
|
t.Error("expected keyMatchesServer=true for same key material")
|
|
}
|
|
}
|