public static ArraySegment<byte> Decrypt(
ArraySegment<byte> dataToDecrypt,
X509Certificate2 encryptingCertificate,
bool useOaep,
ArraySegment<byte> outputBuffer)
{
// get the encrypting key.
using (RSA rsa = encryptingCertificate.GetRSAPrivateKey())
{
if (rsa == null)
{
throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "No private key for certificate.");
}
int inputBlockSize = rsa.KeySize / 8;
int outputBlockSize = GetPlainTextBlockSize(encryptingCertificate, useOaep);
// 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 = outputBuffer.Array;
using (MemoryStream ostrm = new MemoryStream(
decryptedBuffer,
outputBuffer.Offset,
outputBuffer.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);
if (useOaep == true)
{
byte[] plainText = rsa.Decrypt(input, RSAEncryptionPadding.OaepSHA1);
ostrm.Write(plainText, 0, plainText.Length);
}
else
{
byte[] plainText = rsa.Decrypt(input, RSAEncryptionPadding.Pkcs1);
ostrm.Write(plainText, 0, plainText.Length);
}
}
}
// return buffers.
return new ArraySegment<byte>(decryptedBuffer, outputBuffer.Offset, (dataToDecrypt.Count / inputBlockSize) * outputBlockSize);
}
}
#endregion