在DSA密码服务提供商中使用相同密钥签署相同数据时的结果不同

时间:2013-11-22 18:52:27

标签: c# dsa

我正在尝试构建一个小程序,可以发现是否使用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";

    }
}
}

3 个答案:

答案 0 :(得分:10)

您正在使用==运算符比较两个字节数组。您通过引用比较它们,对于两个不同的字节数组实例,即使它们的内容相同,它也始终为false。你需要比较它们的内容。

使用this question中的各种代码段来实际比较内容。

而不是

if (signature == signature2)

你可以这样做:

if (signature.SequenceEqual(signature2))

如果您在使用声明中有System.Linq

答案 1 :(得分:4)

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

答案 2 :(得分:2)

你正在使用

string file_information = f_info.FullName + f_info.LastAccessTime;

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

  • 您不知道.NET框架在内部执行什么操作 创建 FileInfo 类型的对象。也许那已经访问了 文件。或者,当使用 FullName 属性时,它会访问该文件。
  • 再次访问同一文件的属性时,还应调用 Refresh()。否则,它可能会使用cached information
  • LastAccessTime不太可靠。出于性能原因, Windows 7 不会更新该标志。阅读“Windows Internals 6“了解详情。
  • 你为什么要使用DSA 呢? 例?您可以简单地比较file_information字符串 直。签字与否不会产生影响。
  • 像 塞巴斯蒂安说,正确比较 byte []