Click here to Skip to main content
Click here to Skip to main content
Go to top

Encryption/Decryption with .NET

, 14 Mar 2002
Rate this:
Please Sign up or sign in to vote.
A .NET SymmetricAlgorithm security class wrapper for in memory encryption/decryption with a private key
<!-- Download Links --> <!-- Add the rest of your HTML here -->

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

Share

About the Author

Frank Fang
Web Developer
United States United States
No Biography provided

Comments and Discussions

 
QuestionTake this down PinmemberMark Jones12-Feb-13 4:05 
GeneralMy vote of 1 PinmemberSlip_915-Oct-11 0:49 
GeneralMy vote of 2 PinmemberganeshJoshi27-Jul-10 23:06 
GeneralLet me see PinmemberAbinash Bishoyi19-Jun-10 11:48 
GeneralMy vote of 1 PinmemberTyler Xie19-Dec-08 8:55 
GeneralPhrase I LOVE COFFEE! throws and error PinmemberDave Sopko2-Aug-07 8:23 
GeneralRe: Phrase I LOVE COFFEE! throws and error Pinmemberblackjack215016-Jul-08 23:46 
GeneralRe: Phrase I LOVE COFFEE! throws and error PinmemberBruce Burge22-Apr-09 5:57 
QuestionInvalid Length PinmemberNaeem Hassan25-Jan-07 1:10 
AnswerRe: Invalid Length Pinmembersweemeng.koh23-Sep-07 13:19 
AnswerRe: Invalid Length PinmemberbluebeetleRCC15-Aug-08 5:27 
I can confirm this with AES as well.
 
Use ms.ToArray() -- do NOT scan for the first zero byte!!
 
The ms buffer is zero padded, yes, which means the unused portion of the buffer will be filled with zeros. However, there is a reasonable probability that a zero will appear within the used portion as well! So, if you just iterate the buffer and cut it at the first zero you are running the risk of throwing out relevant data (unlikely for small streams (but it happens), more likely for larger streams).
 
This can explain why a source like "I LOVE COFFEE!" might fail but "I LOVE COFFEE?" and other variants might not. Any given particular key and source text combination has a (usually small, for small sources) chance of producing this failure.
 
If, as in my case, your stream contains dynamic data (I was encrypting a timestamp, which, of course, changed ever time it was encrypted) then the failure will seem intermittent and will really drive you crazy!
 
While digging around for a solution to this (having first stupidly missed the one on this site) I discovered that there are a lot of people making this mistake -- if there is any way (except comments) to more visibly mark or correct the error in the code above that would be worthwhile, I think (it's easy to see this working well and only later, with bigger/more dynamic sources notice the flaw). (Overall this is a very good article and a lot of people have (apparently) been using it as reference.)
 
Also, I found that you can see the same behavior (with Aes, at least) in web apps on a web farm. This is not related to the buffer truncation, but can produce the same errors. It is caused by different machineKey values among servers in the same web farm.
 
If you are getting "Invalid Length" or "Padding is Invalid" errors, be sure first you aren't truncating the buffer (use ToArray() as above). If they are still appearing, they may be web-farm related; if so, I think you can cure this somewhere in the IIS config, by setting all the farm's machineKey attributes to the same value.
AnswerRe: Invalid Length Pinmembernathan2240529-May-09 4:24 
GeneralBase64Strings Pinmemberlyn_s_scott26-May-05 10:33 
GeneralRe: Base64Strings Pinmemberdlwiii22-Aug-08 7:26 
GeneralInvalid Length PinsussAnonymous16-Aug-04 16:58 
GeneralRe: Invalid Length Pinmembervipinjosea2-Aug-05 18:17 
GeneralInvalid lenth PinsussK.Vetter14-Jul-04 23:18 
GeneralRe: Invalid lenth PinsussAnonymous9-Sep-04 23:30 
GeneralRe: Invalid lenth PinsussAnonymous3-Jan-05 6:58 
GeneralRe: Invalid lenth PinmemberJohn Storer II5-Jul-06 2:31 
GeneralRe: Invalid lenth Pinmembershuchi agarwal28-Jul-06 3:14 
GeneralThe bug in encryption found... PinmemberNikolai Serdiuk25-Feb-04 23:32 
GeneralRe: The bug in encryption found... PinsussAnonymous31-May-04 12:43 
GeneralRe: The bug in encryption found... PinmemberNikolai Serdiuk31-May-04 21:34 
GeneralRe: The bug in encryption found... PinmemberNikolai Serdiuk31-May-04 21:56 
GeneralRe: The bug in encryption found... PinmemberNikolai Serdiuk31-May-04 21:47 
GeneralPolar Crypto Light... Pinmembermikasa8-Jan-04 11:07 
QuestionBest? PinmemberKluch15-Dec-03 19:34 
GeneralDES, Rijndael work, RC2 doesn't Pinmembercoulsong29-Oct-03 6:32 
GeneralError: data that has to be encrypted has the wrong length Pinmembertec-behind16-Sep-03 6:24 
GeneralRe: Error: data that has to be encrypted has the wrong length Pinmembercoar28-Jan-04 5:39 
GeneralRe: Error: data that has to be encrypted has the wrong length PinsussAnonymous23-Sep-05 2:06 
GeneralEncryption SymmetricAlgorithm Classes Pinmembermrieger12-Jun-03 10:20 
GeneralFrank Fang's latest code PinmemberRickyChen10-May-03 6:00 
GeneralRe: Frank Fang's latest code Pinmembercoolg4443-Apr-07 7:00 
GeneralRe: Frank Fang's latest code Pinmemberdjazzz19-Jun-07 2:08 
GeneralRe: Frank Fang's latest code Pinmemberlanger524718-Oct-07 11:47 
GeneralRe: Frank Fang's latest code Pinmemberctrlnick16-Jul-08 14:20 
GeneralImplementation with Rijndael does bad things in 0.5 % cases Pinmemberutunga5-May-03 5:48 
GeneralRe: (FIXES) Implementation with Rijndael does bad things in 0.5 % cases Pinmemberutunga5-May-03 6:17 
GeneralRe: (FIXES) Implementation with Rijndael does bad things in 0.5 % cases Pinmembersunroam200223-May-03 4:48 
GeneralEnhanced and working version here PinmemberWilliam M. Rawls6-Dec-02 9:33 
GeneralRe: Enhanced and working version here PinmemberWilliam M. Rawls6-Dec-02 9:35 
GeneralRe: Enhanced and working version here PinmemberIan V10-Dec-02 4:39 
GeneralRe: Enhanced and working version here PinmemberWilliam M. Rawls10-Dec-02 11:53 
GeneralRe: (Fix) Enhanced and working version here PinmemberBruno H. M. Oliveira21-Aug-03 9:58 
QuestionQ30701 links did not work? PinsussAnonymous12-Nov-02 15:47 
GeneralCryptoConfig PinsussSebastien Pouliot28-Sep-02 8:14 
GeneralFor all the VBers out there PinsussEdneeis22-Sep-02 19:47 
GeneralCryptography Error PinmemberAnonymous17-Jun-02 11:47 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 15 Mar 2002
Article Copyright 2002 by Frank Fang
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid