2015-01-22 5 views
-2

(Подход №2) Мне нужно создать механизм активации программного обеспечения. Итак, я закончил с этой схемой: приложение создает уникальный идентификатор, основанный на аппаратном обеспечении компьютера. Покупатель отправляет мне этот идентификатор. Я подписываю его своим личным ключом, и я отправляю обратно подписанную строку. Приложение проверяет строку (декодирует ее с помощью открытого ключа и сравнивает ее с идентификатором оборудования).RSA подписывается на C# для лицензирования

До сих пор я закончил с идентификатором оборудования, и я создал ключи (1024 бит) с openssl, это два файла private.pem и public.pem.

Я попытался применить решение, описанное в http://www.christian-etter.de/?p=771 , но проверка всегда терпит неудачу.

Код:

private void Generate_Click(object sender, EventArgs e) 
    { 
     byte[] SignedData; 
     byte[] UnsignedData = Encoding.UTF8.GetBytes(CompID.Text); 

     using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) 
     { 
      rsa.PersistKeyInCsp = false; 
      rsa.LoadPrivateKeyPEM(PrivateKey.Text); 
      using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 
       SignedData = rsa.SignData(UnsignedData, sha1); 
      ActCode.Text = Encoding.UTF8.GetString(SignedData, 0, SignedData.Length); 
     } 
    } 

    //-------------------------------------------------------------------- 

    private void Verify_Click(object sender, EventArgs e) 
    { 
     byte[] UnsignedData = Encoding.UTF8.GetBytes(CompID.Text); 
     byte[] SignedData = Encoding.UTF8.GetBytes(ActCode.Text); 
     bool VerifOK; 

     using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) 
     { 
      rsa.PersistKeyInCsp = false; 
      rsa.LoadPublicKeyPEM(PublicKey.Text); 
      using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 
       VerifOK = rsa.VerifyData(UnsignedData, sha1, SignedData); 
     } 
     if (VerifOK) verif.Text = "verification ok"; 
     else verif.Text = "verification error"; 
    } 
+0

Не смотрите на это подробно, но тот факт, что ваш код кажется более кавалером для перехода на UTF-8 или хранения в текстовом поле, означает, что вы, вероятно, неосознанно изменяете байты. Переход туда и обратно из строки в 'byte []' опасен, если вы не очень осторожны. Попытайтесь сохранить данные как 'byte []', если это вообще возможно. –

+0

Не все байтовые последовательности являются действительными кодировками UTF-8. Используйте кодировку Base64 через 'Convert.To/FromBase64String' для обработки' SignedData'. –

+0

@mikez Спасибо большое! Я пропустил это. Это сделал трюк! – monica

ответ

1

Вы лечите некоторые произвольные байты как UTF-8 закодированной строки (SignedData) Это неверно, потому что не все последовательности байтов действительны. Я подозреваю, что кодер выбрасывает недопустимые байты, в результате чего проверка завершается с ошибкой. Вы должны использовать кодировку Base64 для сохранения двоичных данных в строчном формате, не теряя ничего. Так что это:

using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 
    SignedData = rsa.SignData(UnsignedData, sha1); 
ActCode.Text = Encoding.UTF8.GetString(SignedData, 0, SignedData.Length); 

становится

using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 
    SignedData = rsa.SignData(UnsignedData, sha1); 
ActCode.Text = Convert.ToBase64String(SignedData); 

Аналогично во время проверки вам нужно использовать Convert.FromBase64String, чтобы получить SignedData. Хорошо использовать UTF-8 для CompID, потому что это строковые данные, которые вам нужно преобразовать в двоичную форму для подписания.