diff --git a/src/main/kotlin/id/walt/auditor/PolicyRegistryService.kt b/src/main/kotlin/id/walt/auditor/PolicyRegistryService.kt index 8b886f07..83ccb0e2 100644 --- a/src/main/kotlin/id/walt/auditor/PolicyRegistryService.kt +++ b/src/main/kotlin/id/walt/auditor/PolicyRegistryService.kt @@ -165,6 +165,7 @@ open class PolicyRegistryService : WaltIdService() { ) register(CredentialStatusPolicy::class, "Verify by credential status") register(DynamicPolicy::class, DynamicPolicyArg::class, "Verify credential by rego policy") + register(MultiSignaturePolicy::class, "Verify embedded multiple signatures") // predefined, hardcoded rego policy specializations // VerifiableMandate policy as specialized rego policy diff --git a/src/main/kotlin/id/walt/auditor/policies/MultiSignaturePolicy.kt b/src/main/kotlin/id/walt/auditor/policies/MultiSignaturePolicy.kt new file mode 100644 index 00000000..07023431 --- /dev/null +++ b/src/main/kotlin/id/walt/auditor/policies/MultiSignaturePolicy.kt @@ -0,0 +1,37 @@ +package id.walt.auditor.policies + +import id.walt.auditor.SimpleVerificationPolicy +import id.walt.auditor.VerificationPolicyResult +import id.walt.credentials.w3c.VerifiableCredential + +class JwtHelper(val credential: String) { + val header get() = credential.substringBefore(".") + val payload get() = credential.substringAfter(".").substringBefore(".") + val signature get() = credential.substringAfterLast(".") + val jwsSignaturePart get() = mapOf( + "protected" to header, + "signature" to signature + ) + + companion object { + fun fromJWS(payload: String, sig: Map): JwtHelper { + val h = sig["protected"] ?: throw Exception("No header found") + val s = sig["signature"] ?: throw Exception("No sig found") + return JwtHelper("$h.$payload.$s") + } + } +} + +class MultiSignaturePolicy: SimpleVerificationPolicy() { + override val description: String + get() = "JWS Multi Signature Verification Policy" + + override fun doVerify(vc: VerifiableCredential): VerificationPolicyResult { + val payload = (vc.credentialSubject?.properties?.get("payload") as? String) ?: return VerificationPolicyResult.failure() + val signatures = (vc.credentialSubject?.properties?.get("signatures") as? List>) ?: return VerificationPolicyResult.failure() + val credentials = signatures.map { JwtHelper.fromJWS(payload, it).credential } + return if(credentials.all { SignaturePolicy().verify(VerifiableCredential.fromString(it)).isSuccess }) { + VerificationPolicyResult.success() + } else VerificationPolicyResult.failure() + } +}