/// <summary> /// Verifies that the message was signed by the private key corresponding the paymail's public key. /// </summary> /// <param name="message">A copy of the message which was originally signed.</param> /// <param name="signature">The signature received for validation.</param> /// <param name="paymail">The paymail claiming to have signed the message.</param> /// <param name="pubkey">If known, the public key corresponding to the private key used by the paymail to sign messages.</param> /// <returns>(ok, pubkey) where ok is true only if both the public key and signature were confirmed as valid. /// If ok is true, the returned public key is valid and can be saved for future validations. /// </returns> public async Task <(bool ok, KzPubKey pubkey)> IsValidSignature(string message, string signature, string paymail, KzPubKey pubkey = null) { var(ok, alias, domain) = KzPaymail.Parse(paymail); if (!ok) { goto fail; } if (pubkey != null) { // If a pubkey is provided and the domain is capable, verify that it is correct // If it is not correct, forget the input value and attempt to obtain the valid key. if (await DomainHasCapability(domain, KzPaymail.Capability.verifyPublicKeyOwner)) { if (!await VerifyPubKey(paymail, pubkey)) { pubkey = null; } } } if (pubkey == null) { // Attempt to determine the correct pubkey for the paymail. if (await DomainHasCapability(domain, KzPaymail.Capability.pki)) { pubkey = await GetPubKey(paymail); } } if (pubkey == null) { goto fail; } ok = pubkey.VerifyMessage(message, signature); return(ok, pubkey); fail: return(false, pubkey); }