2013-03-29 3 views
9

Я был над статьей в CodeProject а на некоторое время, что объясняет, как зашифровать и расшифровать с помощью поставщика RSA:ключ шифрования Public с RSACryptoServiceProvider

RSA Private Key Encryption

Хотя старая версия с 2009 года был багги, новая версия 2012 года (с поддержкой System.Numerics.BigInteger) кажется более надежной. Что в этой версии не хватает, хотя это способ зашифровать с ключом общественного и расшифровка с помощью ключа частного.

Итак, я попробовал это сам, но получаю мусор, когда дешифрую. Я не знаком с провайдером RSA, поэтому я здесь в темноте. Трудно найти больше информации о том, как это должно работать.

Кто-нибудь видит, что в этом плохого? Ниже ШИФРОВАНИЕ с открытым ключом:

// Add 4 byte padding to the data, and convert to BigInteger struct 
BigInteger numData = GetBig(AddPadding(data)); 
RSAParameters rsaParams = rsa.ExportParameters(false); 
//BigInteger D = GetBig(rsaParams.D); //only for private key 
BigInteger Exponent = GetBig(rsaParams.Exponent); 
BigInteger Modulus = GetBig(rsaParams.Modulus); 
BigInteger encData = BigInteger.ModPow(numData, Exponent, Modulus);  
return encData.ToByteArray(); 

ли я использовать большой «D» от поставщика, когда я это делаю? Наверное, нет, поскольку это открытый ключ, который не имеет «D».

Тогда аналог (дешифрования с помощью закрытого ключа):

BigInteger numEncData = new BigInteger(cipherData); 

RSAParameters rsaParams = rsa.ExportParameters(true); 
BigInteger D = GetBig(rsaParams.D); 
//BigInteger Exponent = GetBig(rsaParams.Exponent); 
BigInteger Modulus = GetBig(rsaParams.Modulus); 

BigInteger decData = BigInteger.ModPow(numEncData, D, Modulus); 

byte[] data = decData.ToByteArray(); 
byte[] result = new byte[ data.Length - 1 ]; 
Array.Copy(data, result, result.Length); 
result = RemovePadding(result); 

Array.Reverse(result); 
return result; 

мне нужен "D" или экспоненту здесь делать?

Очевидно, мне нужен криптографический режим для работы в частном порядке публично-частный. Любая помощь очень ценится!

ответ

10

вот вам пример:

public static void rsaPlayground() 
    { 
     byte[] data = new byte[] { 1, 2, 3, 4, 5 }; 
     RSACryptoServiceProvider csp = new RSACryptoServiceProvider();//make a new csp with a new keypair 
     var pub_key = csp.ExportParameters(false); // export public key 
     var priv_key = csp.ExportParameters(true); // export private key 

     var encData = csp.Encrypt(data, false); // encrypt with PKCS#1_V1.5 Padding 
     var decBytes = MyRSAImpl.plainDecryptPriv(encData, priv_key); //decrypt with own BigInteger based implementation 
     var decData = decBytes.SkipWhile(x => x != 0).Skip(1).ToArray();//strip PKCS#1_V1.5 padding 

    } 

    public class MyRSAImpl 
    { 

     private static byte[] rsaOperation(byte[] data, BigInteger exp, BigInteger mod) 
     { 
      BigInteger bData = new BigInteger(
       data //our data block 
       .Reverse() //BigInteger has another byte order 
       .Concat(new byte[] { 0 }) // append 0 so we are allways handling positive numbers 
       .ToArray() // constructor wants an array 
      ); 
      return 
       BigInteger.ModPow(bData, exp, mod) // the RSA operation itself 
       .ToByteArray() //make bytes from BigInteger 
       .Reverse() // back to "normal" byte order 
       .ToArray(); // return as byte array 

      /* 
      * 
      * A few words on Padding: 
      * 
      * you will want to strip padding after decryption or apply before encryption 
      * 
      */ 
     } 

     public static byte[] plainEncryptPriv(byte[] data, RSAParameters key) 
     { 
      MyRSAParams myKey = MyRSAParams.fromRSAParameters(key); 
      return rsaOperation(data, myKey.privExponent, myKey.Modulus); 
     } 
     public static byte[] plainEncryptPub(byte[] data, RSAParameters key) 
     { 
      MyRSAParams myKey = MyRSAParams.fromRSAParameters(key); 
      return rsaOperation(data, myKey.pubExponent, myKey.Modulus); 
     } 
     public static byte[] plainDecryptPriv(byte[] data, RSAParameters key) 
     { 
      MyRSAParams myKey = MyRSAParams.fromRSAParameters(key); 
      return rsaOperation(data, myKey.privExponent, myKey.Modulus); 
     } 
     public static byte[] plainDecryptPub(byte[] data, RSAParameters key) 
     { 
      MyRSAParams myKey = MyRSAParams.fromRSAParameters(key); 
      return rsaOperation(data, myKey.pubExponent, myKey.Modulus); 
     } 

    } 

    public class MyRSAParams 
    { 
     public static MyRSAParams fromRSAParameters(RSAParameters key) 
     { 
      var ret = new MyRSAParams(); 
      ret.Modulus = new BigInteger(key.Modulus.Reverse().Concat(new byte[] { 0 }).ToArray()); 
      ret.privExponent = new BigInteger(key.D.Reverse().Concat(new byte[] { 0 }).ToArray()); 
      ret.pubExponent = new BigInteger(key.Exponent.Reverse().Concat(new byte[] { 0 }).ToArray()); 

      return ret; 
     } 
     public BigInteger Modulus; 
     public BigInteger privExponent; 
     public BigInteger pubExponent; 
    } 
+0

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

+0

uhm ... может быть, факт, что вы не можете расшифровать с помощью закрытого ключа, когда у вас его нет ... да ... что это связано с примером вычисления, который просто показывает, как делать математику за RSA? – DarkSquirrel42

+0

Неправильно, вы можете расшифровать данные, которые были зашифрованы с помощью закрытого ключа, используя открытый ключ ТОЛЬКО в процессе дешифрования. В приведенном выше примере требуется секретный ключ независимо от того, расшифровывается ли дешифрование с использованием открытого или закрытого для дешифрования. Пожалуйста, взгляните на свой образец, и вы поймете. Для всех вам необходимо, чтобы ОБА публично и конфиденциально работали над любым из ваших методов расшифровки, что неверно. –

15

Рассмотрим пример кодирования/декодирования

 byte[] toEncryptData = Encoding.ASCII.GetBytes("hello world"); 

     //Generate keys 
     RSACryptoServiceProvider rsaGenKeys = new RSACryptoServiceProvider(); 
     string privateXml = rsaGenKeys.ToXmlString(true); 
     string publicXml = rsaGenKeys.ToXmlString(false); 

     //Encode with public key 
     RSACryptoServiceProvider rsaPublic = new RSACryptoServiceProvider(); 
     rsaPublic.FromXmlString(publicXml); 
     byte[] encryptedRSA = rsaPublic.Encrypt(toEncryptData, false); 
     string EncryptedResult = Encoding.Default.GetString(encryptedRSA); 


     //Decode with private key 
     var rsaPrivate = new RSACryptoServiceProvider(); 
     rsaPrivate.FromXmlString(privateXml); 
     byte[] decryptedRSA = rsaPrivate.Decrypt(encryptedRSA, false); 
     string originalResult = Encoding.Default.GetString(decryptedRSA); 
+0

Исходный вопрос задавал примеры обоих направлений. Ваш код показывает, как делать дешифрование только с помощью частного ключа, а не как расшифровать с помощью открытого ключа. –

+1

В случае RSA нет необходимости расшифровывать с помощью открытого ключа. Кроме того, вы имеете в виду подписание rsa. –

+0

Нет, я имею в виду расшифровку с использованием открытого ключа. Например, в php, используя openssl_private_encrypt() - сохранение закрытого ключа PRIVATE на сервере, как и должно быть. Теперь в «клиенте» это нужно будет расшифровать с помощью открытого ключа (примером клиентов будет программа, написанная на C# и «подписанная» с AuthentiCode). Удобно иметь публичный сертификат, встроенный в программу (часть процесса знака). Теперь, изобразите это другим способом - эпический провал. И катит хэш, который вам нужно проанализировать, чтобы «проверить» данные - так легко взломать. –

Смежные вопросы