Как создать «обновляемый» класс шифрования - PullRequest
1 голос
/ 14 апреля 2009

Идея состоит в том, чтобы создать служебный класс, чтобы всякий раз, когда парни взламывали лучшие из известных в настоящее время алгоритмов, а новый выходил на рынок, единственная мысль, которую разработчик должен сделать, - это добавить класс NewHighTechEncryptingAlgorithm_Encryptor и изменить глобальное приложение. настройка для NewHighTechEncryptingAlgorithm_As_String

чтобы звонок был string myNewEncryptedString = Encryptor.Encrypt (StringToEncrypt, strAlgorithmName)

Редактировать: я удалил старый код и вставил ответ, предоставленный rwwilden, с кодом вызова

Я полагаю, что правильной формулировкой было бы «Enhashing», а не «Encryption», так как здесь не используется соль ... это, кажется, лучшее решение в соответствии с предложенными «specs»

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

 namespace GenApp.Utils.Security
 {

 /// <summary>
 /// Summary description for Encrypter
 /// </summary>
 public class Encrypter 
 {
 /// <summary>
 /// Encrypts according to the passed plain name for hasing algorithm
 /// see CryptoConfig class from MSDN for more details
 /// </summary>
 /// <param name="strPlainTxt">the plain text to encrypt</param>
 /// <param name="strAlgorithmName">The plain name of the hashing algorithm </param>
 /// <returns> the encrypted string </returns>
 public static string Encrypt ( string strPlainTxt, string strAlgorithmName )
 {
  string strHashedTxt = String.Empty;
  byte[] bytPlain = System.Text.Encoding.UTF8.GetBytes ( strPlainTxt );


  using (HashAlgorithm objAlgorithm = HashAlgorithm.Create ( strAlgorithmName ))
  {
   byte[] bytHash = objAlgorithm.ComputeHash ( bytPlain );
   strHashedTxt = Convert.ToBase64String ( bytHash );
   return strHashedTxt; 
  } 

 } //eof method 


 ///// OLD CODE - REQUIRES RECODING 
 ///// <summary>
 ///// Encrypts according to the passed plain name for hasing algorithm
 ///// see CryptoConfig class from MSDN for more details
 ///// </summary>
 ///// <param name="strPlainTxt">the plain text to encrypt</param>
 ///// <param name="strAlgorithmName">The plain name of the hashing algorithm </param>
 ///// <returns> the encrypted string </returns>
 //public static string Encrypt ( string strPlainTxt, string strAlgorithmName )
 //{
 //  string strHashedTxt = String.Empty;
 //  byte[] bytPlains = System.Text.Encoding.UTF8.GetBytes ( strPlainTxt );
 //  byte[] bytHash;
 //  //CryptoConfig objCryptoConfig = new CryptoConfig ();


 //  switch (strAlgorithmName)
 //  {
 //    case "SHA1":
 //      SHA1CryptoServiceProvider objProvForSHA1alg =
 //        (SHA1CryptoServiceProvider)CryptoConfig.CreateFromName ( strAlgorithmName );


 //      bytHash = objProvForSHA1alg.ComputeHash ( bytPlains );
 //      objProvForSHA1alg.Clear ();
 //      strHashedTxt = Convert.ToBase64String ( bytHash );

 //      break;
 //    case "MD5" :

 //      MD5CryptoServiceProvider objProvForMD5alg =
 //        (MD5CryptoServiceProvider)CryptoConfig.CreateFromName ( strAlgorithmName );

 //      bytHash = objProvForMD5alg.ComputeHash ( bytPlains );
 //      strHashedTxt = Convert.ToBase64String ( bytHash );
 //      objProvForMD5alg.Clear ();


 //      break; 

 //  } //eof switch

 //  if (String.IsNullOrEmpty ( strHashedTxt ))
 //    throw new Exception ( "Encryption provider called by invalide simple name " );


 //  return strHashedTxt;
 //} //eof method 


 } //eof class 


 class Program
 {
 static void Main ( string[] args )
 {
  string strPlainTxt = "UnEncryptedText";
  string strAlgorithmName = "SHA1"; //the type of al
  string strHashedTxt = String.Empty;

  //START WITH ONE ALGORITHM
  Console.WriteLine ( "Using the " + strAlgorithmName + " START " );
  Console.WriteLine ( "The plain text is " + strPlainTxt );
  Console.WriteLine ( "The encrypting algorithm is " + strAlgorithmName );
  strHashedTxt = Encrypter.Encrypt ( strPlainTxt, strAlgorithmName );
  Console.WriteLine ( "The hashed text is " + strHashedTxt );
  Console.WriteLine ( "Using the " + strAlgorithmName + " END " );

  //NOW CHANGE THE ALGORITHM
  strAlgorithmName = "MD5";
  Console.WriteLine ( "Using the " + strAlgorithmName + " START " );
  Console.WriteLine ( "The plain text is " + strPlainTxt );
  Console.WriteLine ( "The encrypting algorithm is " + strAlgorithmName );
  strHashedTxt = Encrypter.Encrypt ( strPlainTxt, strAlgorithmName );
  Console.WriteLine ( "The hashed text is " + strHashedTxt );
  Console.WriteLine ( "Using the " + strAlgorithmName + " END " );


  strAlgorithmName = "SHA256";
  Console.WriteLine ( "Using the " + strAlgorithmName + " START " );
  Console.WriteLine ( "The plain text is " + strPlainTxt );
  Console.WriteLine ( "The encrypting algorithm is " + strAlgorithmName );
  strHashedTxt = Encrypter.Encrypt ( strPlainTxt, strAlgorithmName );
  Console.WriteLine ( "The hashed text is " + strHashedTxt );
  Console.WriteLine ( "Using the " + strAlgorithmName + " END " );


  Console.WriteLine ( "Hit enter to exit" );
  Console.ReadLine ();
 }

 }
 } //eof namespace 

Ответы [ 3 ]

2 голосов
/ 14 апреля 2009

Вам следует взглянуть на класс CryptoConfig . Особенно метод CreateFromName . Он предоставляет способ получения криптографического алгоритма на основе имени (которое вы указали в своей конфигурации). Изменение имени в вашей конфигурации автоматически меняет используемый алгоритм.

Если вы сделали выбор в отношении использования симметричного или асимметричного шифрования, вам следует использовать более конкретные SymmetricAlgorithm.Create (string) или AsymmetricAlgorithm.Create (string) методы .

Поскольку вам требуется решение для хеширования, вы должны использовать HashAlgorithm.Create (string) . Причина для реализации этого, как я делаю ниже, заключается в том, что вам не нужно изменять какой-либо код, когда вы решаете использовать другой алгоритм хеширования. В вашем коде вы должны добавить еще один оператор case.

public static string Encrypt(string toEncrypt, string algorithmName)
{
    byte[] bytePlain = System.Text.Encoding.UTF8.GetBytes ( strPlainTxt );
    using (HashAlgorithm algorithm = HashAlgorithm.Create(algorithm))
    {
        byte[] byteHash = algorithm.ComputeHash(bytePlain);
        string strHashedTxt = Convert.ToBase64String (byteHash);
        return strHashedTxt;
    }
}
2 голосов
/ 14 апреля 2009

Я бы предложил копию Resharper или Coderush, чтобы исправить слепоту кодеров :) Подсветка скобок входит в комплект.

Кроме того, это классический или базовый интерфейс + фабричный шаблон. Как уже говорили другие, MEF и ICryptoTransform, скорее всего, самое чистое место для старта, поскольку фреймворк предоставляет его вам, но если вы хотите знать основы:

Сделать интерфейс:

public interface IEncrypter {
  string Encrypt(string plaintext);
}

затем реализуйте это:

public class MD5Encrypter : IEncrypter {
  public string Encrypt(string plaintext) {
    //code goes here.
  }
}

public class SHA1Encrypter : IEncrypter {
  public string Encrypt(string plaintext) {
    //code goes here.
  }
}

затем создайте фабрику:

public class EncryptionFactory {
  public static IEncrypter GetEncrypter() {
    //work out which one to return, maybe based on a config value?

    // I'm just going to return an MD5, but you'd want to use a switch statement etc
    // to decide which one to return.

    return new MD5Encrypter();
  }
}

И используйте это так:

IEncrypter encrypter = EncryptionFactory.GetEncrypter();
string garbageText = encrypter.Encrypt("Hello, world");

Все, что вы изменяете, это фабрика, или, что еще лучше, конфигурация, которую фабрика считывает, чтобы заставить ее использовать что-то еще. Черт возьми, вы можете основывать его на времени суток, если вы действительно хотите :) Код, который вы пишете и который использует интерфейс, не заботится о том, чем на самом деле является объект - он просто заботится о том, что имеет метод: string Encrypt (string).

MEF делает это для вас, в некотором смысле.

Использование интерфейсов также означает, что вы можете вернуть фиктивный поддельный IEncrypter, который ничего не делает, так что вы можете написать модульные тесты против него, фактически не выполняя шифрование. Не СУПЕР полезно в этом случае, но это хорошая практика в целом.

Кроме того, вы можете использовать предложение @ rwwilden в Factory для его генерации - вы читаете строку из config и используете асимметричный / симметричный метод создания, о котором он говорит, для создания базового класса .....

1 голос
/ 14 апреля 2009

Какой смысл в //eof class и //eof namespace корзине?

Для справки: то, что вы пытаетесь достичь, - это несколько ограниченная архитектура плагинов. См. MEF о том, как это можно сделать.

И, кстати, вам известно о ICryptoTransform ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...