2013-11-22 10 views
9

Tôi đang cố xây dựng một chương trình nhỏ có thể khám phá xem tệp/tệp đã được truy cập hoặc sửa đổi bằng thuật toán ký DSA hay chưa.Kết quả khác nhau khi ký cùng một dữ liệu với cùng một khóa trong nhà cung cấp dịch vụ mã hóa DSA

Tôi sẽ cung cấp cho bạn mã ví dụ nhỏ này để mô tả sự cố. Giả sử chúng ta có một tệp c: \ Temporary \ Temp.txt. Chúng tôi có trong các nút chương trình 2 của chúng tôi. Khi chúng ta nhấp vào nút đầu tiên, chúng tôi tạo chữ ký số vào tên của tệp và thời gian truy cập cuối cùng trên đó. Chúng tôi cũng xuất các tham số và lưu chúng. Trên nút thứ hai, chúng tôi tạo lại chữ ký trên cùng một tệp bằng cách sử dụng các tham số mà chúng tôi đã xuất trước đó và so sánh chữ ký mới với chữ ký trước đó.

Vấn đề ở đây là chương trình (luôn luôn) cho tôi kết quả là tệp đã được truy cập !!!!

Tôi đã sử dụng trình gỡ lỗi để tìm sự cố và thấy rằng tất cả các giá trị biến đều giống nhau giữa 2 sự kiện button_click và sự khác biệt xảy ra trong quá trình ký.

Bạn vui lòng cho tôi biết sự cố ở đâu? Đây là mã:

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"; 

    } 
} 
} 

Trả lời

10

Bạn đang so sánh hai mảng byte sử dụng toán tử ==. Bạn đang so sánh chúng bằng cách tham chiếu và điều này luôn luôn sai cho hai trường hợp mảng byte khác nhau, ngay cả khi nội dung của chúng giống nhau. Thay vào đó, bạn cần phải so sánh nội dung của chúng.

Sử dụng các đoạn mã khác nhau từ this question để so sánh nội dung.

Thay vì

if (signature == signature2) 

bạn có thể làm một cái gì đó như:

if (signature.SequenceEqual(signature2)) 

Nếu bạn có System.Linq trong việc sử dụng tờ khai của bạn.

+0

có SequenceEqual, hoặc chuyển sang chuỗi để so sánh. –

4

Bạn hoàn toàn bỏ lỡ DSA. DSA là một thuật toán chữ ký, bạn cần xác minh bằng thuật toán xác minh chữ ký số. Trong thực tế, DSA được thiết kế để tạo ra một chữ ký khác nhau trên mỗi lần sử dụng, bởi vì nó phụ thuộc vào các số ngẫu nhiên để tạo ra nó. Những gì bạn muốn ở đây là một thuật toán Hash, như SHA-256 hoặc Keccak.

+0

DSA sử dụng thuật toán băm SHA1, gọi phương thức '.SignData()' trả về hàm băm SHA1, mặc dù tôi đồng ý với bạn rằng nếu OP đang sử dụng DSA cho băm chỉ có thể không phải là lựa chọn tốt nhất – geedubb

+0

@geedubb DSA không tạo ra mã băm SHA1 nhưng chữ ký DSA. DSA băm đầu vào của nó nhưng không có mối quan hệ với các yêu cầu của OP. – Aris

2

Bạn đang sử dụng

string file_information = f_info.FullName + f_info.LastAccessTime; 

làm cơ sở cho các deciion, có nghĩa là bạn dựa trên thực tế là tên tập tin và thời gian truy cập cuối cùng không thay đổi.

  • Bạn không biết những gì khuôn khổ NET làm trong nội bộ khi tạo một đối tượng kiểu FileInfo. Có thể đã truy cập tệp . Hoặc nó truy cập tệp khi sử dụng thuộc tính FullName.
  • Bạn cũng nên gọi Làm mới() khi truy cập lại các thuộc tính của cùng một tệp. Nếu không, nó có thể sử dụng cached information.
  • LastAccessTime không đáng tin cậy lắm. Vì lý do hiệu suất, Windows 7 không không cập nhật cờ đó. Đọc "Windows Nội bộ 6" để biết chi tiết.
  • Tại sao bạn sử dụng DSA ở tất cả trong ví dụ này? Bạn chỉ có thể so sánh trực tiếp các chuỗi file_information . Việc ký tên hay không sẽ không tạo ra sự khác biệt.
  • Giống như Sebastian cho biết, so sánh byte [] cho bình đẳng đúng
Các vấn đề liên quan