/// <summary> /// Decrypts a blob of data encrypted using <see cref="EncryptAndSign"/> after verifying the digital signature on it. /// </summary> /// <param name="container"></param> /// <param name="joseObject">The compact form of the encrypted and signed JOSE object.</param> /// <param name="signedBy">The certificate of the signer will be output into this variable.</param> /// <param name="decryptionCertificates">The set of certificates whose key pairs may be used for decryption. The correct certificate and key pair will be selected automatically (if it is among the set).</param> /// <exception cref="CryptographicException"> /// Thrown if a cryptographic operation fails (e.g. because you do not have the correct decryption key). /// </exception> public static byte[] VerifyAndDecrypt(this HelpersContainerClasses.Jose container, string joseObject, out X509Certificate2 signedBy, params X509Certificate2[] decryptionCertificates) { Helpers.Argument.ValidateIsNotNull(joseObject, nameof(joseObject)); Helpers.Argument.ValidateIsNotNull(decryptionCertificates, nameof(decryptionCertificates)); foreach (var decryptionCertificate in decryptionCertificates) { if (decryptionCertificate == null) { throw new ArgumentException("Decryption certificate list cannot contain null values.", nameof(decryptionCertificates)); } VerifyCertificateAndPrivateKeyIsSaneAndUsable(decryptionCertificate); } // Part 1: verify signature. var signedHeader = JWT.Headers(joseObject); if (!signedHeader.ContainsKey("typ") || signedHeader["typ"] as string != JoseSignedType) { throw new ArgumentException("The JOSE object was not produced by " + nameof(EncryptAndSign), nameof(joseObject)); } signedBy = GetCertificateFromJoseHeader(signedHeader); VerifyCertificateIsSaneAndUsable(signedBy); var encrypted = JWT.Decode(joseObject, signedBy.GetRSAPublicKey(), JwsAlgorithm.RS512); // Part 2: decrypt. var encryptedHeader = JWT.Headers(encrypted); if (!encryptedHeader.ContainsKey("typ") || encryptedHeader["typ"] as string != JoseEncryptedType) { throw new ArgumentException("The JOSE object was not produced by " + nameof(EncryptAndSign), nameof(joseObject)); } var encryptedFor = GetCertificateFromJoseHeader(encryptedHeader); var decryptWith = decryptionCertificates.FirstOrDefault(c => c.Thumbprint == encryptedFor.Thumbprint); if (decryptWith == null) { throw new CryptographicException("None of the available decryption keys matched the one used to encrypt the JOSE object."); } return(JWT.DecodeBytes(encrypted, decryptWith.GetRSAPrivateKey(), JweAlgorithm.RSA_OAEP, JweEncryption.A256CBC_HS512)); }