2016-04-11 6 views
2

Ich arbeite an einer Zuweisung in Bezug auf RSA-Verschlüsselung und Entschlüsselung. Für diese Zuweisung müssen wir in der Lage sein, ANY Größenschlüssel zu verschlüsseln und zu entschlüsseln.RSA-Verschlüsselung/Entschlüsselung mehrerer Blöcke in C#

Ich habe Code geschrieben, der erfolgreich verschlüsselt und entschlüsselt (vorausgesetzt, dass der Schlüssel die maximale Schlüsselgröße nicht überschreitet), aber jetzt muss ich diesen Code ändern, um jede Größe zu behandeln.

public partial class Form1 : Form 
{ 
    //Strings to hold public & private keys 
    String publicKey, privateKey; 
    UnicodeEncoding encoder = new UnicodeEncoding(); 

    public Form1() 
    { 
     RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider(); 
     InitializeComponent(); 
     privateKey = myRSA.ToXmlString(true); 
     publicKey = myRSA.ToXmlString(false); 
    } 
private void btnEncrypt_Click(object sender, EventArgs e) 
    { 
     var myRSA = new RSACryptoServiceProvider(); 

     //Set cryptoserviceprovider with the proper key 
     myRSA.FromXmlString(publicKey); 

     //Encode the data to encrypt as a byte array 
     var dataToEncrypt = encoder.GetBytes(txtPlain.Text); 

     //Encrypt the byte array 
     var encryptedByteArray = myRSA.Encrypt(dataToEncrypt, false).ToArray(); 

     var length = encryptedByteArray.Count(); 
     var item = 0; 
     var sb = new StringBuilder(); 

     //Change each byte in the encrypted byte array to text 
     foreach(var x in encryptedByteArray) 
     { 
      item++; 
      sb.Append(x); 
      if (item < length) sb.Append(","); 
     } 
     txtCypher.Text = sb.ToString(); 
    } 

    private void btnDecrypt_Click(object sender, EventArgs e) 
    { 
     var myRSA = new RSACryptoServiceProvider(); 

     //Split data into an array 
     var dataArray = txtCypher.Text.Split(new char[] { ',' }); 

     //Convert chars to bytes 
     byte[] dataByte = new byte[dataArray.Length]; 

     for(int i = 0; i < dataArray.Length; i++) dataByte[i] = Convert.ToByte(dataArray[i]); 

     //Decrypt the byte array 
     myRSA.FromXmlString(privateKey); 
     var decryptedBytes = myRSA.Decrypt(dataByte, false); 

     //place into cypher text box 
     txtPlain.Text = encoder.GetString(decryptedBytes); 
    } 
} 

Ich habe mit dem folgenden Code kommen zu können, jede mögliche Größe verschlüsseln (was meines Wissens scheint zu funktionieren):

//store dataLength 
     int dataLength = dataToEncrypt.Length; 

     //Check if dataLength > 117 
     if (dataLength > 117) 
     { 
      //Divide dataLength by 128 to determine how many cycles will be needed 
      float numOfCycles = (dataLength/117); 
      //round up to nearest whole number 
      cycles = (int)Math.Ceiling(numOfCycles); 


      //for however many cycles 
      for (int i = 0; i < cycles; i++) 
      { 
       var myByteArray = new byte[117]; 
       for (int j = 0; j < 117; j++) 
       { 
        int currentByte = i * 117 + j; 
        myByteArray[j] = dataToEncrypt[currentByte]; 
       } 

       var encryptedByteArray = myRSA.Encrypt(myByteArray, false).ToArray(); 

       var length = encryptedByteArray.Count(); 
       var item = 0; 

       //Change each byte in the encrypted byte array to text 
       foreach (var x in encryptedByteArray) 
       { 
        item++; 
        sb.Append(x); 
        if (item < length) sb.Append(","); 
       } 
       txtCypher.Text = sb.ToString(); 
      } 
     } 
     else 
     { 
      var encryptedByteArray = myRSA.Encrypt(dataToEncrypt, false).ToArray(); 
      var length = encryptedByteArray.Count(); 
      var item = 0; 
      var sb = new StringBuilder(); 

      //Change each byte in the encrypted byte array to text 
      foreach(var x in encryptedByteArray) 
      { 
       item++; 
       sb.Append(x); 
      if (item < length) sb.Append(","); 
      } 
       txtCypher.Text = sb.ToString(); 
      } 

Und den folgenden Code jeder Größe, die ISN zu entschlüsseln ‚T ARBEITS:

float length = dataArray.Count(); 
     float numOfCycles = (length/117); 
     int cycles = (int)Math.Ceiling(numOfCycles); 

     for (int i = 0; i < cycles; i++) 
     { 
      byte[] dataByte = new byte[117]; 
      for(int j = 0; j < 117; j++) 
      { 
       //Convert chars to bytes 
       dataByte[j] = Convert.ToByte(dataArray[ i * 117 + j ]); 
      } 
      //Decrypt the byte array 
      myRSA.FromXmlString(privateKey); 
      var decryptedBytes = myRSA.Decrypt(dataByte, false); 
      txtPlain.Text += encoder.GetString(decryptedBytes); 
     } 

Die folgende Zeile: var decryptedBytes = myRSA.Decrypt(dataByte, false);

führt den Fehler: An unhandled exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll Additional information: Bad Data.

Ich habe keine Ahnung, warum dieser Fehler ausgelöst wird, ich das Programm gedebuggt haben und die in databyte gespeicherten Daten [] scheint nicht von anders zu sein, was im Inneren gespeichert wurde, als ich erfolgreich eine Nachricht mit einer Größe entschlüsseln, die kleiner als die maximale Schlüsselgröße ist.

+0

Hat meine Antwort Ihnen geholfen, das Problem zu lösen? Wenn Sie es gelöst haben, können Sie Ihre eigene Antwort mit dem Arbeitscode posten und [accept] (http://meta.stackexchange.com/q/5234/266187) entweder beantworten. –

Antwort

1

RSA, als asymmetrisches Kryptosystem, ist im Vergleich zu symmetrischen Chiffren wie AES sehr langsam. Der richtige Weg, dies zu implementieren, wäre, einen symmetrischen AES-Schlüssel zu erzeugen, die tatsächlichen Daten mit AES zu verschlüsseln (z.B. mit CBC/CTR/GCM/EAX) und dann den einzelnen Schlüssel mit RSA zu verschlüsseln.

Es gibt keinen Standard für die Anwendung von RSA auf mehrere "Blöcke". Es wird daher nicht empfohlen, dies zu implementieren. Wenn Sie es dennoch implementieren möchten, sind hier einige Probleme mit Ihrem Code.

RSA muss auf Sicherheit gepuffert werden. Da Sie einen 128-Byte-Schlüssel verwenden und den Klartext in 117-Byte-Blöcke aufteilen, bedeutet dies, dass Sie PKCS # 1 v1.5-Padding verwenden. Jeder Block wird aufgefüllt und dann verschlüsselt. Der Schlüsseltext ist numerisch streng kleiner als der Modul, aber normalerweise ziemlich nah. Die meisten Chiffriertexte werden 128 Byte lang sein, aber einige können kleiner sein, weil ein Chiffretext eine fortlaufende Zahl ist, bei der die führenden Nullen nicht gespeichert werden müssen. Das bedeutet, dass Sie sie nicht einfach nacheinander schreiben können und erwarten, dass Sie sie korrekt zurücklesen.
Sie müssen entweder die Chiffretexte mit 0x00 Bytes auffüllen, so dass sie alle die gleiche Länge haben (128 Byte) oder die Länge jedes Chiffretextes vor dem entsprechenden Chiffretext speichern, so dass Sie wissen, wie viel Sie lesen müssen.