9

DSA 署名アルゴリズムを使用して、ファイルがアクセスまたは変更されたかどうかを検出できる小さなプログラムを構築しようとしています。

この問題を説明するために、この小さなサンプル コードを提供します。ファイル c:\Temporary\Temp.txt があるとします。プログラムには 2 つのボタンがあります。最初のボタンをクリックすると、ファイルの名前と最終アクセス時刻にデジタル署名が作成されます。また、パラメータをエクスポートして保存します。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

==演算子を使用して 2 つのバイト配列を比較しています。それらを参照によって比較していますが、内容が同じであっても、これは 2 つの異なるバイト配列インスタンスでは常に false です。代わりに、それらの内容を比較する必要があります。

この質問のさまざまなコードを使用して、実際に内容を比較してください。

それ以外の

if (signature == signature2)

次のようなことができます:

if (signature.SequenceEqual(signature2))

System.Linqusing 宣言がある場合。

于 2013-12-13T16:22:50.790 に答える
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 に答える