Click here to Skip to main content
15,891,375 members
Articles / Web Development / ASP.NET
Article

Encryption/Decryption with .NET

Rate me:
Please Sign up or sign in to vote.
3.00/5 (31 votes)
14 Mar 2002 447.9K   5K   90   63
A .NET SymmetricAlgorithm security class wrapper for in memory encryption/decryption with a private key

Introduction

Encryption and Decryption

The System.Security.Cryptographic namespace within the Microsoft .NET Framework provides a variety of tools to aid in encryption and decryption. The CryptoStream class is used here to demonstrate the encryption and decryption with System.Security.Cryptographic.SymmetricAlgorithm, such as DESCryptoServiceProvider, RC2CryptoServiceProvider, and RijndaelManaged classes.

I have searched the Internet for some samples and all I found were based on the Microsoft sample code in KB Article Q307010 which basically uses input/output files as source and destination. I would like to have the encryption and decryption done in memory without having to specify source and destination files, so that I could use the code on a web server or so.

If you have any questions, please email to: fangfrank@hotmail.com

Frank Fang

Source Code

using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;

namespace FangHome_Crypto
{
    /// <summary>
    /// SymmCrypto is a wrapper of System.Security.Cryptography.SymmetricAlgorithm classes
    /// and simplifies the interface. It supports customized SymmetricAlgorithm as well.
    /// </summary>
    public class SymmCrypto
    {
        /// <remarks>
        /// Supported .Net intrinsic SymmetricAlgorithm classes.
        /// </remarks>
        public enum SymmProvEnum : int
        {
            DES, RC2, Rijndael
        }

        private SymmetricAlgorithm mobjCryptoService;

        /// <remarks>
        /// Constructor for using an intrinsic .Net SymmetricAlgorithm class.
        /// </remarks>
        public SymmCrypto(SymmProvEnum NetSelected)
        {
            switch (NetSelected)
            {
                case SymmProvEnum.DES:
                    mobjCryptoService = new DESCryptoServiceProvider();
                    break;
                case SymmProvEnum.RC2:
                    mobjCryptoService = new RC2CryptoServiceProvider();
                    break;
                case SymmProvEnum.Rijndael:
                    mobjCryptoService = new RijndaelManaged();
                    break;
            }
        }

        /// <remarks>
        /// Constructor for using a customized SymmetricAlgorithm class.
        /// </remarks>
        public SymmCrypto(SymmetricAlgorithm ServiceProvider)
        {
            mobjCryptoService = ServiceProvider;
        }

        /// <remarks>
        /// Depending on the legal key size limitations of a specific CryptoService provider
        /// and length of the private key provided, padding the secret key with space character
        /// to meet the legal size of the algorithm.
        /// </remarks>
        private byte[] GetLegalKey(string Key)
        {
            string sTemp;
            if (mobjCryptoService.LegalKeySizes.Length > 0)
            {
                int lessSize = 0, moreSize = mobjCryptoService.LegalKeySizes[0].MinSize;
                // key sizes are in bits
                while (Key.Length * 8 > moreSize)
                {
                    lessSize = moreSize;
                    moreSize += mobjCryptoService.LegalKeySizes[0].SkipSize;
                }
                sTemp = Key.PadRight(moreSize / 8, ' ');
            }
            else
                sTemp = Key;

            // convert the secret key to byte array
            return ASCIIEncoding.ASCII.GetBytes(sTemp);
        }

        public string Encrypting(string Source, string Key)
        {
            byte[] bytIn = System.Text.ASCIIEncoding.ASCII.GetBytes(Source);
            // create a MemoryStream so that the process can be done without I/O files
            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            byte[] bytKey = GetLegalKey(Key);

            // set the private key
            mobjCryptoService.Key = bytKey;
            mobjCryptoService.IV = bytKey;

            // create an Encryptor from the Provider Service instance
            ICryptoTransform encrypto = mobjCryptoService.CreateEncryptor();

            // create Crypto Stream that transforms a stream using the encryption
            CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Write);

            // write out encrypted content into MemoryStream
            cs.Write(bytIn, 0, bytIn.Length);
            cs.FlushFinalBlock();
            
            // get the output and trim the '\0' bytes
            byte[] bytOut = ms.GetBuffer();
            int i = 0;
            for (i = 0; i < bytOut.Length; i++)
                if (bytOut[i] == 0)
                    break;
                    
            // convert into Base64 so that the result can be used in xml
            return System.Convert.ToBase64String(bytOut, 0, i);
        }

        public string Decrypting(string Source, string Key)
        {
            // convert from Base64 to binary
            byte[] bytIn = System.Convert.FromBase64String(Source);
            // create a MemoryStream with the input
            System.IO.MemoryStream ms = new System.IO.MemoryStream(bytIn, 0, bytIn.Length);

            byte[] bytKey = GetLegalKey(Key);

            // set the private key
            mobjCryptoService.Key = bytKey;
            mobjCryptoService.IV = bytKey;

            // create a Decryptor from the Provider Service instance
            ICryptoTransform encrypto = mobjCryptoService.CreateDecryptor();
 
            // create Crypto Stream that transforms a stream using the decryption
            CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read);

            // read out the result from the Crypto Stream
            System.IO.StreamReader sr = new System.IO.StreamReader( cs );
            return sr.ReadToEnd();
        }
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralThe bug in encryption found... Pin
Nikolai Serdiuk25-Feb-04 23:32
Nikolai Serdiuk25-Feb-04 23:32 
GeneralRe: The bug in encryption found... Pin
Anonymous31-May-04 12:43
Anonymous31-May-04 12:43 
GeneralRe: The bug in encryption found... Pin
Nikolai Serdiuk31-May-04 21:34
Nikolai Serdiuk31-May-04 21:34 
GeneralRe: The bug in encryption found... Pin
Nikolai Serdiuk31-May-04 21:56
Nikolai Serdiuk31-May-04 21:56 
GeneralRe: The bug in encryption found... Pin
Nikolai Serdiuk31-May-04 21:47
Nikolai Serdiuk31-May-04 21:47 
GeneralPolar Crypto Light... Pin
mikasa8-Jan-04 11:07
mikasa8-Jan-04 11:07 
QuestionBest? Pin
MKlucher15-Dec-03 19:34
MKlucher15-Dec-03 19:34 
GeneralDES, Rijndael work, RC2 doesn't Pin
coulsong29-Oct-03 6:32
coulsong29-Oct-03 6:32 
I added the suggested code fixes (VB.Net version). DES and Rijndael work fine, but RC2 gets the following error:
'' read out the result from the Crypto Stream
Dim sr As System.IO.StreamReader = New ystem.IO.StreamReader(cs)
Return sr.ReadToEnd() ***This line has the error***
End Function

[CryptographicException: Bad Data.]
   System.Security.Cryptography.CryptoAPITransform._DecryptData(IntPtr hKey, 
                            Byte[] rgb, Int32 ib, Int32 cb, Boolean fDone) +0
   System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(
                 Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) +1007
   System.Security.Cryptography.CryptoStream.Read(Byte[] buffer, Int32 offset,
                 Int32 count) +802
   System.IO.StreamReader.ReadBuffer(Char[] userBuffer, Int32 userOffset, 
                 Int32 desiredChars, Boolean& readToUserBuffer) +68
   System.IO.StreamReader.Read(Char[] buffer, Int32 index, Int32 count) +125
   System.IO.StreamReader.ReadToEnd() +93
   SecurIt.Crypto.SymmCrypto.Decrypting(String Source, String Key) in 
           C:\ATEC System.root\ATEC System\SecurityLayer\UserSecurity.vb:141

Here's what I used to test it (ASP.Net):
Private Sub btnRunTest_Click(ByVal sender As System.Object, 
                          ByVal e As System.EventArgs) Handles btnRunTest.Click
        Dim objCrypto As SymmCrypto = New SymmCrypto
        Dim countBad As Integer = 0
        Dim countGood As Integer = 0
        Dim sPswd As String 'ASCII char
        Dim pswdLength As Integer
        Dim tmpString1, tmpString2 As String

        Dim i, j As Integer

        Dim rand As New Random(CInt(Date.Now.Ticks And Integer.MaxValue))

        txtRunTest.Text = ""

        For i = 1 To txtHowMany.Text
            sPswd = ""
            'get password length between 1 and 30
            pswdLength = rand.Next(1, 30)
            'build password string by selecting random Ascii
            'characters between "0" and "z"
            For j = 1 To pswdLength
                sPswd &= Chr(rand.Next(48, 122))
            Next

            'Get a random key between 1 and 1M 
            Key = rand.Next(1, 1000000).ToString

            objCrypto.SymmCrypto(SymmCrypto.SymmProvEnum.RC2)
            tmpString1 = objCrypto.Encrypting(sPswd, Key)
            tmpString2 = objCrypto.Decrypting(tmpString1, Key)

            If tmpString2.Equals(sPswd) Then
                countGood += 1
            Else
                countBad += 1
            End If

        Next

      txtRunTest.Text = "Test Complete. Good=" & countGood.ToString & _
            " Bad=" & countBad.ToString

    End Sub

Note: If I set the key to "12345" it still fails.

It passes for 100,000 items using DES or Rijndael.

Thanks, Gord.
GeneralError: data that has to be encrypted has the wrong length Pin
tec-behind16-Sep-03 6:24
tec-behind16-Sep-03 6:24 
GeneralRe: Error: data that has to be encrypted has the wrong length Pin
coar28-Jan-04 5:39
coar28-Jan-04 5:39 
GeneralRe: Error: data that has to be encrypted has the wrong length Pin
Anonymous23-Sep-05 2:06
Anonymous23-Sep-05 2:06 
GeneralEncryption SymmetricAlgorithm Classes Pin
mrieger12-Jun-03 10:20
mrieger12-Jun-03 10:20 
GeneralFrank Fang's latest code Pin
RickyChen10-May-03 6:00
RickyChen10-May-03 6:00 
GeneralRe: Frank Fang's latest code Pin
coolg4443-Apr-07 7:00
coolg4443-Apr-07 7:00 
GeneralRe: Frank Fang's latest code Pin
djazzz19-Jun-07 2:08
djazzz19-Jun-07 2:08 
GeneralRe: Frank Fang's latest code Pin
langer524718-Oct-07 11:47
langer524718-Oct-07 11:47 
GeneralRe: Frank Fang's latest code Pin
ctrlnick16-Jul-08 14:20
ctrlnick16-Jul-08 14:20 
GeneralImplementation with Rijndael does bad things in 0.5 % cases Pin
utunga5-May-03 5:48
utunga5-May-03 5:48 
GeneralRe: (FIXES) Implementation with Rijndael does bad things in 0.5 % cases Pin
utunga5-May-03 6:17
utunga5-May-03 6:17 
GeneralRe: (FIXES) Implementation with Rijndael does bad things in 0.5 % cases Pin
sunroam200223-May-03 4:48
sunroam200223-May-03 4:48 
GeneralEnhanced and working version here Pin
William M. Rawls6-Dec-02 9:33
William M. Rawls6-Dec-02 9:33 
GeneralRe: Enhanced and working version here Pin
William M. Rawls6-Dec-02 9:35
William M. Rawls6-Dec-02 9:35 
GeneralRe: Enhanced and working version here Pin
Ian V10-Dec-02 4:39
Ian V10-Dec-02 4:39 
GeneralRe: Enhanced and working version here Pin
William M. Rawls10-Dec-02 11:53
William M. Rawls10-Dec-02 11:53 
GeneralRe: (Fix) Enhanced and working version here Pin
Bruno H. M. Oliveira21-Aug-03 9:58
Bruno H. M. Oliveira21-Aug-03 9:58 

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.