Как защитить серийник при помощи RSACryptoServiceProvide
От: Streamer1 Украина  
Дата: 06.06.06 22:10
Оценка: 24 (5)
#Имя: FAQ.dotnet.RSACrypto.keygen
Здравствуйте, H.P. Baxxter, Вы писали:

HPB>sn должен шифроваться закрытым ключом, и дешифроваться открытым непосредственно при активации. Это возможно при помощи RSACryptoServiceProvider — у меня он ну никак не хочет шифровать закрытым ключом, только открытым. ??? Можно ли поставленную задачу решить средствами FCL без собственной реализации RSA?


непонятно зачем шифровать серийник, если расшифровать его сможет каждый
ты уж поверь что если речь дойдет до расшифровки то открытый ключ который ты наверняка хочешь спрятать в коде уже известен...

по поводу надежных серийников — можно реализовывать так:

1. Разработчик формирует пару ключей открытый/закрытый: publicKey/privateKey
publicKey встраивается в софтину, privateKey в кейген, причем последний нежно прижимая к груди прячет в сейф...

  private static string publicKey  = @"<RSAKeyValue><Modulus>s2nF3YcI+jaRcdtfWbVmkWbN2own5Jb4XOLbvwZYMqTLZA40rn2CVRj//66N2La+ay8Zg0Hjil7hXZGkC0ujTYecdGhPnyAH7TC3A7Ksz+kg2z32N5vgk+ZpVIiU+9wi83fsD5Ojk8QuTlYiQpyxWI66d5h6I7BoWmhnmeM2YPk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
  private static string privateKey  = @"<RSAKeyValue><Modulus>s2nF3YcI+jaRcdtfWbVmkWbN2own5Jb4XOLbvwZYMqTLZA40rn2CVRj//66N2La+ay8Zg0Hjil7hXZGkC0ujTYecdGhPnyAH7TC3A7Ksz+kg2z32N5vgk+ZpVIiU+9wi83fsD5Ojk8QuTlYiQpyxWI66d5h6I7BoWmhnmeM2YPk=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";



2. Разработчик самоуверенно вводит такой текст в кейгене:

Product=Super Puper Mega Software System
LicenseType=FULL
MegaAddress=http://www.supermegasoft.medved.preved.net
UserName=Медвед


3. Кейген подписывает текст с помощью закрытого ключа и получается такой текст:

Product=Super Puper Mega Software System
LicenseType=FULL
MegaAddress=http://www.supermegasoft.medved.preved.net
UserName=Медвед
SuperPuperSignature=DKGEA8FVCEC3CHGIENFRCDFQDOFTE9GRB9AECIENAIEKGHCYABA8ECEUB5GSE1AQBOCCFRBZENAODYBQEUCBCYCEACE0DGFJE7BZG4DOEYEMF2D3G2B3BPB0BKG4C7EMGHDHB8D1FOF8FMF0BDBYEHENGJE4GED8CIGMCNFPE0ETFFCUCPA6BPBPF6CADKFCERAGF0AEEIB5AGGBA8CHGHESGJBVGYDJDJEJFIBEAAGLGQA5AICCE0AVDRFWCOGE


4. Кейген заворачивает весь этот текст в сериал нумбер, примерно такого содержания:

{CIEXADGACIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAC7
ACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB
9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJA
AB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB
7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AA
BCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5
AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAA
B8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACP
AAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AA
CJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5
AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB
7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEA
AB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AAC
FAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5A
ACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB
6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIA
AB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACL
AAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AA
CEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9
AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAA
B5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AABCIAAB5AAB7AAB6AACJAAB5AACPAAB9AACFAAB8AACEAAB5AACLAAB7AAB9AABTAAB7A
AB9AAB7AAB8AAB3AACOAAB3AACFAAB7AACAAAB3AACPAAB3AAB3AAB8AABSAAAKAA}


5. Разработчик высокомерно продает полученную абракадабру за вожделенную денюжку



Что происходит у юзверя:

1. Юзверь расставшись с денюжкой некоторое время горюет и оплакивает их крокодиловыми слезами, потом наконец успокаивается и вводит сериал нумбер в софтине

2. Софтина раскручивает абракадабру в текст:

Product=Super Puper Mega Software System
LicenseType=FULL
MegaAddress=http://www.supermegasoft.medved.preved.net
UserName=Медвед
SuperPuperSignature=DKGEA8FVCEC3CHGIENFRCDFQDOFTE9GRB9AECIENAIEKGHCYABA8ECEUB5GSE1AQBOCCFRBZENAODYBQEUCBCYCEACE0DGFJE7BZG4DOEYEMF2D3G2B3BPB0BKG4C7EMGHDHB8D1FOF8FMF0BDBYEHENGJE4GED8CIGMCNFPE0ETFFCUCPA6BPBPF6CADKFCERAGF0AEEIB5AGGBA8CHGHESGJBVGYDJDJEJFIBEAAGLGQA5AICCE0AVDRFWCOGE


3. Софтина убирает строчку с SuperPuperSignature и проверяет подлинность оставшегося текста с помощью открытого ключа в теле программы и подписи из SuperPuperSignature, если текст оказался подлиным он юзается для разблокировки софта в нужный режим, а юзверь счастливо улыбается увидев заветную надпись "Поздравляем!!! Супермегасофт система зарегистрирована для юзверя: Медвед"

Алгоритмы заворачивания/разворачивания текста и ключа в ASCII абракадабру:
      private static string alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

// заворачивание:
      public static string EncodeLicenseKey(string licenseKey, bool split)
      {
         return ("{" + Encode(Encoding.Unicode.GetBytes(licenseKey), split) + "}");
      }

      public static string Encode(byte[] bytes, bool split)
      {
         StringBuilder builder = new StringBuilder();
         if (bytes != null)
         {
            for (int i = 0; i < bytes.Length; i++)
            {
               if ((split && ((i % 0x20) == 0)) && (i > 0))
               {
                  builder.Append("\r\n");
               }
               builder.Append(alphabet[bytes[i] / alphabet.Length]);
               builder.Append(alphabet[bytes[i] % alphabet.Length]);
            }
         }
         return builder.ToString();
      }

// разворачивание:
      public static string DecodeLicenseKey(string text)
      {
         StringBuilder builder = new StringBuilder();
         bool flag = false;
         for (int i = 0; i < text.Length; i++)
         {
            if (!flag && (text[i] == '{'))
               flag = true;
            else
            {
               if (text[i] == '}')
                  break;
               if (alphabet.IndexOf(text[i]) != -1)
                  builder.Append(text[i]);
            }
         }
         return Encoding.Unicode.GetString(Decode(builder.ToString()));
      }

      public static byte[] Decode(string text)
      {
         if (text == null)
         {
            text = string.Empty;
         }
         byte[] buffer = new byte[text.Length / 2];
         for (int i = 0; i < (buffer.Length * 2); i += 2)
         {
            buffer[i / 2] = (byte)((alphabet.IndexOf(text[i]) * alphabet.Length) + alphabet.IndexOf(text[i + 1]));
         }
         return buffer;
      }


Проверка подписи производится так:
      public static bool CheckLicenseSign(string licenseText, string signText, string publicKey)
      {
         byte[] buffer1 = Decode(signText);
         RSACryptoServiceProvider provider = new RSACryptoServiceProvider(0x400);
         provider.FromXmlString(publicKey);
         byte[] buffer2 = Encoding.Unicode.GetBytes(licenseText);
         SHA1 sha = new SHA1CryptoServiceProvider();
         byte[] buffer3 = sha.ComputeHash(buffer2);
         RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(provider);
         deformatter.SetHashAlgorithm("SHA1");
         return deformatter.VerifySignature(buffer3, buffer1);
      }


Подпись в кейгене производится так:
   private void buttonSign_Click(object sender, EventArgs e)
   {
// ....<skip>...
      licenseText = GetSuperLicenseText(collection);

      byte[] buffer2 = Encoding.Unicode.GetBytes(licenseText);
      RSACryptoServiceProvider myprov = new RSACryptoServiceProvider(0x400);
      myprov.FromXmlString(privateKey);
      SHA1 sha1 = new SHA1CryptoServiceProvider();
      byte[] buffer3 = sha1.ComputeHash(buffer2);

      RSAPKCS1SignatureFormatter formatter1 = new RSAPKCS1SignatureFormatter(myprov);
      formatter1.SetHashAlgorithm("SHA1");
      byte[] buffer1 = formatter1.CreateSignature(buffer3);

      string mysign = Encode(buffer1, false);        // получили подпись

      licenseLines.Add("SuperPuperSignature=" + mysign);        // добавили строчку с подписью

// ...<skip>
   }


писалось все это весьма давно, так что чтото мог и забыть, но вроде все описал...

подбор ключа имхо невозможен, шифровать ничё не надо
так что не заморачивайтесь

P.S.: все имена, названия, public/private ключи вымышленные, ключи юзабельные но нигде не использовались, сериал формировался Copy/Paste мусора, более подробно описывать лень...
Тот кто говорит не знает, тот кто знает не говорит.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.