Click here to Skip to main content
15,886,664 members
Articles / Programming Languages / C#
Tip/Trick

Cryptography with certificates

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
2 Nov 2012CPOL 29.4K   10   3
Cryptography Class for Certificates

Introduction

How to do cryptography with X509 certificates.

Background

There is a great article on cryptography and I had to use certificates so I created a class around the functions from http://www.codeproject.com/Articles/10877/Public-Key-RSA-Encryption-in-C-NET.

Using the code

Create a class project with C# and paste the code and build, after that you can add the reference to the project and you will be able to encrypt and decrypt using a X509 certificate.

C#
#region
 
using System;
using System.Collections;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
 
#endregion
 
namespace CertificateCrypto
{
    public class X509Cryptography
    {
        public readonly X509Certificate2 _CertFile;
        public readonly bool _FOaep;
 
        public X509Cryptography(X509Certificate2 certFile, bool fOAEP)
        {
            if (certFile != null) _CertFile = certFile;
            else throw new SystemException("Certificate is null");
            _FOaep = fOAEP;
        }
 
        public X509Cryptography(X509Certificate2 certFile)
        {
            if (certFile != null) _CertFile = certFile;
            else throw new SystemException("Certificate is null");
            _FOaep = false;
        }
 
        public static byte[] ReadStream(Stream input)
        {
            using (var ms = new MemoryStream())
            {
                input.CopyTo(ms);
                return ms.ToArray();
            }
        }
        #region Encryption
 
        public string EncryptStringTest(string inputString)
        {
            // TODO: Add Proper Exception Handlers
            var rsaCryptoServiceProvider = (RSACryptoServiceProvider) _CertFile.PublicKey.Key;
            int keySize = rsaCryptoServiceProvider.KeySize/8;
            byte[] bytes = Encoding.UTF32.GetBytes(inputString);
            // The hash function in use by the .NET RSACryptoServiceProvider here 
            // is SHA1
            // int maxLength = ( keySize ) - 2 - 
            //              ( 2 * SHA1.Create().ComputeHash( rawBytes ).Length );
            int maxLength = keySize - 42;
            int dataLength = bytes.Length;
            int iterations = dataLength/maxLength;
            var stringBuilder = new StringBuilder();
            for (int i = 0; i <= iterations; i++)
            {
                var tempBytes = new byte[
                    (dataLength - maxLength*i > maxLength)
                        ? maxLength
                        : dataLength - maxLength*i];
                Buffer.BlockCopy(bytes, maxLength*i, tempBytes, 0,
                                 tempBytes.Length);
                byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt(tempBytes, _FOaep);
 
                // Be aware the RSACryptoServiceProvider reverses the order of 
                // encrypted bytes. It does this after encryption and before 
                // decryption. If you do not require compatibility with Microsoft 
                // Cryptographic API (CAPI) and/or other vendors. Comment out the 
                // next line and the corresponding one in the DecryptString function.
                Array.Reverse(encryptedBytes);
                // Why convert to base 64?
                // Because it is the largest power-of-two base printable using only 
                // ASCII characters
                stringBuilder.Append(Convert.ToBase64String(encryptedBytes));
            }
            return stringBuilder.ToString();
        }
 
        public string DecryptStringTest(string inputString)
        {
            // TODO: Add Proper Exception Handlers
            var rsaCryptoServiceProvider = (RSACryptoServiceProvider) _CertFile.PrivateKey;
            int keySize = rsaCryptoServiceProvider.KeySize/8;
            int base64BlockSize = ((keySize/8)%3 != 0) ? (((keySize/8)/3)*4) + 4 : ((keySize/8)/3)*4;
 
            int iterations = inputString.Length/base64BlockSize;
            var arrayList = new ArrayList();
            for (int i = 0; i < iterations; i++)
            {
                byte[] encryptedBytes = Convert.FromBase64String(
                    inputString.Substring(base64BlockSize*i, base64BlockSize));
                // Be aware the RSACryptoServiceProvider reverses the order of 
                // encrypted bytes after encryption and before decryption.
                // If you do not require compatibility with Microsoft Cryptographic 
                // API (CAPI) and/or other vendors.
                // Comment out the next line and the corresponding one in the 
                // EncryptString function.
                Array.Reverse(encryptedBytes);
                arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(encryptedBytes, _FOaep));
            }
            return Encoding.UTF32.GetString(arrayList.ToArray(Type.GetType("System.Byte")) as byte[]);
        }
 
 
        public string EncryptString(string inputString)
        {
            try
            {
                // TODO: Add Proper Exception Handlers
                var rsaCryptoServiceProvider = (RSACryptoServiceProvider) _CertFile.PublicKey.Key;
 
                int keySize = rsaCryptoServiceProvider.KeySize/8;
                byte[] bytes = Encoding.UTF32.GetBytes(inputString);
                // The hash function in use by the .NET RSACryptoServiceProvider here 
                // is SHA1
                // int maxLength = ( keySize ) - 2 - 
                //              ( 2 * SHA1.Create().ComputeHash( rawBytes ).Length );
                int maxLength = keySize - 42;
                int dataLength = bytes.Length;
                int iterations = dataLength/maxLength;
                var stringBuilder = new StringBuilder();
                for (int i = 0; i <= iterations; i++)
                {
                    var tempBytes = new byte[
                        (dataLength - maxLength*i > maxLength)
                            ? maxLength
                            : dataLength - maxLength*i];
                    Buffer.BlockCopy(bytes, maxLength*i, tempBytes, 0,
                                     tempBytes.Length);
                    byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt(tempBytes,
                                                                             true);
                    // Be aware the RSACryptoServiceProvider reverses the order of 
                    // encrypted bytes. It does this after encryption and before 
                    // decryption. If you do not require compatibility with Microsoft 
                    // Cryptographic API (CAPI) and/or other vendors. Comment out the 
                    // next line and the corresponding one in the DecryptString function.
                    Array.Reverse(encryptedBytes);
                    // Why convert to base 64?
                    // Because it is the largest power-of-two base printable using only 
                    // ASCII characters
                    stringBuilder.Append(Convert.ToBase64String(encryptedBytes));
                }
                return stringBuilder.ToString();
            }
            catch (Exception ex)
            {
                throw new SystemException(ex.Message);
            }
        }
 
        public string DecryptString(string inputString)
        {
            try
            {
                // TODO: Add Proper Exception Handlers
                var rsaCryptoServiceProvider
                    = (RSACryptoServiceProvider) _CertFile.PrivateKey;
                int dwKeySize = rsaCryptoServiceProvider.KeySize;
                int base64BlockSize = ((dwKeySize/8)%3 != 0)
                                          ? (((dwKeySize/8)/3)*4) + 4
                                          : ((dwKeySize/8)/3)*4;
                int iterations = inputString.Length/base64BlockSize;
                var arrayList = new ArrayList();
                for (int i = 0; i < iterations; i++)
                {
                    byte[] encryptedBytes = Convert.FromBase64String(
                        inputString.Substring(base64BlockSize*i, base64BlockSize));
                    // Be aware the RSACryptoServiceProvider reverses the order of 
                    // encrypted bytes after encryption and before decryption.
                    // If you do not require compatibility with Microsoft Cryptographic 
                    // API (CAPI) and/or other vendors.
                    // Comment out the next line and the corresponding one in the 
                    // EncryptString function.
                    Array.Reverse(encryptedBytes);
                    arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(
                        encryptedBytes, true));
                }
                return Encoding.ASCII.GetString(arrayList.ToArray(
                    Type.GetType("System.Byte")) as byte[]);
            }
            catch (Exception ex)
            {
                throw new SystemException(ex.Message);
            }
        }
 
        #endregion
       
    }
}

Points of Interest

It was a bit difficult to find the exact code I needed but one I went through the article http://www.codeproject.com/Articles/10877/Public-Key-RSA-Encryption-in-C-NET and asymetric encryption 101 it became clear.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionPrivate key read error Pin
Viswanathareddy Kethireddy20-Mar-20 22:34
Viswanathareddy Kethireddy20-Mar-20 22:34 
QuestionEncoding Pin
Member 114266035-May-15 4:05
Member 114266035-May-15 4:05 
AnswerRe: Encoding Pin
CafedeJamaica7-Jul-15 1:56
professionalCafedeJamaica7-Jul-15 1:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.