Professional Applications Programmers/Consultants برمجة واستشارات تطبيقات الإنترنت
Skip Navigation LinksHome » Code Library » Encryption

Public general use code classes and xml files that we've compiled and used over the years:

Symmetric Key Algorithm (Rijndael/AES) to encrypt and decrypt data.

   1:  using System;
   2:  using System.Web;
   3:  using System.Xml;
   4:  using System.IO;
   5:  using System.Configuration;
   6:  using System.Text;
   7:  using System.Security.Cryptography;
   8:  using System.Security.Cryptography.X509Certificates;
   9:   
  10:  namespace Ia.Cl.Model.Cryptography
  11:  {
  12:      ////////////////////////////////////////////////////////////////////////////
  13:   
  14:      /// <summary publish="true">
  15:      /// Symmetric Key Algorithm (Rijndael/AES) to encrypt and decrypt data.
  16:      /// </summary>
  17:      /// <value>
  18:      /// Symmetric Key Algorithm (Rijndael/AES) to encrypt and decrypt data. As long as encryption and decryption routines use the same
  19:      /// parameters to generate the keys, the keys are guaranteed to be the same. The class uses static functions with duplicate code to make it easier to
  20:      /// demonstrate encryption and decryption logic. In a real-life application, this may not be the most efficient way of handling encryption, so - as
  21:      /// soon as you feel comfortable with it - you may want to redesign this class.
  22:      /// 
  23:      /// To create a new certificate (.NET Framework Tools Certificate Creation Tool (Makecert.exe) http://msdn.microsoft.com/en-us/library/bfsktky3(VS.71).aspx)
  24:      /// Do the following:
  25:      /// - "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\makecert" -r -pe -n "CN=Test Client Certificate" -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr CurrentUser -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
  26:      /// - Unless, that is, TLS-PSK, the Secure Remote Password (SRP) protocol, or some other protocol is used that can provide strong mutual authentication in the absence of certificates.
  27:      /// - In practice, you will hash the message beforehand (with hash algorithm such as MD5 or SHA1), obtaining the hashed message M1. Then you will encrypt M1 with your private key K0, digitally signing your message, and, finally, you will send your message M, the encrypted hash M1 (the signature) and the public key K1 to your recipient. Your recipient will compute the hash of your message M and will compare it with the decrypted value of M1. If the two hashes matches, the signature is valid.
  28:      /// - Launch the command "certmgr.msc" in Windows Start/Start Search to open the Certificate Manager.
  29:      /// - Double click a certifical file *.pfx to import it into the certificate store and you can use its public keys
  30:      /// For information see:
  31:      /// http://www.codeproject.com/KB/cs/Data_Encryption_Decryptio.aspx
  32:      /// http://www.grimes.demon.co.uk/workshops/secWSSixteen.htm
  33:      /// 
  34:      /// The other party should have a "public key certificate" that I import into my certificate store
  35:      /// 
  36:      /// Import a Certificate:
  37:      /// - You should only import certificates obtained from trusted sources. Importing an unreliable certificate could compromise the security of any system component that uses the imported certificate.
  38:      /// - You can import a certificate into any logical or physical store. In most cases, you will import certificates into the Personal store or the Trusted Root Certification Authorities store, depending on whether the certificate is intended for you or if it is a root CA certificate.
  39:      /// 
  40:      /// http://www.entrust.com/resources/pdf/cryptointro.pdf
  41:      /// - Add certificate name in web.config
  42:      /// </value>
  43:      /// <remarks> 
  44:      /// Copyright � 2001-2015 Jasem Y. Al-Shamlan (info@ia.com.kw), Internet Applications - Kuwait. All Rights Reserved.
  45:      ///
  46:      /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
  47:      /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  48:      ///
  49:      /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  50:      /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  51:      /// 
  52:      /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
  53:      /// 
  54:      /// Copyright notice: This notice may not be removed or altered from any source distribution.
  55:      /// </remarks> 
  56:      public class Encryption
  57:      {
  58:          static string certificateName = ConfigurationManager.AppSettings["certificateName"].ToString();
  59:   
  60:          ////////////////////////////////////////////////////////////////////////////
  61:   
  62:          /// <summary>
  63:          /// Encryption methods common to most applications - focus is on standard configuration using RSA symetric keys of 1024 bytes or higher.
  64:          /// </summary>
  65:          /// <remark link="http://www.grimes.demon.co.uk/workshops/secWSSixteen.htm"/>
  66:          /// <remark link="http://www.entrust.com/resources/pdf/cryptointro.pdf"/>
  67:          public Encryption() { }
  68:   
  69:          ////////////////////////////////////////////////////////////////////////////
  70:   
  71:          /// <summary>
  72:          ///
  73:          /// </summary>
  74:          /// <param name="data"></param>
  75:          /// <returns></returns>
  76:          /// </summary>
  77:          /// <remarks> </remarks>
  78:          public static string Sign(string data)
  79:          {
  80:              bool verify;
  81:              byte[] buffer, signature;
  82:              string s;
  83:              X509Certificate2 certificate;
  84:   
  85:              s = string.Empty;
  86:              certificate = null;
  87:   
  88:              certificate = GetCertificate(certificateName);
  89:   
  90:              if (certificate == null) { throw new Exception("No Certificate could be found in name " + certificateName); }
  91:              else
  92:              {
  93:                  if (certificate.HasPrivateKey)
  94:                  {
  95:                      // cast the privateKey object to a RSACryptoServiceProvider object, or, in more elegant way:
  96:                      RSACryptoServiceProvider privateKey = certificate.PrivateKey as RSACryptoServiceProvider;
  97:   
  98:                      // now a signature can be performed. To do so, the SignData method of the privateKey object can be used. It accepts, as input, (1) the data to sign, as array of bytes, and (2) the object that represents the hash algorithm to use:
  99:                      buffer = Encoding.Default.GetBytes(data);
 100:   
 101:                      signature = privateKey.SignData(buffer, new SHA1Managed());
 102:   
 103:                      // signature can also be verified. To do so you must utilize the public key of the certificate.
 104:                      RSACryptoServiceProvider publicKey = certificate.PublicKey.Key as RSACryptoServiceProvider;
 105:                      verify = publicKey.VerifyData(buffer, new SHA1Managed(), signature);
 106:   
 107:                      if (verify) s = Convert.ToBase64String(signature);
 108:                      else s = null;
 109:                  }
 110:                  else
 111:                  {
 112:                      throw new Exception("Certificate used for has no private key.");
 113:                  }
 114:              }
 115:   
 116:              s = "<dataSignature><data>" + data + "</data><signature>" + s + "</signature></dataSignature>";
 117:   
 118:              return s;
 119:          }
 120:   
 121:          ////////////////////////////////////////////////////////////////////////////
 122:   
 123:          /// <summary>
 124:          ///
 125:          /// </summary>
 126:          /// <param name="data"></param>
 127:          /// <param name="recipientCertificate"></param>
 128:          /// <returns></returns>
 129:          public static string Seal(string data, string recipientCertificate)
 130:          {
 131:              string s, cipher, key, iv;
 132:              X509Certificate2 certificate;
 133:   
 134:              s = key = iv = string.Empty;
 135:              certificate = null;
 136:   
 137:              System.Security.Cryptography.Rijndael r = System.Security.Cryptography.Rijndael.Create();
 138:   
 139:              cipher = global::Ia.Cl.Model.Cryptography.Rijndael.Encrypt(data, r.Key, r.IV);
 140:   
 141:              certificate = GetCertificate(recipientCertificate);
 142:   
 143:              if (certificate == null) { throw new Exception("No Certificate could be found in name " + recipientCertificate); }
 144:              else
 145:              {
 146:                  byte[] cipher_byte;
 147:   
 148:                  using (var rsa = (RSACryptoServiceProvider)certificate.PublicKey.Key)
 149:                  {
 150:                      cipher_byte = rsa.Encrypt(r.Key, false);
 151:                      key = Convert.ToBase64String(cipher_byte);
 152:   
 153:                      cipher_byte = rsa.Encrypt(r.IV, false);
 154:                      iv = Convert.ToBase64String(cipher_byte);
 155:                  }
 156:              }
 157:   
 158:              return s = "<cipherSymmetricKey><cipher>" + cipher + "</cipher><symmetricKey><key>" + key + "</key><iv>" + iv + "</iv></symmetricKey></cipherSymmetricKey>";
 159:          }
 160:   
 161:          ////////////////////////////////////////////////////////////////////////////
 162:   
 163:          /// <summary>
 164:          ///
 165:          /// </summary>
 166:          /// <param name="data"></param>
 167:          /// <returns></returns>
 168:          public static void Deliver(string data)
 169:          {
 170:              // send data 
 171:          }
 172:   
 173:          ////////////////////////////////////////////////////////////////////////////
 174:   
 175:          /// <summary>
 176:          ///
 177:          /// </summary>
 178:          /// <returns></returns>
 179:          public static string Accept()
 180:          {
 181:              // accept data 
 182:              string s;
 183:   
 184:              s = null;
 185:   
 186:              return s;
 187:          }
 188:   
 189:          ////////////////////////////////////////////////////////////////////////////
 190:   
 191:          /// <summary>
 192:          ///
 193:          /// </summary>
 194:          /// <param name="data"></param>
 195:          /// <returns></returns>
 196:          public static string Open(string data)
 197:          {
 198:              byte[] key_, iv_;
 199:              string s, cipher, key, iv;
 200:              XmlDocument xd;
 201:              X509Certificate2 certificate;
 202:   
 203:              key_ = iv_ = null;
 204:              s = string.Empty;
 205:              certificate = null;
 206:   
 207:              certificate = GetCertificate(certificateName);
 208:   
 209:              xd = new XmlDocument();
 210:   
 211:              xd.LoadXml(data);
 212:   
 213:              cipher = xd.SelectSingleNode("cipherSymmetricKey/cipher").InnerText;
 214:              key = xd.SelectSingleNode("cipherSymmetricKey/symmetricKey/key").InnerText;
 215:              iv = xd.SelectSingleNode("cipherSymmetricKey/symmetricKey/iv").InnerText;
 216:   
 217:              if (certificate == null) { throw new Exception("No Certificate could be found in name " + certificateName); }
 218:              else
 219:              {
 220:                  key_ = Convert.FromBase64String(key);
 221:                  iv_ = Convert.FromBase64String(iv);
 222:   
 223:                  using (var rsa = (RSACryptoServiceProvider)certificate.PrivateKey)
 224:                  {
 225:                      key_ = rsa.Decrypt(key_, false);
 226:                      iv_ = rsa.Decrypt(iv_, false);
 227:                  }
 228:              }
 229:   
 230:              System.Security.Cryptography.Rijndael r = System.Security.Cryptography.Rijndael.Create();
 231:   
 232:              s = global::Ia.Cl.Model.Cryptography.Rijndael.Decrypt(cipher, key_, iv_);
 233:   
 234:              return s;
 235:          }
 236:   
 237:          ////////////////////////////////////////////////////////////////////////////
 238:   
 239:          /// <summary>
 240:          ///
 241:          /// </summary>
 242:          /// <param name="data"></param>
 243:          /// <returns></returns>
 244:          public static string Verify(string data)
 245:          {
 246:              bool verify;
 247:              byte[] buffer, si;
 248:              string s, u, signature;
 249:              XmlDocument xd;
 250:              X509Certificate2 certificate;
 251:   
 252:              s = string.Empty;
 253:              certificate = null;
 254:   
 255:              certificate = GetCertificate(certificateName);
 256:   
 257:              xd = new XmlDocument();
 258:   
 259:              xd.LoadXml(data);
 260:   
 261:              u = xd.SelectSingleNode("dataSignature/data").InnerText;
 262:              signature = xd.SelectSingleNode("dataSignature/signature").InnerText;
 263:   
 264:              if (certificate == null) { throw new Exception("No Certificate could be found in name " + certificateName); }
 265:              else
 266:              {
 267:                  // cast the publicKey object to a RSACryptoServiceProvider object, or, in more elegant way:
 268:                  RSACryptoServiceProvider publiceKey = certificate.PublicKey.Key as RSACryptoServiceProvider;
 269:   
 270:                  // now a signature can be performed. To do so, the SignData method of the privateKey object can be used. It accepts, as input, (1) the data to sign, as array of bytes, and (2) the object that represents the hash algorithm to use:
 271:                  buffer = Encoding.Default.GetBytes(u);
 272:   
 273:                  //si = Encoding.Default.GetBytes(signature);
 274:                  si = Convert.FromBase64String(signature);
 275:   
 276:                  verify = publiceKey.VerifyData(buffer, new SHA1Managed(), si);
 277:              }
 278:   
 279:              s = "<data>" + u + "</data>";
 280:   
 281:              return s;
 282:          }
 283:   
 284:          ////////////////////////////////////////////////////////////////////////////
 285:   
 286:          /// <summary>
 287:          /// Encrypted the specified data.
 288:          /// </summary>
 289:          /// <param name="data">The bytes to encrypt</param>
 290:          /// <returns>Returns the encrypted bytes.</returns>
 291:          public static string Encrypt(string data)
 292:          {
 293:              string s;
 294:              X509Certificate2 certificate;
 295:   
 296:              s = string.Empty;
 297:              certificate = null;
 298:   
 299:              certificate = GetCertificate(certificateName);
 300:   
 301:              if (certificate == null) { throw new Exception("No Certificate could be found in name " + certificateName); }
 302:              else
 303:              {
 304:                  try
 305:                  {
 306:                      string PlainString = data.Trim();
 307:                      byte[] cipherbytes = ASCIIEncoding.ASCII.GetBytes(PlainString);
 308:                      byte[] cipher;
 309:   
 310:                      using (var rsa = (RSACryptoServiceProvider)certificate.PublicKey.Key) cipher = rsa.Encrypt(cipherbytes, false);
 311:   
 312:                      s = Convert.ToBase64String(cipher);
 313:                  }
 314:                  catch (Exception e)
 315:                  {
 316:                      throw e;
 317:                  }
 318:              }
 319:   
 320:              return s;
 321:          }
 322:   
 323:          ////////////////////////////////////////////////////////////////////////////
 324:   
 325:          /// <summary>
 326:          /// Decrypts the bytes specified.
 327:          /// </summary>
 328:          /// <param name="data">The bytes to decrypt</param>
 329:          /// <returns>Returns the decrypted bytes.</returns>
 330:          public static string Decrypt(string data)
 331:          {
 332:              string s;
 333:              X509Certificate2 certificate;
 334:   
 335:              s = string.Empty;
 336:              certificate = null;
 337:   
 338:              certificate = GetCertificate(certificateName);
 339:   
 340:              if (certificate == null) { throw new Exception("No Certificate could be found in name " + certificateName); }
 341:              else
 342:              {
 343:                  try
 344:                  {
 345:                      byte[] cipherbytes = Convert.FromBase64String(data);
 346:   
 347:                      if (certificate.HasPrivateKey)
 348:                      {
 349:                          byte[] plainbytes;
 350:   
 351:                          using (RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PrivateKey) plainbytes = rsa.Decrypt(cipherbytes, false);
 352:   
 353:                          System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
 354:   
 355:                          s = enc.GetString(plainbytes);
 356:                      }
 357:                      else
 358:                      {
 359:                          throw new Exception("Certificate used for has no private key.");
 360:                      }
 361:                  }
 362:                  catch (Exception e)
 363:                  {
 364:                      throw e;
 365:                  }
 366:              }
 367:   
 368:              return s;
 369:          }
 370:   
 371:          ////////////////////////////////////////////////////////////////////////////
 372:   
 373:          /// <summary>
 374:          /// Return the certificate in X509Certificate2 format from its string name
 375:          /// </summary>
 376:          /// <param name="name">Certificate name</param>
 377:          /// <returns>Certificate</returns>
 378:          private static X509Certificate2 GetCertificate(string name)
 379:          {
 380:              X509Store store;
 381:              X509Certificate2 certificate;
 382:   
 383:              certificate = null;
 384:   
 385:              store = new X509Store(StoreName.My);
 386:              store.Open(OpenFlags.ReadWrite);
 387:   
 388:              if (name.Length > 0)
 389:              {
 390:                  foreach (X509Certificate2 cert in store.Certificates)
 391:                  {
 392:                      if (cert.SubjectName.Name.Contains(name))
 393:                      {
 394:                          certificate = cert;
 395:                          break;
 396:                      }
 397:                  }
 398:              }
 399:              else
 400:              {
 401:                  certificate = store.Certificates[0];
 402:              }
 403:   
 404:              return certificate;
 405:          }
 406:   
 407:          ////////////////////////////////////////////////////////////////////////////
 408:          ////////////////////////////////////////////////////////////////////////////
 409:      }
 410:   
 411:      ////////////////////////////////////////////////////////////////////////////
 412:      ////////////////////////////////////////////////////////////////////////////
 413:   
 414:      /// <summary>
 415:      /// This class uses a symmetric key algorithm (Rijndael/AES) to encrypt and decrypt data. As long as encryption and decryption routines use the same
 416:      /// parameters to generate the keys, the keys are guaranteed to be the same. The class uses static functions with duplicate code to make it easier to
 417:      /// demonstrate encryption and decryption logic. In a real-life application, this may not be the most efficient way of handling encryption, so - as
 418:      /// soon as you feel comfortable with it - you may want to redesign this class.
 419:      /// </summary>
 420:      public class Rijndael
 421:      {
 422:          ////////////////////////////////////////////////////////////////////////////
 423:          ////////////////////////////////////////////////////////////////////////////
 424:   
 425:          /// <summary>
 426:          /// Encrypts specified plaintext using Rijndael symmetric key algorithm
 427:          /// and returns a base64-encoded result.
 428:          /// </summary>
 429:          /// <param name="plainText">
 430:          /// Plaintext value to be encrypted.
 431:          /// </param>
 432:          /// <param name="initVectorBytes">
 433:          /// Initialization vector (or IV). This value is required to encrypt the first block of plaintext data. For RijndaelManaged class IV must be exactly 16 ASCII characters long.
 434:          /// </param>
 435:          /// <param name="keyBytes"></param>
 436:          /// <returns>
 437:          /// Encrypted value formatted as a base64-encoded string.
 438:          /// </returns>
 439:          public static string Encrypt(string plainText, byte[] keyBytes, byte[] initVectorBytes)
 440:          {
 441:              // convert our plaintext into a byte array. Let us assume that plaintext contains UTF8-encoded characters.
 442:              byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
 443:              string cipher;
 444:   
 445:              // create uninitialized Rijndael encryption object.
 446:              RijndaelManaged symmetricKey = new RijndaelManaged();
 447:   
 448:              // It is reasonable to set encryption mode to Cipher Block Chaining (CBC). Use default options for other symmetric key parameters.
 449:              symmetricKey.Mode = CipherMode.CBC;
 450:   
 451:              // Generate encryptor from the existing key bytes and initialization vector. Key size will be defined based on the number of the key bytes.
 452:              ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
 453:   
 454:              // Define memory stream which will be used to hold encrypted data.
 455:              using (MemoryStream memoryStream = new MemoryStream())
 456:              {
 457:                  // Define cryptographic stream (always use Write mode for encryption).
 458:                  using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
 459:                  {
 460:                      // Start encrypting.
 461:                      cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
 462:   
 463:                      // Finish encrypting.
 464:                      cryptoStream.FlushFinalBlock();
 465:   
 466:                      // Convert our encrypted data from a memory stream into a byte array.
 467:                      byte[] cipherTextBytes = memoryStream.ToArray();
 468:   
 469:                      // Convert encrypted data into a base64-encoded string.
 470:                      cipher = Convert.ToBase64String(cipherTextBytes);
 471:   
 472:                      //cryptoStream.Close();
 473:                  }
 474:   
 475:                  //memoryStream.Close();
 476:              }
 477:   
 478:              // Return encrypted string.
 479:              return cipher;
 480:          }
 481:   
 482:          ////////////////////////////////////////////////////////////////////////////
 483:   
 484:          /// <summary>
 485:          /// Decrypts specified ciphertext using Rijndael symmetric key algorithm.
 486:          /// </summary>
 487:          /// <param name="cipher">
 488:          /// Base64-formatted ciphertext value.
 489:          /// </param>
 490:          /// <param name="initVectorBytes">
 491:          /// Initialization vector (or IV). This value is required to encrypt the first block of plaintext data. For RijndaelManaged class IV must be exactly 16 ASCII characters long.
 492:          /// </param>
 493:          /// <param name="keyBytes"></param>
 494:          /// <returns>
 495:          /// Decrypted string value.
 496:          /// </returns>
 497:          /// </summary>
 498:          /// <remarks> 
 499:          /// Most of the logic in this function is similar to the Encrypt logic. In order for decryption to work, all parameters of this function
 500:          /// - except cipher value - must match the corresponding parameters of the Encrypt function which was called to generate the ciphertext.
 501:          /// </remarks>
 502:          public static string Decrypt(string cipher, byte[] keyBytes, byte[] initVectorBytes)
 503:          {
 504:              // Convert our ciphertext into a byte array.
 505:              byte[] cipherTextBytes = Convert.FromBase64String(cipher);
 506:              string plainText;
 507:   
 508:              // Create uninitialized Rijndael encryption object.
 509:              RijndaelManaged symmetricKey = new RijndaelManaged();
 510:   
 511:              // It is reasonable to set encryption mode to Cipher Block Chaining (CBC). Use default options for other symmetric key parameters.
 512:              symmetricKey.Mode = CipherMode.CBC;
 513:   
 514:              // Generate decryptor from the existing key bytes and initialization vector. Key size will be defined based on the number of the key bytes.
 515:              ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
 516:   
 517:              // Define memory stream which will be used to hold encrypted data.
 518:              using (MemoryStream memoryStream = new MemoryStream(cipherTextBytes))
 519:              {
 520:                  // Define cryptographic stream (always use Read mode for encryption).
 521:                  using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
 522:                  {
 523:                      // Since at this point we don't know what the size of decrypted data will be, allocate the buffer long enough to hold ciphertext; plaintext is never longer than ciphertext.
 524:                      byte[] plainTextBytes = new byte[cipherTextBytes.Length];
 525:   
 526:                      // Start decrypting.
 527:                      int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
 528:   
 529:                      // Convert decrypted data into a string. Let us assume that the original plaintext string was UTF8-encoded.
 530:                      plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
 531:   
 532:                      // Close both streams.
 533:                      //cryptoStream.Close();
 534:                  }
 535:   
 536:                  //memoryStream.Close();
 537:              }
 538:   
 539:              // Return decrypted string.   
 540:              return plainText;
 541:          }
 542:   
 543:          /*
 544:          ////////////////////////////////////////////////////////////////////////////
 545:  
 546:          /// <summary>
 547:          ///
 548:          /// </summary>
 549:          /// <returns></returns>
 550:          public static byte[] Password()
 551:          {
 552:              /// <param name="passPhrase">
 553:              /// Passphrase from which a pseudo-random password will be derived. The
 554:              /// derived password will be used to generate the encryption key.
 555:              /// Passphrase can be any string. In this example we assume that this
 556:              /// passphrase is an ASCII string.
 557:              /// </param>
 558:              /// <param name="saltValue">
 559:              /// Salt value used along with passphrase to generate password. Salt can
 560:              /// be any string. In this example we assume that salt is an ASCII string.
 561:              /// </param>
 562:              /// <param name="hashAlgorithm">
 563:              /// Hash algorithm used to generate password. Allowed values are: "MD5" and
 564:              /// "SHA1". SHA1 hashes are a bit slower, but more secure than MD5 hashes.
 565:              /// </param>
 566:              /// <param name="passwordIterations">
 567:              /// Number of iterations used to generate password. One or two iterations
 568:              /// should be enough.
 569:              /// </param>
 570:              /// <param name="keySize">
 571:              /// Size of encryption key in bits. Allowed values are: 128, 192, and 256.
 572:              /// Longer keys are more secure than shorter keys.
 573:              /// </param>
 574:  
 575:              string passPhrase = "*";        // can be any string
 576:              string saltValue = "*";        // can be any string
 577:              string hashAlgorithm = "SHA1";             // can be "MD5"
 578:              int passwordIterations = 2;                  // can be any number
 579:              int keySize = 256;                // can be 192 or 128
 580:  
 581:              // Convert strings defining encryption key characteristics into byte
 582:              // arrays. Let us assume that strings only contain ASCII codes.
 583:              // If strings include Unicode characters, use Unicode, UTF7, or UTF8
 584:              // encoding.
 585:              byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
 586:  
 587:              // First, we must create a password, from which the key will be 
 588:              // derived. This password will be generated from the specified 
 589:              // passphrase and salt value. The password will be created using
 590:              // the specified hash algorithm. Password creation can be done in
 591:              // several iterations.
 592:              PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);
 593:  
 594:              // Use the password to generate pseudo-random bytes for the encryption
 595:              // key. Specify the size of the key in bytes (instead of bits).
 596:              byte[] keyBytes = password.GetBytes(keySize / 8);
 597:  
 598:              return keyBytes;
 599:          }
 600:          */
 601:   
 602:          ////////////////////////////////////////////////////////////////////////////
 603:          ////////////////////////////////////////////////////////////////////////////
 604:      }
 605:   
 606:      ////////////////////////////////////////////////////////////////////////////
 607:      ////////////////////////////////////////////////////////////////////////////
 608:   
 609:      /// <summary>
 610:      /// 
 611:      /// </summary>
 612:      public class Md5
 613:      {
 614:          ////////////////////////////////////////////////////////////////////////////
 615:   
 616:          /// <summary>
 617:          /// 
 618:          /// </summary>
 619:          public static string Hash(string text)
 620:          {
 621:              // hash an input string and return the hash as a 32 character hexadecimal string
 622:   
 623:              byte[] data;
 624:              StringBuilder sb;
 625:              MD5 md5;
 626:   
 627:              sb = new StringBuilder();
 628:              md5 = MD5.Create();
 629:   
 630:              // convert the input string to a byte array and compute the hash
 631:              data = md5.ComputeHash(Encoding.Default.GetBytes(text));
 632:   
 633:              // loop through each byte of the hashed data and format each one as a hexadecimal string
 634:              for (int i = 0; i < data.Length; i++) sb.Append(data[i].ToString("x2"));
 635:   
 636:              return sb.ToString();
 637:          }
 638:   
 639:          ////////////////////////////////////////////////////////////////////////////
 640:          ////////////////////////////////////////////////////////////////////////////
 641:      }
 642:   
 643:      ////////////////////////////////////////////////////////////////////////////
 644:      ////////////////////////////////////////////////////////////////////////////
 645:  }
 646: