2013-11-22 20 views
9

Ich versuche, ein kleines Programm zu erstellen, das erkennen kann, ob auf Dateien/Dateien zugegriffen wurde oder mit dem DSA-Signaturalgorithmus geändert wurde.Unterschiedliche Ergebnisse beim Signieren derselben Daten mit gleichen Schlüsseln in DSA cryptoservice provider

Ich gebe Ihnen diesen kleinen Beispielcode, um das Problem zu beschreiben. Angenommen, wir haben eine Datei c: \ Temporary \ Temp.txt. Wir haben in unserem Programm 2 Tasten. Wenn wir auf die erste Schaltfläche klicken, erstellen wir eine digitale Signatur über den Namen der Datei und die letzte Zugriffszeit darauf. Wir exportieren auch die Parameter und speichern sie. Beim zweiten Klick klicken wir die Signatur in der gleichen Datei mit den zuvor exportierten Parametern an und vergleichen die neue Signatur mit der vorherigen.

Das Problem hier ist, dass das Programm (immer) gibt mir ein Ergebnis, dass die Datei zugegriffen wurde !!!!

Ich habe den Debugger verwendet, um das Problem zu finden und sah, dass alle Variablenwerte zwischen den 2 button_click-Ereignissen identisch sind und dass der Unterschied im Signierprozess auftritt.

Würden Sie mir bitte sagen, wo das Problem liegt? Hier ist der Code:

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Data.SqlClient; 
using System.Security.Cryptography; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     string filename = @"C:\Temporary\Temp.txt"; 
     DSAParameters parameters; 
     byte[] data_to_sign, signature; 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_Load(object sender, EventArgs e) 
    { 

    } 

    private void Sign_button_Click(object sender, EventArgs e) 
    { 
     FileInfo f_info = new FileInfo(filename); 
     string file_information = f_info.FullName + f_info.LastAccessTime; 
     UnicodeEncoding byteEncoder = new UnicodeEncoding(); 
     data_to_sign = byteEncoder.GetBytes(file_information); 
     DSACryptoServiceProvider dsaprovider = new DSACryptoServiceProvider(); 
     parameters = dsaprovider.ExportParameters(true); 
     signature = dsaprovider.SignData(data_to_sign); 
     label1.Text = " Signature generated"; 
    } 

    private void Verify_button_Click(object sender, EventArgs e) 
    { 
     FileInfo f_info = new FileInfo(filename); 
     string file_information = f_info.FullName + f_info.LastAccessTime; 
     UnicodeEncoding byteEncoder = new UnicodeEncoding(); 
     data_to_sign = byteEncoder.GetBytes(file_information); 
     DSACryptoServiceProvider dsaprovider2 = new DSACryptoServiceProvider(); 
     dsaprovider2.ImportParameters(parameters); 
     byte [] signature2 = dsaprovider2.SignData(data_to_sign); 
     if (signature == signature2) 
      label1.Text = "The file hasn't been accessed"; 
     else 
      label1.Text = "Opp... The file has been accessed"; 

    } 
} 
} 

Antwort

10

Sie vergleichen zwei Byte-Arrays mit dem == Operator. Sie vergleichen sie als Referenz und dies ist immer falsch für zwei verschiedene Byte-Array-Instanzen, selbst wenn ihr Inhalt derselbe ist. Sie müssen stattdessen ihren Inhalt vergleichen.

Verwenden Sie die verschiedenen Codeteile von this question, um den Inhalt tatsächlich zu vergleichen.

Statt

if (signature == signature2) 

können Sie so etwas wie:

if (signature.SequenceEqual(signature2)) 

Wenn Sie System.Linq in Ihrer Verwendung von Erklärungen haben.

+0

ja SequenceEqual oder in String konvertieren zu vergleichen. –

4

Sie missbrauchen DSA völlig. DSA ist ein Signaturalgorithmus, den Sie mithilfe eines digitalen Signaturverifikationsalgorithmus überprüfen müssen. In der Tat ist DSA entworfen, um eine unterschiedliche Signatur bei jeder Verwendung zu erzeugen, weil es auf Zufallszahlen angewiesen ist, um es zu generieren. Was Sie hier wollen, ist ein Hash-Algorithmus, wie SHA-256 oder Keccak.

+0

DSA verwendet den Hash-Algorithmus SHA1, die Aufrufmethode '.SignData()' gibt einen SHA1-Hash zurück, obwohl ich Ihnen zustimme, wenn OP DSA nur für Hashing verwendet, ist es möglicherweise nicht die beste Wahl – geedubb

+0

@geedubb DSA nicht Erzeuge einen SHA1-Hash, aber eine DSA-Signatur. DSA hashes seine Eingabe, aber das hat keine Beziehung mit OP-Anforderungen. – Aris

2

Sie sind für die deciion

string file_information = f_info.FullName + f_info.LastAccessTime; 

als Grundlage verwenden, was bedeutet, dass Sie sich darauf verlassen, dass der Dateiname und die letzte Zugriffszeit nicht ändern.

  • Sie wissen nicht, was das .NET Framework intern tut, wenn ein Objekt vom Typ Fileinfo Schaffung. Vielleicht greift das schon auf die Datei zu. Oder es greift auf die Datei zu, wenn Sie die Eigenschaft FullName verwenden.
  • Sie sollten auch Refresh() aufrufen, wenn Sie erneut auf die Eigenschaften der gleichen Datei zugreifen. Andernfalls kann cached information verwendet werden.
  • Die LastAccessTime ist nicht sehr zuverlässig. Aus Leistungsgründen Windows 7 nicht dieses Flag nicht aktualisieren. Lesen Sie "Windows Internals 6" für Details.
  • Warum verwenden Sie DSA überhaupt in diesem Beispiel? Sie können einfach die file_information Strings direkt vergleichen. Unterschreiben oder nicht würde nicht den Unterschied machen.
  • Wie sagte Sebastian, zu vergleichen byte [] für die Gleichstellung richtig