9

我正在尝试构建一个小程序,该程序可以使用 DSA 签名算法发现文件/文件是否已被访问或修改。

我会给你这个小示例代码来描述这个问题。假设我们有一个文件 c:\Temporary\Temp.txt。我们的程序中有 2 个按钮。当我们单击第一个按钮时,我们会在文件名和最后访问时间上创建一个数字签名。我们还导出参数并保存它们。在第二个按钮上单击,我们使用之前导出的参数在同一文件上重新创建签名,并将新签名与以前的签名进行比较。

这里的问题是程序(总是)给我一个文件已被访问的结果!!!!

我使用调试器找到了问题,发现 2 个 button_click 事件之间的所有变量值都相同,并且差异发生在签名过程中。

你能告诉我问题出在哪里吗?这是代码:

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

    }
}
}
4

3 回答 3

10

您正在使用==运算符比较两个字节数组。您通过引用比较它们,这对于两个不同的字节数组实例总是错误的,即使它们的内容相同。您需要比较它们的内容。

使用此问题中的各种代码片段来实际比较内容。

代替

if (signature == signature2)

您可以执行以下操作:

if (signature.SequenceEqual(signature2))

如果您有System.Linqusing 声明。

于 2013-12-13T16:22:50.790 回答
4

你完全误用了 DSA。DSA 是一种签名算法,您需要使用数字签名验证算法对其进行验证。事实上,DSA 旨在在每次使用时产生不同的签名,因为它依赖于随机数来生成它。您需要的是哈希算法,例如 SHA-256 或 Keccak。

于 2013-12-20T13:31:29.773 回答
2

你正在使用

string file_information = f_info.FullName + f_info.LastAccessTime;

作为决定的基础,这意味着您依赖于文件名和上次访问时间没有改变的事实。

  • 在创建FileInfo类型的对象时,您不知道 .NET 框架在内部做了什么。也许已经访问了该文件。或者它在使用FullName属性时访问文件。
  • 再次访问同一文件的属性时,您还应该调用Refresh() 。否则它可能会使用缓存信息
  • LastAccessTime 不是很可靠。出于性能原因,Windows 7 不会更新该标志。阅读“Windows Internals 6”了解详细信息。
  • 为什么在这个例子中使用 DSA ?您可以直接比较 file_information 字符串。签约与否不会有什么不同。
  • 就像塞巴斯蒂安所说,正确比较byte[] 是否相等
于 2013-12-20T15:33:19.353 回答