/// <summary> /// Encrypts a blob of data and digitally signs it, returning the resulting JOSE object in compact form. /// </summary> /// <param name="container"></param> /// <param name="data">The data to encrypt and sign.</param> /// <param name="encryptFor">Certificate of the recipient. Must contain RSA public key for a 2048-bit key pair or larger.</param> /// <param name="signWith">Certificate of the signer. Must be linked to RSA private key at least 2048 bits in length.</param> public static string EncryptAndSign(this HelpersContainerClasses.Jose container, byte[] data, X509Certificate2 encryptFor, X509Certificate2 signWith) { Helpers.Argument.ValidateIsNotNull(data, nameof(data)); Helpers.Argument.ValidateIsNotNull(encryptFor, nameof(encryptFor)); Helpers.Argument.ValidateIsNotNull(signWith, nameof(signWith)); VerifyCertificateIsSaneAndUsable(encryptFor); VerifyCertificateAndPrivateKeyIsSaneAndUsable(signWith); // Part 1: encrypt. var encryptionHeaders = new Dictionary <string, object> { // Yes, it really is not meant to be base64url for some reason, like the rest of the JOSE object. { "x5c", new[] { Convert.ToBase64String(encryptFor.GetRawCertData()) } }, { "typ", JoseEncryptedType } }; var encrypted = JWT.EncodeBytes(data, encryptFor.GetRSAPublicKey(), JweAlgorithm.RSA_OAEP, JweEncryption.A256CBC_HS512, extraHeaders: encryptionHeaders); // Part 2: sign. var signingHeaders = new Dictionary <string, object> { // Yes, it really is not meant to be base64url for some reason, like the rest of the JOSE object. { "x5c", new[] { Convert.ToBase64String(signWith.GetRawCertData()) } }, { "typ", JoseSignedType } }; return(JWT.Encode(encrypted, signWith.GetRSAPrivateKey(), JwsAlgorithm.RS512, extraHeaders: signingHeaders)); }
protected override async Task <HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var content = await request.Content.ReadAsByteArrayAsync(); var contentJws = JWT.EncodeBytes(content, _certificate.GetRSAPrivateKey(), JwsAlgorithm.RS256); var startIndex = contentJws.IndexOf('.') + 1; var jwsSignature = contentJws.Remove(startIndex, contentJws.IndexOf('.', startIndex) - startIndex); request.Headers.Remove("X-JWS-SIGNATURE"); request.Headers.TryAddWithoutValidation("X-JWS-SIGNATURE", jwsSignature); return(await base.SendAsync(request, cancellationToken)); }