ディレクトリ/フォルダが変更/編集されていないか確認する方法(Windows/.NET)

悪意のあるないにかかわらず、第三者がアプリケーションの設定ファイルやフォルダ構造を誤って編集してしまう可能性はあると思います。
そのような場合に、ファイルのハッシュ値を保存しておき、アプリケーション起動時に再度ハッシュ値をチェックし、変更がないかどうか確認することで編集の有無を確認できます。

調査したところ、Windowsではいくつか方法があります。

#fciv.exeを利用する
Microsoft File Checksum Integrity Verifier(FCIV)

fcivはMS謹製のチェックツールです。
デフォルトではついていないので、別途ダウンロードする必要があります。

https://www.microsoft.com/en-us/download/details.aspx?id=11533

ダウンロード自由なので、再頒布可能なのかな？（自分の作ったアプリと一緒に配って良いのか？）
情報は見つけられませんでした。

Win32アプリのようです。
DependencyWalkerで依存関係を覗いてみると
こんな依存関係なので、Windows2000以降なら動作しそうですね。

![Image.png](https://qiita-image-store.s3.amazonaws.com/0/12790/080a7cbb-1f34-eff2-32ab-4ed57aa1a7f4.png)


@ITにも記事がありました。
http://www.atmarkit.co.jp/ait/articles/0507/30/news017.html

フォルダの配下を再帰的にチェックして、各ファイルのハッシュを取りそれをXMLファイルとして保存できます。

`fciv -add [ディレクトリ] -r -type *.ini -xml org.xml`

上記の場合は、
-add でディレクトリを指定
-r でディレクトリ配下を再帰的に検索
-type *.iniで、対象となるファイルの拡張子を指定
-xml で結果をxmlに出力する
としています。

結果、org.xmlが出力されます。ハッシュ値はbase64エンコーディングされているのでよくわからない文字になっています。

オプションでハッシュ方式を指定できます。
`Options:`
`        -md5 | -sha1 | -both    : Specify hashtype, default md5.`

```lang:xml
<FILE_ENTRY>
     <name>c:\tools\flexrena84\FlexRena84\Flexible Renamer.DE.Strings.ini</name><MD5>LwW7+4D7jb+LWSfh6CPdtw==</MD5>
</FILE_ENTRY>
```

上記保存したXMLと、現在のディレクトリの状態を比較できます。

` fciv -v [ディレクトリ] -r -type *.ini -xml org.xml`

-v で検証対象を指定
-xml で比較元のXMLを指定

上記の結果、一致していれば、
` All files verified successfully`
と出力され、
一致していなければ、どのファイルが一致していなかったか出力されます。

```
例:
List of modified files:
-----------------------
c:\tools\flexrena84\FlexRena84\Flexible Renamer.ES.Strings.ini
        Hash is         : cb980140479db08b26eba02c45b85a82
        It should be    : 1ae576dd381102a4fdb1107f05172fdb

c:\tools\flexrena84\FlexRena84\Flexible Renamer.ES.Strings.ini
        Hash is         : cb980140479db08b26eba02c45b85a82
        It should be    : 1ae576dd381102a4fdb1107f05172fdb

c:\tools\flexrena84\FlexRena84\Flexible Renamer.ES.Strings.ini
        Hash is         : cb980140479db08b26eba02c45b85a82
        It should be    : 1ae576dd381102a4fdb1107f05172fdb

c:\tools\flexrena84\FlexRena84\Flexible Renamer.ES.Strings.ini
        Hash is         : cb980140479db08b26eba02c45b85a82
        It should be    : 1ae576dd381102a4fdb1107f05172fdb
```

気になるのはパフォーマンスですが、試しにC:\Windows内を検索してみました。

` fciv -add C:\Windows\ -r -type *.ini  -xml org.xml `
.iniでフィルタしていますが、結果は３秒ぐらい。( Win8.1/Core i7/Memory 16GB (MacBook Pro retina mid2012のスペックです))

```
//
// File Checksum Integrity Verifier version 2.05.
//
Start Time: 05/28/2015 at 06h02'09''
End Time..: 05/28/2015 at 06h02'12''
     Processed 32717 directories
     Processed 135005 files
```


そんなに悪くないんじゃないかと思います。
出来上がったxmlのサイズは373KBでした。(MD5の場合。暗号化方式を変えるとサイズは変わります）

検証は更に速く、１秒かかりませんでした。

```
//
// File Checksum Integrity Verifier version 2.05.
//
Could not create the registry key.
Starting checksums verification : 05/28/2015 at 06h04'12
All files verified successfully
End Verification : 05/28/2015 at 06h04'12
```



#自作する(.NETで試します)

StackOverflowに記事がありましたので、それを参考にしてコードを書きます。
http://stackoverflow.com/questions/1177607/what-is-the-fastest-way-to-create-a-checksum-for-large-files-in-c-sharp

書いてみたコードが以下になります。
https://gist.github.com/Koki-Shimizu/529e178e2e6ba9f3aa62

私の環境には検証用のOracleが入っていまして、Oracleフォルダ内には.sqlファイルが2500ファイルほどあります。
2500ファイルで約1.3秒。遅いですね。
もうちょっとチューニング出来る気がします。
fcivはbase64にしたり、XMLタグ作ったりしているので、処理の割にはもっと速いですね。

この結果を最新の状態と比較すれば、ファイルの編集有無を確認できます。