/// <summary> /// Decrypts the message using RSA encryption. /// </summary> private ArraySegment <byte> Rsa_Decrypt( ArraySegment <byte> dataToDecrypt, ArraySegment <byte> headerToCopy, X509Certificate2 encryptingCertificate, RsaUtils.Padding padding) { RSA rsa = null; try { // get the encrypting key. rsa = encryptingCertificate.GetRSAPrivateKey(); if (rsa == null) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "No private key for certificate."); } int inputBlockSize = RsaUtils.GetCipherTextBlockSize(rsa, padding); int outputBlockSize = RsaUtils.GetPlainTextBlockSize(rsa, padding); // verify the input data is the correct block size. if (dataToDecrypt.Count % inputBlockSize != 0) { Utils.Trace("Message is not an integral multiple of the block size. Length = {0}, BlockSize = {1}.", dataToDecrypt.Count, inputBlockSize); } byte[] decryptedBuffer = BufferManager.TakeBuffer(SendBufferSize, "Rsa_Decrypt"); Array.Copy(headerToCopy.Array, headerToCopy.Offset, decryptedBuffer, 0, headerToCopy.Count); RSAEncryptionPadding rsaPadding = RsaUtils.GetRSAEncryptionPadding(padding); using (MemoryStream ostrm = new MemoryStream( decryptedBuffer, headerToCopy.Count, decryptedBuffer.Length - headerToCopy.Count)) { // decrypt body. byte[] input = new byte[inputBlockSize]; for (int ii = dataToDecrypt.Offset; ii < dataToDecrypt.Offset + dataToDecrypt.Count; ii += inputBlockSize) { Array.Copy(dataToDecrypt.Array, ii, input, 0, input.Length); byte[] plainText = rsa.Decrypt(input, rsaPadding); ostrm.Write(plainText, 0, plainText.Length); } } // return buffers. return(new ArraySegment <byte>(decryptedBuffer, 0, (dataToDecrypt.Count / inputBlockSize) * outputBlockSize + headerToCopy.Count)); } finally { RsaUtils.RSADispose(rsa); } }