Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different results when signing same data with same keys in DSA cryptoservice provider

Tags:

c#

dsa

I am trying to build a small program that can discover whether file/files has been accessed or modified using DSA Signing algorithm.

I will give you this small example code to describe the issue. Suppose that we have a file c:\Temporary\Temp.txt. We have in our program 2 buttons. When we click the first button we create a digital signature on the name of the file and the last access time on it. We also export the parameters and save them. On the second button click we recreate the signature on the same file using the parameters that we exported earlier and compare the new signature with the previous.

The problem here is that the program (always) gives me a result that the file has been accessed!!!!

I used the debugger to find the problem and saw that all variable values are identical between the 2 button_click events and that the difference occurs in the signing process.

Would you please tell me where the problem is? Here is the 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";

    }
}
}
like image 357
AhdDbn Avatar asked Nov 22 '13 18:11

AhdDbn


3 Answers

You are comparing two byte arrays using the == operator. You are comparing them by reference and this is always false for two different byte array instances, even if their contents are the same. You need to compare their contents instead.

Use the various code pieces from this question to actually compare the contents.

Instead of

if (signature == signature2)

you can do something like:

if (signature.SequenceEqual(signature2))

If you have System.Linq in your using declarations.

like image 185
Sebastian Avatar answered Oct 16 '22 23:10

Sebastian


You completely missuse DSA. DSA is a signature algorithm, that you need to verify using a digital signature verification algorithm. In fact DSA is designed to produce a different signature on every use, because it depends on random numbers to generate it. What you want here is an Hash algorithm, like SHA-256 or Keccak.

like image 26
Aris Avatar answered Oct 17 '22 01:10

Aris


You're using

string file_information = f_info.FullName + f_info.LastAccessTime;

as the basis for the deciion, which means you rely on the fact that the file name and last access time did not change.

  • You don't know what the .NET framework does internally when creating an object of type FileInfo. Maybe that already accesses the file. Or it accesses the file when using the FullName property.
  • You should also call Refresh() when accessing the properties of the same file again. Otherwise it may use cached information.
  • The LastAccessTime is not very reliable. For performance reasons, Windows 7 does not update that flag. Read "Windows Internals 6" for details.
  • Why are you using DSA at all in this example? You could simply compare the file_information strings directly. Signing or not would not make the difference.
  • Like Sebastian said, compare byte[] for equality correctly
like image 33
Thomas Weller Avatar answered Oct 17 '22 01:10

Thomas Weller