Files
hanzoai_agent/control-plane/internal/cli/vc_verification_enhanced.go
zeekay 2899aeaa9f feat: merge agents control plane + SDKs into unified agent repo
Consolidate all Hanzo agent infrastructure into one repo:
- control-plane/: Go control plane server (was agents-new)
- sdk/: Go, Python, TypeScript SDKs
- deployments/: Docker, Kubernetes, Helm configs
- Dockerfile.sdk: Python SDK image (ghcr.io/hanzoai/agent:latest)
- CI builds both SDK + control-plane images

No more agentfield — everything is hanzoai/agent.
2026-02-13 12:24:31 -08:00

628 lines
21 KiB
Go

package cli
import (
"crypto/ed25519"
"encoding/base64"
"encoding/json"
"fmt"
"time"
"github.com/hanzoai/agents/control-plane/pkg/types"
)
// EnhancedVCVerifier provides comprehensive VC verification with all integrity checks
type EnhancedVCVerifier struct {
didResolutions map[string]DIDResolutionInfo
verbose bool
}
// NewEnhancedVCVerifier creates a new enhanced VC verifier
func NewEnhancedVCVerifier(didResolutions map[string]DIDResolutionInfo, verbose bool) *EnhancedVCVerifier {
return &EnhancedVCVerifier{
didResolutions: didResolutions,
verbose: verbose,
}
}
// VerificationIssue represents a specific verification problem
type VerificationIssue struct {
Type string `json:"type"`
Severity string `json:"severity"` // "critical", "warning", "info"
Component string `json:"component"`
Field string `json:"field"`
Expected string `json:"expected"`
Actual string `json:"actual"`
Description string `json:"description"`
}
// ComprehensiveVerificationResult provides detailed verification results
type ComprehensiveVerificationResult struct {
Valid bool `json:"valid"`
OverallScore float64 `json:"overall_score"` // 0-100
CriticalIssues []VerificationIssue `json:"critical_issues"`
Warnings []VerificationIssue `json:"warnings"`
ComponentResults []ComponentVerification `json:"component_results"`
WorkflowVerification *WorkflowVerification `json:"workflow_verification,omitempty"`
IntegrityChecks IntegrityCheckResults `json:"integrity_checks"`
SecurityAnalysis SecurityAnalysis `json:"security_analysis"`
ComplianceChecks ComplianceChecks `json:"compliance_checks"`
VerificationTimestamp string `json:"verification_timestamp"`
}
// WorkflowVerification represents workflow-level verification results
type WorkflowVerification struct {
WorkflowID string `json:"workflow_id"`
Valid bool `json:"valid"`
SignatureValid bool `json:"signature_valid"`
ComponentConsistency bool `json:"component_consistency"`
TimestampConsistency bool `json:"timestamp_consistency"`
StatusConsistency bool `json:"status_consistency"`
ChainIntegrity bool `json:"chain_integrity"`
Issues []VerificationIssue `json:"issues"`
}
// IntegrityCheckResults represents various integrity verification results
type IntegrityCheckResults struct {
MetadataConsistency bool `json:"metadata_consistency"`
FieldConsistency bool `json:"field_consistency"`
TimestampValidation bool `json:"timestamp_validation"`
HashValidation bool `json:"hash_validation"`
StructuralIntegrity bool `json:"structural_integrity"`
Issues []VerificationIssue `json:"issues"`
}
// SecurityAnalysis represents security-focused verification results
type SecurityAnalysis struct {
SignatureStrength string `json:"signature_strength"`
KeyValidation bool `json:"key_validation"`
DIDAuthenticity bool `json:"did_authenticity"`
ReplayProtection bool `json:"replay_protection"`
TamperEvidence []string `json:"tamper_evidence"`
SecurityScore float64 `json:"security_score"`
Issues []VerificationIssue `json:"issues"`
}
// ComplianceChecks represents compliance and audit verification results
type ComplianceChecks struct {
W3CCompliance bool `json:"w3c_compliance"`
HanzoAgentsStandardCompliance bool `json:"hanzo_agents_standard_compliance"`
AuditTrailIntegrity bool `json:"audit_trail_integrity"`
DataIntegrityChecks bool `json:"data_integrity_checks"`
Issues []VerificationIssue `json:"issues"`
}
// VerifyEnhancedVCChain performs comprehensive verification of a VC chain
func (v *EnhancedVCVerifier) VerifyEnhancedVCChain(chain EnhancedVCChain) *ComprehensiveVerificationResult {
result := &ComprehensiveVerificationResult{
VerificationTimestamp: time.Now().UTC().Format(time.RFC3339),
CriticalIssues: []VerificationIssue{},
Warnings: []VerificationIssue{},
ComponentResults: []ComponentVerification{},
}
// 1. Verify each execution VC with comprehensive checks
for _, execVC := range chain.ExecutionVCs {
compResult := v.verifyExecutionVCComprehensive(execVC)
result.ComponentResults = append(result.ComponentResults, compResult)
// Collect issues
if !compResult.Valid {
result.CriticalIssues = append(result.CriticalIssues, VerificationIssue{
Type: "execution_vc_invalid",
Severity: "critical",
Component: execVC.VCID,
Description: fmt.Sprintf("Execution VC %s failed verification", execVC.VCID),
})
}
}
// 2. Verify workflow VC if present
if chain.WorkflowVC.VCDocument != nil {
result.WorkflowVerification = v.verifyWorkflowVC(chain.WorkflowVC, chain.ExecutionVCs)
if result.WorkflowVerification != nil && !result.WorkflowVerification.Valid {
result.CriticalIssues = append(result.CriticalIssues, result.WorkflowVerification.Issues...)
}
}
// 3. Perform integrity checks
result.IntegrityChecks = v.performIntegrityChecks(chain)
// 4. Perform security analysis
result.SecurityAnalysis = v.performSecurityAnalysis(chain)
// 5. Perform compliance checks
result.ComplianceChecks = v.performComplianceChecks(chain)
// 6. Calculate overall validity and score
result.Valid = len(result.CriticalIssues) == 0
result.OverallScore = v.calculateOverallScore(result)
return result
}
// verifyExecutionVCComprehensive performs comprehensive verification of a single execution VC
func (v *EnhancedVCVerifier) verifyExecutionVCComprehensive(execVC types.ExecutionVC) ComponentVerification {
result := ComponentVerification{
VCID: execVC.VCID,
ExecutionID: execVC.ExecutionID,
IssuerDID: execVC.IssuerDID,
Status: execVC.Status,
Valid: true,
FormatValid: true,
}
// Parse VC document
var vcDoc types.VCDocument
if err := json.Unmarshal(execVC.VCDocument, &vcDoc); err != nil {
result.Valid = false
result.FormatValid = false
result.Error = fmt.Sprintf("Failed to parse VC document: %v", err)
return result
}
// CRITICAL CHECK 1: Metadata consistency between top-level and VC document
if execVC.IssuerDID != vcDoc.Issuer {
result.Valid = false
result.Error = fmt.Sprintf("Issuer DID mismatch: metadata=%s, vc_document=%s", execVC.IssuerDID, vcDoc.Issuer)
return result
}
// CRITICAL CHECK 2: Execution ID consistency
if execVC.ExecutionID != vcDoc.CredentialSubject.ExecutionID {
result.Valid = false
result.Error = fmt.Sprintf("Execution ID mismatch: metadata=%s, vc_document=%s", execVC.ExecutionID, vcDoc.CredentialSubject.ExecutionID)
return result
}
// CRITICAL CHECK 3: Workflow ID consistency
if execVC.WorkflowID != vcDoc.CredentialSubject.WorkflowID {
result.Valid = false
result.Error = fmt.Sprintf("Workflow ID mismatch: metadata=%s, vc_document=%s", execVC.WorkflowID, vcDoc.CredentialSubject.WorkflowID)
return result
}
// CRITICAL CHECK 4: Session ID consistency
if execVC.SessionID != vcDoc.CredentialSubject.SessionID {
result.Valid = false
result.Error = fmt.Sprintf("Session ID mismatch: metadata=%s, vc_document=%s", execVC.SessionID, vcDoc.CredentialSubject.SessionID)
return result
}
// CRITICAL CHECK 5: Caller DID consistency
if execVC.CallerDID != vcDoc.CredentialSubject.Caller.DID {
result.Valid = false
result.Error = fmt.Sprintf("Caller DID mismatch: metadata=%s, vc_document=%s", execVC.CallerDID, vcDoc.CredentialSubject.Caller.DID)
return result
}
// CRITICAL CHECK 6: Target DID consistency
if execVC.TargetDID != vcDoc.CredentialSubject.Target.DID {
result.Valid = false
result.Error = fmt.Sprintf("Target DID mismatch: metadata=%s, vc_document=%s", execVC.TargetDID, vcDoc.CredentialSubject.Target.DID)
return result
}
// CRITICAL CHECK 7: Status consistency (with HanzoAgents system status mapping)
if !v.isStatusConsistent(execVC.Status, vcDoc.CredentialSubject.Execution.Status) {
result.Valid = false
result.Error = fmt.Sprintf("Status mismatch: metadata=%s, vc_document=%s", execVC.Status, vcDoc.CredentialSubject.Execution.Status)
return result
}
// CRITICAL CHECK 8: Hash consistency
if execVC.InputHash != vcDoc.CredentialSubject.Execution.InputHash {
result.Valid = false
result.Error = fmt.Sprintf("Input hash mismatch: metadata=%s, vc_document=%s", execVC.InputHash, vcDoc.CredentialSubject.Execution.InputHash)
return result
}
if execVC.OutputHash != vcDoc.CredentialSubject.Execution.OutputHash {
result.Valid = false
result.Error = fmt.Sprintf("Output hash mismatch: metadata=%s, vc_document=%s", execVC.OutputHash, vcDoc.CredentialSubject.Execution.OutputHash)
return result
}
// CRITICAL CHECK 9: Signature consistency
if execVC.Signature != vcDoc.Proof.ProofValue {
result.Valid = false
result.Error = fmt.Sprintf("Signature mismatch: metadata=%s, vc_document=%s", execVC.Signature, vcDoc.Proof.ProofValue)
return result
}
// CRITICAL CHECK 10: Cryptographic signature verification
if resolution, exists := v.didResolutions[vcDoc.Issuer]; exists {
valid, err := v.verifyVCSignature(vcDoc, resolution)
result.SignatureValid = valid
if !valid {
result.Valid = false
if err != nil {
result.Error = fmt.Sprintf("Signature verification failed: %v", err)
} else {
result.Error = "Signature verification failed: invalid signature"
}
return result
}
} else {
result.Valid = false
result.SignatureValid = false
result.Error = "DID resolution failed - cannot verify signature"
return result
}
// CRITICAL CHECK 11: Timestamp validation
if err := v.validateTimestamp(vcDoc.IssuanceDate); err != nil {
result.Valid = false
result.Error = fmt.Sprintf("Invalid timestamp: %v", err)
return result
}
// CRITICAL CHECK 12: VC structure validation
if err := v.validateVCStructure(vcDoc); err != nil {
result.Valid = false
result.Error = fmt.Sprintf("Invalid VC structure: %v", err)
return result
}
return result
}
// verifyWorkflowVC performs comprehensive verification of workflow VC
func (v *EnhancedVCVerifier) verifyWorkflowVC(workflowVC types.WorkflowVC, executionVCs []types.ExecutionVC) *WorkflowVerification {
result := &WorkflowVerification{
WorkflowID: workflowVC.WorkflowID,
Valid: true,
SignatureValid: true,
Issues: []VerificationIssue{},
}
// Parse workflow VC document
var workflowVCDoc types.WorkflowVCDocument
if err := json.Unmarshal(workflowVC.VCDocument, &workflowVCDoc); err != nil {
result.Valid = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "workflow_vc_parse_error",
Severity: "critical",
Component: "workflow_vc",
Description: fmt.Sprintf("Failed to parse workflow VC document: %v", err),
})
return result
}
// Verify workflow VC signature
if resolution, exists := v.didResolutions[workflowVCDoc.Issuer]; exists {
validSig, err := verifyWorkflowVCSignature(workflowVCDoc, resolution)
result.SignatureValid = err == nil && validSig
if err != nil {
result.Valid = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "workflow_signature_error",
Severity: "critical",
Component: "workflow_vc",
Field: "proof",
Description: fmt.Sprintf("Failed to verify workflow VC signature: %v", err),
})
} else if !validSig {
result.Valid = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "workflow_signature_invalid",
Severity: "critical",
Component: "workflow_vc",
Field: "proof",
Description: "Workflow VC signature is invalid",
})
}
} else {
result.SignatureValid = false
result.Valid = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "workflow_signature_missing_did",
Severity: "critical",
Component: "workflow_vc",
Field: "issuer_did",
Description: fmt.Sprintf("Missing DID resolution for workflow issuer %s", workflowVCDoc.Issuer),
})
}
// Check component VC consistency
result.ComponentConsistency = v.checkComponentVCConsistency(workflowVC, executionVCs)
if !result.ComponentConsistency {
result.Valid = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "component_vc_inconsistency",
Severity: "critical",
Component: "workflow_vc",
Description: "Component VC list inconsistency detected",
})
}
// Check timestamp consistency
result.TimestampConsistency = v.checkTimestampConsistency(workflowVC, executionVCs)
if !result.TimestampConsistency {
result.Valid = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "timestamp_inconsistency",
Severity: "critical",
Component: "workflow_vc",
Description: "Timestamp inconsistency detected",
})
}
// Check status consistency
result.StatusConsistency = v.checkStatusConsistency(workflowVC, executionVCs)
if !result.StatusConsistency {
result.Valid = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "status_inconsistency",
Severity: "critical",
Component: "workflow_vc",
Description: "Status inconsistency detected",
})
}
// Check chain integrity
result.ChainIntegrity = v.checkChainIntegrity(workflowVC, executionVCs)
if !result.ChainIntegrity {
result.Valid = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "chain_integrity_failure",
Severity: "critical",
Component: "workflow_vc",
Description: "Chain integrity check failed",
})
}
return result
}
// performIntegrityChecks performs various integrity checks
func (v *EnhancedVCVerifier) performIntegrityChecks(chain EnhancedVCChain) IntegrityCheckResults {
result := IntegrityCheckResults{
MetadataConsistency: true,
FieldConsistency: true,
TimestampValidation: true,
HashValidation: true,
StructuralIntegrity: true,
Issues: []VerificationIssue{},
}
// Check metadata consistency across all VCs
for _, execVC := range chain.ExecutionVCs {
if !v.checkExecutionVCMetadataConsistency(execVC) {
result.MetadataConsistency = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "metadata_inconsistency",
Severity: "critical",
Component: execVC.VCID,
Description: "Metadata inconsistency detected in execution VC",
})
}
}
return result
}
// performSecurityAnalysis performs security-focused analysis
func (v *EnhancedVCVerifier) performSecurityAnalysis(chain EnhancedVCChain) SecurityAnalysis {
result := SecurityAnalysis{
SignatureStrength: "Ed25519",
KeyValidation: true,
DIDAuthenticity: true,
ReplayProtection: true,
TamperEvidence: []string{},
SecurityScore: 100.0,
Issues: []VerificationIssue{},
}
// Check for tamper evidence
for _, execVC := range chain.ExecutionVCs {
if evidence := v.detectTamperEvidence(execVC); len(evidence) > 0 {
result.TamperEvidence = append(result.TamperEvidence, evidence...)
result.SecurityScore -= 20.0
}
}
return result
}
// performComplianceChecks performs compliance verification
func (v *EnhancedVCVerifier) performComplianceChecks(chain EnhancedVCChain) ComplianceChecks {
result := ComplianceChecks{
W3CCompliance: true,
HanzoAgentsStandardCompliance: true,
AuditTrailIntegrity: true,
DataIntegrityChecks: true,
Issues: []VerificationIssue{},
}
// Check W3C compliance for each VC
for _, execVC := range chain.ExecutionVCs {
var vcDoc types.VCDocument
if err := json.Unmarshal(execVC.VCDocument, &vcDoc); err == nil {
if !v.checkW3CCompliance(vcDoc) {
result.W3CCompliance = false
result.Issues = append(result.Issues, VerificationIssue{
Type: "w3c_compliance_failure",
Severity: "warning",
Component: execVC.VCID,
Description: "VC does not meet W3C standards",
})
}
}
}
return result
}
// Helper methods for verification checks
func (v *EnhancedVCVerifier) verifyVCSignature(vcDoc types.VCDocument, resolution DIDResolutionInfo) (bool, error) {
// Create canonical representation for verification
vcCopy := vcDoc
vcCopy.Proof = types.VCProof{} // Remove proof for verification
canonicalBytes, err := json.Marshal(vcCopy)
if err != nil {
return false, fmt.Errorf("failed to marshal VC for verification: %w", err)
}
// Check if PublicKeyJWK is empty
if len(resolution.PublicKeyJWK) == 0 {
return false, fmt.Errorf("public key JWK is empty")
}
// Extract public key from JWK
xValue, ok := resolution.PublicKeyJWK["x"].(string)
if !ok {
return false, fmt.Errorf("invalid public key JWK: missing 'x' parameter")
}
publicKeyBytes, err := base64.RawURLEncoding.DecodeString(xValue)
if err != nil {
return false, fmt.Errorf("failed to decode public key: %w", err)
}
publicKey := ed25519.PublicKey(publicKeyBytes)
// Decode signature
signatureBytes, err := base64.RawURLEncoding.DecodeString(vcDoc.Proof.ProofValue)
if err != nil {
return false, fmt.Errorf("failed to decode signature: %w", err)
}
// Verify signature
return ed25519.Verify(publicKey, canonicalBytes, signatureBytes), nil
}
func (v *EnhancedVCVerifier) validateTimestamp(timestamp string) error {
_, err := time.Parse(time.RFC3339, timestamp)
return err
}
func (v *EnhancedVCVerifier) validateVCStructure(vcDoc types.VCDocument) error {
// Check required fields
if len(vcDoc.Context) == 0 {
return fmt.Errorf("missing @context")
}
if len(vcDoc.Type) == 0 {
return fmt.Errorf("missing type")
}
if vcDoc.ID == "" {
return fmt.Errorf("missing id")
}
if vcDoc.Issuer == "" {
return fmt.Errorf("missing issuer")
}
if vcDoc.IssuanceDate == "" {
return fmt.Errorf("missing issuanceDate")
}
return nil
}
func (v *EnhancedVCVerifier) checkExecutionVCMetadataConsistency(execVC types.ExecutionVC) bool {
var vcDoc types.VCDocument
if err := json.Unmarshal(execVC.VCDocument, &vcDoc); err != nil {
return false
}
// All the critical checks we implemented above
return execVC.IssuerDID == vcDoc.Issuer &&
execVC.ExecutionID == vcDoc.CredentialSubject.ExecutionID &&
execVC.WorkflowID == vcDoc.CredentialSubject.WorkflowID &&
execVC.SessionID == vcDoc.CredentialSubject.SessionID &&
execVC.CallerDID == vcDoc.CredentialSubject.Caller.DID &&
execVC.TargetDID == vcDoc.CredentialSubject.Target.DID &&
v.isStatusConsistent(execVC.Status, vcDoc.CredentialSubject.Execution.Status) &&
execVC.InputHash == vcDoc.CredentialSubject.Execution.InputHash &&
execVC.OutputHash == vcDoc.CredentialSubject.Execution.OutputHash &&
execVC.Signature == vcDoc.Proof.ProofValue
}
func (v *EnhancedVCVerifier) checkComponentVCConsistency(workflowVC types.WorkflowVC, executionVCs []types.ExecutionVC) bool {
// Check if component VC count matches
if len(workflowVC.ComponentVCs) != len(executionVCs) {
return false
}
// Check if all execution VC IDs are in component list
componentSet := make(map[string]bool)
for _, vcID := range workflowVC.ComponentVCs {
componentSet[vcID] = true
}
for _, execVC := range executionVCs {
if !componentSet[execVC.VCID] {
return false
}
}
return true
}
func (v *EnhancedVCVerifier) checkTimestampConsistency(workflowVC types.WorkflowVC, executionVCs []types.ExecutionVC) bool {
// Implementation for timestamp consistency checks
return true // Simplified for now
}
func (v *EnhancedVCVerifier) checkStatusConsistency(workflowVC types.WorkflowVC, executionVCs []types.ExecutionVC) bool {
// Implementation for status consistency checks
return true // Simplified for now
}
func (v *EnhancedVCVerifier) checkChainIntegrity(workflowVC types.WorkflowVC, executionVCs []types.ExecutionVC) bool {
// Implementation for chain integrity checks
return true // Simplified for now
}
func (v *EnhancedVCVerifier) detectTamperEvidence(execVC types.ExecutionVC) []string {
evidence := []string{}
// Check for inconsistencies that indicate tampering
if !v.checkExecutionVCMetadataConsistency(execVC) {
evidence = append(evidence, "metadata_inconsistency")
}
return evidence
}
func (v *EnhancedVCVerifier) checkW3CCompliance(vcDoc types.VCDocument) bool {
// Check W3C VC standard compliance
requiredContexts := []string{"https://www.w3.org/2018/credentials/v1"}
for _, required := range requiredContexts {
found := false
for _, context := range vcDoc.Context {
if context == required {
found = true
break
}
}
if !found {
return false
}
}
return true
}
func (v *EnhancedVCVerifier) calculateOverallScore(result *ComprehensiveVerificationResult) float64 {
score := 100.0
// Deduct points for critical issues
score -= float64(len(result.CriticalIssues)) * 25.0
// Deduct points for warnings
score -= float64(len(result.Warnings)) * 5.0
// Factor in security score
score = (score + result.SecurityAnalysis.SecurityScore) / 2.0
if score < 0 {
score = 0
}
return score
}
// isStatusConsistent checks if status values are consistent, accounting for HanzoAgents system status mapping
func (v *EnhancedVCVerifier) isStatusConsistent(metadataStatus, vcDocStatus string) bool {
return types.NormalizeExecutionStatus(metadataStatus) == types.NormalizeExecutionStatus(vcDocStatus)
}