• R/O
  • SSH
  • HTTPS

easyhashchecker: コミット


コミットメタ情報

リビジョン4 (tree)
日時2007-01-28 04:41:03
作者seraphy

ログメッセージ

version 1.0_d20060207

変更サマリ

差分

--- trunk/DigestItem.cpp (nonexistent)
+++ trunk/DigestItem.cpp (revision 4)
@@ -0,0 +1,59 @@
1+#include "stdafx.h"
2+
3+#include "DigestItem.h"
4+
5+DigestItem::DigestItem() throw()
6+ : hash_(NULL)
7+ , name_(NULL)
8+ , binary_(false)
9+ , algoId_(CALG_MD5)
10+{
11+}
12+
13+DigestItem::~DigestItem() throw()
14+{
15+}
16+
17+void DigestItem::SetHash(const LPCSTR src, const size_t len) throw()
18+{
19+ if (hash_)
20+ hash_.Empty();
21+ hash_ = CComBSTR(static_cast<UINT>(len), src);
22+}
23+
24+void DigestItem::SetName(const LPCSTR src, const size_t len) throw()
25+{
26+ if (name_)
27+ name_.Empty();
28+ name_ = CComBSTR(static_cast<UINT>(len), src);
29+}
30+
31+void DigestItem::SetBinary(const bool binary) throw()
32+{
33+ binary_ = binary;
34+}
35+
36+void DigestItem::SetAlgoID(const ALG_ID algoId) throw()
37+{
38+ algoId_ = algoId;
39+}
40+
41+LPCWSTR DigestItem::GetHash() const throw()
42+{
43+ return hash_;
44+}
45+
46+LPCWSTR DigestItem::GetName() const throw()
47+{
48+ return name_;
49+}
50+
51+bool DigestItem::IsBinary() const throw()
52+{
53+ return binary_;
54+}
55+
56+ALG_ID DigestItem::getAlgoId() const throw()
57+{
58+ return algoId_;
59+}
--- trunk/stdafx.h (nonexistent)
+++ trunk/stdafx.h (revision 4)
@@ -0,0 +1,16 @@
1+// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または
2+// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル
3+// を記述します。
4+//
5+
6+#pragma once
7+
8+#define WIN32_LEAN_AND_MEAN // Windows ヘッダーから使用されていない部分を除外します。
9+
10+#include <windows.h>
11+#include <Wincrypt.h>
12+#include <atlbase.h>
13+#include <atlmem.h>
14+#include <atlcoll.h>
15+
16+//#include <atlstr.h>
--- trunk/DigestItem.h (nonexistent)
+++ trunk/DigestItem.h (revision 4)
@@ -0,0 +1,33 @@
1+#pragma once
2+
3+#include <atlbase.h>
4+
5+class DigestItem
6+{
7+private:
8+ DigestItem(const DigestItem&); //<! 実装なし
9+ DigestItem& operator=(const DigestItem&); //<! 実装なし
10+
11+public:
12+ DigestItem() throw();
13+ ~DigestItem() throw();
14+
15+ void SetHash(const LPCSTR src, const size_t len) throw();
16+ void SetName(const LPCSTR src, const size_t len) throw();
17+ void SetBinary(const bool binary) throw();
18+ void SetAlgoID(const ALG_ID algoId) throw();
19+
20+ LPCWSTR GetHash() const throw();
21+ LPCWSTR GetName() const throw();
22+ bool IsBinary() const throw();
23+ ALG_ID getAlgoId() const throw();
24+
25+private:
26+ CComBSTR hash_;
27+ CComBSTR name_;
28+ bool binary_;
29+ ALG_ID algoId_;
30+};
31+
32+typedef CAutoPtr<DigestItem> DigestItemPtr;
33+typedef CAutoPtrList<DigestItem> DigestItemPtrList;
--- trunk/MakeOperation.h (nonexistent)
+++ trunk/MakeOperation.h (revision 4)
@@ -0,0 +1,140 @@
1+#pragma once
2+
3+#include <wincrypt.h>
4+#include <atlbase.h>
5+
6+#include "Utility.h"
7+
8+int MakeOperation(DigestContext& ctx, const ALG_ID algId, const LPCWSTR ext) throw()
9+{
10+ WIN32_FIND_DATA findData;
11+ HANDLE hFind = ::FindFirstFile(L"*.*", &findData);
12+ if (hFind == INVALID_HANDLE_VALUE)
13+ return 0;
14+
15+ bool err = false;
16+ while(1)
17+ {
18+ if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
19+ {
20+ CComBSTR fileName(findData.cFileName);
21+
22+ Digest digest(ctx);
23+ if (!digest.Create(algId))
24+ {
25+ ShowError(::GetLastError());
26+ err = true;
27+ break;
28+ }
29+
30+ if (!CalcFileDigest(fileName, digest))
31+ {
32+ ShowError(::GetLastError());
33+ err = true;
34+ break;
35+ }
36+
37+ const size_t siz = digest.GetHashSize();
38+ const size_t max_siz = 64;
39+ ATLASSERT(siz < max_siz);
40+ BYTE hashBuf[max_siz];
41+ if (!digest.GetHashValue(hashBuf, static_cast<DWORD>(siz)))
42+ {
43+ ShowError(::GetLastError());
44+ err = true;
45+ break;
46+ }
47+
48+ CComBSTR digestFileName(fileName);
49+ digestFileName.Append(L".");
50+ digestFileName.Append(ext);
51+
52+ HANDLE fh = ::CreateFile(
53+ digestFileName,
54+ GENERIC_WRITE,
55+ 0,
56+ NULL,
57+ CREATE_ALWAYS,
58+ FILE_FLAG_SEQUENTIAL_SCAN,
59+ NULL
60+ );
61+ if (fh == INVALID_HANDLE_VALUE)
62+ {
63+ ShowError(::GetLastError());
64+ err = true;
65+ break;
66+ }
67+ CHandle fhAutoCloser(fh);
68+
69+ DWORD wd;
70+ unsigned char buf[3] = {0};
71+ for (size_t idx = 0; !err && idx < siz; idx++)
72+ {
73+ const static LPCSTR hexmap = "0123456789abcdef";
74+ const BYTE x = hashBuf[idx];
75+ buf[0] = hexmap[((x >> 4) & 0x0f)];
76+ buf[1] = hexmap[x & 0x0f];
77+ if (!::WriteFile(fh, buf, 2, &wd, NULL) || wd != 2)
78+ err = true;
79+ }
80+
81+ if (!err)
82+ {
83+ if (!::WriteFile(fh, " *", 2, &wd, NULL) || wd != 2)
84+ err = true;
85+ }
86+ if (!err)
87+ {
88+ CHAR mbcsFileName[MAX_PATH];
89+ if (!::WideCharToMultiByte(
90+ ::GetACP(),
91+ 0,
92+ findData.cFileName,
93+ -1,
94+ mbcsFileName,
95+ MAX_PATH,
96+ NULL,
97+ NULL
98+ ))
99+ {
100+ err = true;
101+ break;
102+ }
103+
104+ const DWORD len = lstrlenA(mbcsFileName);
105+ if (!::WriteFile(fh, mbcsFileName, len, &wd, NULL) || wd != len)
106+ err = true;
107+ }
108+ if (!err)
109+ {
110+ if (!::WriteFile(fh, "\n", 1, &wd, NULL) || wd != 1)
111+ err = true;
112+ }
113+
114+ if (err)
115+ {
116+ ShowError(::GetLastError());
117+ break;
118+ }
119+ }
120+
121+ if (!::FindNextFile(hFind, &findData))
122+ {
123+ const DWORD err = ::GetLastError();
124+ if (err == ERROR_NO_MORE_FILES)
125+ break;
126+ else
127+ ShowError(err);
128+ }
129+ }
130+ ::FindClose(hFind);
131+
132+ if (!err)
133+ ::MessageBox(
134+ NULL,
135+ L"作成が終了しました。",
136+ L"ハッシュの作成",
137+ MB_ICONINFORMATION | MB_OK);
138+
139+ return 0;
140+}
--- trunk/Utility.cpp (nonexistent)
+++ trunk/Utility.cpp (revision 4)
@@ -0,0 +1,91 @@
1+#include "stdafx.h"
2+
3+#include "Utility.h"
4+
5+void ShowError(const DWORD errcode) throw()
6+{
7+ LPVOID lpMsgBuf;
8+ if (FormatMessage(
9+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
10+ FORMAT_MESSAGE_FROM_SYSTEM |
11+ FORMAT_MESSAGE_IGNORE_INSERTS,
12+ NULL,
13+ errcode,
14+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // 既定の言語
15+ (LPTSTR) &lpMsgBuf,
16+ 0,
17+ NULL
18+ ))
19+ {
20+ MessageBox(NULL, (LPCTSTR)lpMsgBuf, NULL, MB_OK | MB_ICONERROR);
21+ LocalFree(lpMsgBuf);
22+ }
23+}
24+
25+BSTR ReadFile(const LPCWSTR fileName) throw()
26+{
27+ HANDLE hFile = ::CreateFile(
28+ (LPCWSTR)fileName,
29+ GENERIC_READ,
30+ FILE_SHARE_READ,
31+ NULL,
32+ OPEN_EXISTING,
33+ FILE_FLAG_SEQUENTIAL_SCAN,
34+ NULL
35+ );
36+ if (hFile == INVALID_HANDLE_VALUE)
37+ return NULL;
38+ CHandle hFileAutoCloser(hFile);
39+
40+ const DWORD siz = ::GetFileSize(hFile, NULL);
41+ if (siz == INVALID_FILE_SIZE)
42+ return NULL;
43+
44+ BSTR buf = ::SysAllocStringByteLen(NULL, siz + 1);
45+ if (!buf)
46+ return NULL;
47+
48+ DWORD rd = 0;
49+ if (!::ReadFile(hFile, reinterpret_cast<LPSTR>(buf), siz, &rd, NULL ))
50+ {
51+ ::SysFreeString(buf);
52+ return NULL;
53+ }
54+
55+ reinterpret_cast<LPSTR>(buf)[siz] = 0;
56+ return buf;
57+}
58+
59+size_t HexToBin(const LPCWSTR text, LPBYTE buf, const size_t buf_siz) throw()
60+{
61+ size_t idx = 0;
62+ LPCWSTR p = text;
63+ bool alt = false;
64+ unsigned char d = 0;
65+ while (*p && idx < buf_siz)
66+ {
67+ unsigned char x = 0;
68+ const WCHAR c = *p;
69+ p++;
70+ if (c >= '0' && c <= '9')
71+ x = c - '0';
72+ else if (c >= 'a' && c <= 'f')
73+ x = c - 'a' + 10;
74+ else if (c >= 'A' && c <= 'F')
75+ x = c - 'A' + 10;
76+ if (alt)
77+ {
78+ alt = false;
79+ d <<= 4;
80+ d |= x;
81+ *(buf + idx) = d;
82+ idx++;
83+ }
84+ else
85+ {
86+ alt = true;
87+ d = x;
88+ }
89+ }
90+ return idx;
91+}
--- trunk/DigestFormatParser.cpp (nonexistent)
+++ trunk/DigestFormatParser.cpp (revision 4)
@@ -0,0 +1,80 @@
1+#include "stdafx.h"
2+
3+#include "DigestFormatParser.h"
4+
5+namespace
6+{
7+ inline BOOL IsCRLF(const CHAR c) throw()
8+ {
9+ return (c == '\r') || (c == '\n');
10+ }
11+
12+ inline BOOL IsWhiteSpace(const CHAR c) throw()
13+ {
14+ return (c == ' ') || (c == '\t') || IsCRLF(c);
15+ }
16+}
17+
18+DigestFormatParser::DigestFormatParser(DigestItemPtrList& list)
19+ : list_(list)
20+{
21+}
22+
23+DigestFormatParser::~DigestFormatParser()
24+{
25+}
26+
27+BOOL DigestFormatParser::ParseDigest(const LPCSTR text, const ALG_ID algoId) throw()
28+{
29+ LPCSTR p = text;
30+ while (*p)
31+ {
32+ while (IsWhiteSpace(*p))
33+ p++;
34+ if (!*p)
35+ break;
36+
37+ LPCSTR hash_st = p;
38+ while (*p && !IsWhiteSpace(*p))
39+ p++;
40+ if (!*p)
41+ return FALSE; // 不正なフォーマット
42+ LPCSTR hash_end = p;
43+ const size_t hash_len = hash_end - hash_st;
44+ if (hash_len == 0 || (hash_len % 2))
45+ return FALSE; // 不正なフォーマット
46+
47+ while (IsWhiteSpace(*p))
48+ p++;
49+ if (!*p)
50+ return FALSE; // 不正なフォーマット
51+
52+ bool binary = false;
53+ if (*p == '*')
54+ {
55+ binary = true;
56+ p++;
57+ }
58+
59+ LPCSTR filename_st = p;
60+ while (*p && !IsCRLF(*p))
61+ p++;
62+ LPCSTR filename_en = p;
63+ const size_t filename_len = filename_en - filename_st;
64+
65+ DigestItem* item = new DigestItem();
66+ if (!item)
67+ return FALSE; // メモリ不足
68+
69+ DigestItemPtr itemPtr(item);
70+
71+ item->SetHash(hash_st, hash_len);
72+ item->SetName(filename_st, filename_len);
73+ item->SetBinary(binary);
74+ item->SetAlgoID(algoId);
75+
76+ list_.AddTail(itemPtr);
77+ }
78+
79+ return TRUE;
80+}
--- trunk/docs/easyhashchecker.html (nonexistent)
+++ trunk/docs/easyhashchecker.html (revision 4)
@@ -0,0 +1,256 @@
1+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2+<HTML>
3+<HEAD>
4+ <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=shift_jis">
5+ <TITLE>easyhashcheckerについて</TITLE>
6+ <META NAME="GENERATOR" CONTENT="OpenOffice.org 2.0 (Win32)">
7+ <META NAME="CREATED" CONTENT="20060207;22052000">
8+ <META NAME="CHANGED" CONTENT="20060207;22553136">
9+ <META NAME="&yuml;%4c&laquo;b&yuml;%0c&laquo;b&yuml;%,c&laquo;b&yuml;%(c&laquo;b&yuml;%$c&laquo;b&yuml;% c&laquo;b&yuml;%c&laquo;b&yuml;%c&laquo;b&yuml;%c&laquo;b&yuml;%c&laquo;b&yuml;% c&laquo;b&yuml;%c&laquo;b&yuml;%c&laquo;b&yuml;%" CONTENT="easyhashcheckerについて">
10+ <META NAME="KEYWORDS" CONTENT="easyhashchecker">
11+ <STYLE>
12+ <!--
13+ @page { size: 21cm 29.7cm; margin: 2cm }
14+ P { margin-bottom: 0.21cm }
15+ H1 { margin-bottom: 0.21cm; background: transparent; border-top: 1px solid #000000; border-bottom: 1.00pt solid #000000; border-left: 1px solid #000000; border-right: 1.00pt solid #000000; padding: 0.05cm; text-align: center }
16+ H1.western { font-family: "Arial", sans-serif; font-size: 16pt }
17+ H1.cjk { font-family: "MS Pゴシック"; font-size: 16pt }
18+ H1.ctl { font-family: "Tahoma"; font-size: 16pt }
19+ H2 { margin-bottom: 0.21cm; background: #b3b3b3; border: 1px solid #000000; padding: 0cm }
20+ H2.western { font-family: "Arial", sans-serif; font-size: 14pt; font-style: italic }
21+ H2.cjk { font-family: "MS Pゴシック"; font-size: 14pt; font-style: italic }
22+ H2.ctl { font-size: 14pt; font-style: italic }
23+ H3 { margin-bottom: 0.21cm; background: transparent }
24+ H3.western { font-family: "Arial", sans-serif }
25+ H3.cjk { font-family: "MS Pゴシック" }
26+ -->
27+ </STYLE>
28+</HEAD>
29+<BODY LANG="ja-JP" DIR="LTR">
30+<H1 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>について</H1>
31+<P ALIGN=RIGHT STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">Version
32+1.0_d20060207</SPAN></FONT></P>
33+<P ALIGN=RIGHT STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">2006/2/7
34+copyright seraphy</SPAN></FONT></P>
35+<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
36+</P>
37+<P ALIGN=LEFT STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><FONT COLOR="#666666"><FONT SIZE=2 STYLE="font-size: 9pt">本ドキュメントでは</FONT><FONT FACE="Times New Roman, serif"><FONT SIZE=2 STYLE="font-size: 9pt"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT></FONT><FONT SIZE=2 STYLE="font-size: 9pt">の使い方について説明します。</FONT></FONT></P>
38+<P ALIGN=LEFT STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><FONT COLOR="#666666"><FONT SIZE=2 STYLE="font-size: 9pt">最新の情報については<A HREF="http://sourceforge.jp/projects/easyhashchecker/">プロジェクト・ホームページ</A>にて確認してください。</FONT></FONT></P>
39+<H2 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">1.</SPAN></FONT>本ツールの目的</H2>
40+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>は何らかのメディアを媒介してファイルを移動/複製する際に<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
41+</SPAN></FONT>
42+</P>
43+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm">その<B><U>ファイルが正しく受け渡されたか検証する</U></B>ことを目的とするツールです。</P>
44+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm">つま<SPAN LANG="ja-JP">り</SPAN><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
45+</SPAN></FONT><SPAN LANG="ja-JP">ファイルが破損しているか</SPAN><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
46+</SPAN></FONT><SPAN LANG="ja-JP">改竄されているか</SPAN><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
47+</SPAN></FONT><SPAN LANG="ja-JP">といったことを確認できます。</SPAN></P>
48+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm">ファイルの復元や<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
49+</SPAN></FONT>ファイルを正しく取得するためのツールではありません。</P>
50+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm">インターネットを経由するファイルの受け渡しでは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
51+</SPAN></FONT>しばしば受け取ったファイルが部分的に破損している等の理由により本来の機能を果さないなどの分かりづらいトラブルも多く<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
52+</SPAN></FONT>ファイルが破損なく取得できたことを判断したい場合が多々あります。</P>
53+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm"><SPAN LANG="ja-JP">このような状況において</SPAN><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
54+</SPAN></FONT><SPAN LANG="ja-JP">ファイルの受け取り側が容易にファイルの破損チェックができるようにするために</SPAN><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
55+</SPAN></FONT><SPAN LANG="ja-JP">本ツールは作成さ</SPAN>れました。</P>
56+<H2 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">2.</SPAN></FONT>実現方法</H2>
57+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ファイルの検証は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
58+</SPAN></FONT>ファイルの指紋といえるハッシュ値を取得し<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
59+</SPAN></FONT>配布元のハッシュ値と受け取ったファイルのハッシュ値を比較することで行います。</P>
60+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ハッシュ値のアルゴリズムとして<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">MD5(Message
61+Digest 5) </SPAN></FONT>もしくは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">SHA1(Secure
62+Hash Algorithm 1)</SPAN></FONT>を用います。</P>
63+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">これらのハッシュ<SPAN LANG="ja-JP">値</SPAN>には<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
64+</SPAN></FONT>ファイルのサイズや内容が一部でも変更されると<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
65+</SPAN></FONT>その値もかわる性質があり<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
66+</SPAN></FONT>ハッシュ値が一致しなければ<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
67+</SPAN></FONT>その<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">2</SPAN></FONT>つのファイルは異なる内容である<SPAN LANG="ja-JP">と</SPAN>判断できます。</P>
68+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(</SPAN></FONT>まったく同じハッシュ値でありながら異なる内容である可能性もありますが<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
69+</SPAN></FONT>ほぼゼロと見なされるほど低い確率です。<SPAN LANG="ja-JP">また</SPAN><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
70+</SPAN></FONT>同じ内容であれば同じハッシュ値となることは<SPAN LANG="ja-JP">確実</SPAN>あるため<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
71+</SPAN></FONT>「同じハッシュ値でなければ少なくとも同じ内容ではない」といえます。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">)</SPAN></FONT></P>
72+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ハッシュ値は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
73+</SPAN></FONT>ファイルのサイズに関わらず<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">16</SPAN></FONT>〜<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">20</SPAN></FONT>バイトとコンパクトであり<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
74+</SPAN></FONT>またテキストファイルの形式であるため容易に配布することが可能です。</P>
75+<H2 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">3.</SPAN></FONT>コンセプト/モチベーション</H2>
76+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ファイルの内容が正しいかチェックする方法として広く<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5</SPAN></FONT>や<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">sha1</SPAN></FONT>が使われており<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
77+</SPAN></FONT>これらは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">sha1sum/md5sum</SPAN></FONT>といったツールを利用することで簡単に行うことができます。</P>
78+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">しかし<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
79+Windows XP</SPAN></FONT>等のエンドユーザ向けの環境には<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
80+</SPAN></FONT>これらのツールは存在せず<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
81+</SPAN></FONT>また<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
82+</SPAN></FONT>使うためにコマンドラインの入力が要求されます。</P>
83+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">これは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5sum</SPAN></FONT>や<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">sha1sum</SPAN></FONT>に慣れていない初心者には難しいものと考えらられます。</P>
84+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ハッシュ値の計算や検証を行うフリーソフトも多くあるものの<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
85+</SPAN></FONT>これらは汎用的に使うことが想定されており<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
86+</SPAN></FONT>インストール等の手順が必要です。</P>
87+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">そこで<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
88+</SPAN></FONT>この<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
89+</SPAN></FONT>配布するファイルと一緒に受け渡し先に取得してもらい<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
90+</SPAN></FONT>ダブルクリックするだけでファイルの検証を行い<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
91+</SPAN></FONT>目的を達したあとは使い捨てることができる</P>
92+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">
93+<B>『簡単で軽量』なツール</B>となることを目標としています。</P>
94+<H2 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">4.</SPAN></FONT>対応<FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">OS</SPAN></FONT></H2>
95+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT><SPAN LANG="ja-JP">は</SPAN><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
96+</SPAN></FONT><SPAN LANG="ja-JP">以下の</SPAN><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">OS</SPAN></FONT><SPAN LANG="ja-JP">で動作します</SPAN>。</P>
97+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm"><BR>
98+</P>
99+<UL>
100+ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">Windows
101+ 2000 (Professional/Server)</SPAN></FONT></P>
102+ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">Windows
103+ XP (Home/Professional)</SPAN></FONT></P>
104+ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">Windows
105+ 2003 Server</SPAN></FONT></P>
106+</UL>
107+<P STYLE="margin-bottom: 0cm"><BR>
108+</P>
109+<P STYLE="text-indent: 0.4cm; margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US"><U><B>Windows95/98/ME</B></U></SPAN></FONT><U><B>では動作しません。</B></U></P>
110+<H2 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">5.</SPAN></FONT>特徴</H2>
111+<H3 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">1.</SPAN></FONT>簡単であること。</H3>
112+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ファイルの配布者は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5/sha1</SPAN></FONT>の有用性について理解しており<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
113+</SPAN></FONT>それらのツールを使いこなせるとしても<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
114+</SPAN></FONT>ファイルの受け取り側が<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
115+ </SPAN></FONT>それらの扱いに慣れているとは限りません。</P>
116+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">そこで<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>では<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
117+</SPAN></FONT>ダブルクリックだけでファイルの検証を行えるようにしています。</P>
118+<H3 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">2.</SPAN></FONT>軽量であること。</H3>
119+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ファイルの受け取り側の環境には特別なライブラリ等がインストール済みであることを仮定できないため<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
120+</SPAN></FONT>実行ファイル<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(easyhashchecker.exe)</SPAN></FONT>単体で動作することが必要です。</P>
121+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">また<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
122+</SPAN></FONT>ファイルを配布する際に<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
123+easyhashchecker.exe</SPAN></FONT>が目的とするファイルよりも大きなファイルであっては本末転倒ですから<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
124+ </SPAN></FONT>極力小さなサイズであることが望ましいといえます。</P>
125+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">そこで<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker.exe</SPAN></FONT>は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">15k
126+bytes</SPAN></FONT>程度のコンパクトなものとし<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
127+</SPAN></FONT>システム<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">DLL</SPAN></FONT>以外に依存しないものとします。</P>
128+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(</SPAN></FONT>ただし<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
129+md5/sha1</SPAN></FONT>の計算などに<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">Windows2000/2003/XP</SPAN></FONT>以降の<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">API</SPAN></FONT>を用いるため<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
130+Windows 95/98/ME</SPAN></FONT>では動作しません。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">)</SPAN></FONT></P>
131+<H3 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">3.</SPAN></FONT>独自仕様でないこと</H3>
132+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ファイルの受け渡し先のユーザが初心者ではなく<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5/sha1</SPAN></FONT>などを使い慣れており<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
133+</SPAN></FONT>そのための使い慣れたツールをもっている場合には<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
134+easyhashchecker</SPAN></FONT>を使わずに検証できることが望ましいでしょう。</P>
135+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">あるいは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
136+</SPAN></FONT>ハッシュ値の作成においても<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
137+</SPAN></FONT>すでに使い慣れたツールがある場合には<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
138+</SPAN></FONT>それを使いたいと思うことでしょう。</P>
139+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">そこで<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>が生成/検証する<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5/sha1</SPAN></FONT>のフォーマットは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5sum/sha1sum</SPAN></FONT>と互換性のあるものとします。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(</SPAN></FONT>バイナリモードのみをサポートします。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">)</SPAN></FONT></P>
140+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ただし<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
141+easyhashchecker</SPAN></FONT>が扱うハッシュファイルにはシフト<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">JIS(csWindows31j)</SPAN></FONT>を用いますので<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
142+</SPAN></FONT>日本語ファイル名を使う場合は互換性が損なわれる可能性があります。</P>
143+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>で生成・検証を行う分には日本語ファイル名は問題ありません。</P>
144+<H3 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">4.</SPAN></FONT>フリーであること。</H3>
145+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>は誰でも無償で利用でき<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
146+</SPAN></FONT>再配布も自由であることが望ましいため<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
147+</SPAN></FONT>再配布に制限のある商用ライブラリは用いません。</P>
148+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">また<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
149+</SPAN></FONT>この<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>には<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">GPL(v2)</SPAN></FONT>ライセンスを適用します。</P>
150+<H2 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">6.</SPAN></FONT>使い方</H2>
151+<H3 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">1.
152+</SPAN></FONT>ハッシュファイルの作成</H3>
153+<P STYLE="margin-bottom: 0cm">これから説明するものは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
154+</SPAN></FONT>ファイルを提供する側の作業です。</P>
155+<OL>
156+ <LI><P STYLE="margin-bottom: 0cm">まず<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
157+ </SPAN></FONT>任意の新しいフォルダを作成し<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
158+ </SPAN></FONT>そこに配布したいファイルをコピーします。</P>
159+ <LI><P STYLE="margin-bottom: 0cm">そのフォルダに<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker.exe</SPAN></FONT>をコピーします。</P>
160+ <LI><P STYLE="margin-bottom: 0cm">シフトキーを押しながら<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
161+ easyhashchecker.exe</SPAN></FONT>をダブルクリックします。</P>
162+ <P STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(</SPAN></FONT>シフトキーとコントロールキーを押しながら起動すると<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">sha1</SPAN></FONT>ハッシュの作成となります。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">)</SPAN></FONT></P>
163+ <LI><P STYLE="margin-bottom: 0cm">ハッシュを作成するか問い合わせのダイアログが表示されるため「はい」を選択してください。</P>
164+ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker.exe</SPAN></FONT>のあるフォルダの<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
165+ </SPAN></FONT>すべてのファイルの<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5</SPAN></FONT>ハッシュが作成されます。ファイル名はハッシュ値を計算したファイル名の末尾に「<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">.md5</SPAN></FONT>」をつけたものとなります。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(</SPAN></FONT>既存のハッシュファイルは上書きされますので注意してください。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">)</SPAN></FONT></P>
166+ <LI><P STYLE="margin-bottom: 0cm">ファイルは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
167+ </SPAN></FONT>出来上がったハッシュファイルと<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker.exe</SPAN></FONT>とともに配布してください。</P>
168+ <LI><P STYLE="margin-bottom: 0cm"> ファイルの検証方法を説明したテキストファイルも配布すると良いでしょう。</P>
169+</OL>
170+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><BR>
171+</P>
172+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">なお<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
173+1</SPAN></FONT>つのファイルに対して<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">1</SPAN></FONT>つのハッシュファイルを作成しますが<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
174+</SPAN></FONT>これらは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">1</SPAN></FONT>個のファイルにまとめることもできます。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(</SPAN></FONT>テキストエディタ等で連結してください。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">)</SPAN></FONT></P>
175+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker</SPAN></FONT>はハッシュファイルの拡張子だけを見ており<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
176+</SPAN></FONT>ファイル名は識別しません。</P>
177+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ハッシュファイルの中には複数のハッシュをリストすることができます。</P>
178+<H3 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">2.
179+</SPAN></FONT>ファイルの検証</H3>
180+<P STYLE="margin-bottom: 0cm">これから説明するものは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
181+</SPAN></FONT>ファイルを受け取った側の作業です。</P>
182+<OL>
183+ <LI><P STYLE="margin-bottom: 0cm">まず<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
184+ </SPAN></FONT>受け取ったファイルを新しいフォルダに保存します。</P>
185+ <LI><P STYLE="margin-bottom: 0cm">拡張子が<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5</SPAN></FONT>もしくは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">sha1</SPAN></FONT>のファイルも同じフォルダに保存します。</P>
186+ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker.exe</SPAN></FONT>も同じフォルダに保存します。</P>
187+ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker.exe</SPAN></FONT>をダブルクリックします。</P>
188+ <LI><P STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">easyhashchecker.exe</SPAN></FONT>のあるフォルダの拡張子<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5</SPAN></FONT>もしくは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">sha1</SPAN></FONT>からファイルの指紋を読み取り<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
189+ </SPAN></FONT>同じフォルダにあるファイルの指紋と比較した結果が表示されます。</P>
190+ <LI><P STYLE="margin-bottom: 0cm">検証に成功すると「検証に成功しました」と表示されます。</P>
191+ <LI><P STYLE="margin-bottom: 0cm">検証が成功したら拡張子<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5</SPAN></FONT>もしくは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">sha1</SPAN></FONT>ファイルと<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
192+ easyhashchecker.exe</SPAN></FONT>は不要ですので削除してかまいません。</P>
193+</OL>
194+<P STYLE="margin-bottom: 0cm"><BR>
195+</P>
196+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">もし<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
197+</SPAN></FONT>「<B>検証に失敗しました</B>」というエラーが発生したとき<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
198+</SPAN></FONT>そのダイアログに「ファイルがみつからないか読み込みに失敗しました」という表示がある場合<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
199+</SPAN></FONT>その左側に示される検証対象となるファイルが<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
200+</SPAN></FONT>そのディレクトリに存在しない可能性があります。</P>
201+<P STYLE="margin-bottom: 0cm"><BR>
202+</P>
203+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">「<B>ハッシュ値が一致しません</B>」という表示がある場合<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
204+</SPAN></FONT>ファイルの検証を行った結果<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
205+</SPAN></FONT>そのファイルが元ファイルのハッシュ値と一致しない<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
206+</SPAN></FONT>つまり<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
207+</SPAN></FONT>そのファイルが元ファイルとは違う内容になっていることを意味しています。</P>
208+<P STYLE="margin-bottom: 0cm"><BR>
209+</P>
210+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">「<B>ダイジェストファイル</B><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US"><B>(*.md5/*.sha1)</B></SPAN></FONT><B>がカレントディレクトリに</B><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US"><B>1</B></SPAN></FONT><B>つも見つからないため検証できません</B>」というエラーが発生した場合は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
211+easyhashchecker.exe</SPAN></FONT>の起動時のカレントディレクトリに<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
212+</SPAN></FONT>拡張子<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5</SPAN></FONT>もしくは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">sha1</SPAN></FONT>のファイルがないため検証できないことを意味します。</P>
213+<P STYLE="margin-bottom: 0cm">このエラーが発生した場合は拡張子<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">md5/sha1</SPAN></FONT>のファイルがあることを確認してください。</P>
214+<H2 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">7.</SPAN></FONT>ソースコード</H2>
215+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ソースコードは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">VisualC++.NET
216+2003</SPAN></FONT>で作成されています。</P>
217+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">必要に応じて<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">GPL(v2)</SPAN></FONT>に従って修正してください。</P>
218+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">バグ等があれば<A HREF="http://sourceforge.jp/projects/easyhashchecker/">プロジェクトホームページ</A>のバグトラッキングに報告していただけると幸いです。</P>
219+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">また<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
220+</SPAN></FONT>もし修正された場合には<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
221+</SPAN></FONT>必ず<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
222+</SPAN></FONT>ソースコードを<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">zip</SPAN></FONT>等にアーカイブしたものをパッチとして投稿してください。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(</SPAN></FONT>「パッチ」である必要はありません。丸ごと一式でかまいません。<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">)</SPAN></FONT></P>
223+<H2 CLASS="cjk"><FONT FACE="Arial, sans-serif"><SPAN LANG="en-US">8.</SPAN></FONT>ライセンス</H2>
224+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">このプログラムはフリーウェアです。</P>
225+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">あなたはこれを<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
226+</SPAN></FONT>フリーソフトウェア財団によって発行された <FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">GNU
227+</SPAN></FONT>一般公衆利用許諾契約書<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">(</SPAN></FONT>バージョン<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">2)</SPAN></FONT>の定める条件の下で再頒布または改変することができます。</P>
228+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">このプログラムは有用であることを願って頒布されますが<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
229+*</SPAN></FONT>全くの無保証<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">*
230+</SPAN></FONT>です。</P>
231+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">商業可能性の保証や特定の目的への適合性は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
232+</SPAN></FONT>言外に示されたものも含め全く存在しません。</P>
233+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">詳しくは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">GNU
234+</SPAN></FONT>一般公衆利用許諾契約書をご覧ください。</P>
235+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><BR>
236+</P>
237+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">著作権は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">seraphy</SPAN></FONT>にあります。</P>
238+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ライセンスは<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">GPL(v2)</SPAN></FONT>です。</P>
239+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">商用<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
240+</SPAN></FONT>非商用ともに自由にご利用<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
241+</SPAN></FONT>再配布いただいてかまいません。</P>
242+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">ソースコードを修正する場合は<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">GPL(v2)</SPAN></FONT>に従ってください。</P>
243+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">実行ファイルのみの再配布も可能ですが<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
244+</SPAN></FONT>その場合は以下の<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">URL</SPAN></FONT>にアクセスできるように記載してください。</P>
245+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm"><BR>
246+</P>
247+<P STYLE="text-indent: 0.37cm; margin-bottom: 0cm">このソフトウェアに関する詳細<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
248+</SPAN></FONT>および問い合わせについては<FONT FACE="Times New Roman, serif"><SPAN LANG="en-US">,
249+</SPAN></FONT>
250+</P>
251+<P ALIGN=CENTER STYLE="margin-bottom: 0cm"><FONT FACE="Times New Roman, serif"><SPAN LANG="en-US"><A HREF="http://sourceforge.jp/projects/easyhashchecker/">http://sourceforge.jp/projects/easyhashchecker/
252+</A></SPAN></FONT>で確認してください。</P>
253+<P ALIGN=LEFT STYLE="margin-bottom: 0cm"><BR>
254+</P>
255+</BODY>
256+</HTML>
\ No newline at end of file
--- trunk/docs/エンドユーザ向け説明雛型.txt (nonexistent)
+++ trunk/docs/エンドユーザ向け説明雛型.txt (revision 4)
@@ -0,0 +1,12 @@
1+???????t?@?C?????擾???????m?F????菇?ɂ‚??Đ??????܂??B
2+
3+?V?????t?H???_???쐬???A?????Ɉȉ??̃t?@?C???????ׂĊi?[???Ă????????B
4+
5++ ((?????ɔz?z????t?@?C?????L?q????))
6++ ((?????ɔz?z????t?@?C???ɑ΂???md5/sha1?t?@?C?????L?q????))
7++ easyhashchecker.exe
8+
9+?‚??ɁAeasyhashchecker.exe???_?u???N???b?N???Ă????????B
10+
11+?t?@?C????????Ɏ擾????Ă???ꍇ?́u???؂ɐ??????܂????v?Ƃ????_?C?A???O?{?b?N?X???\??????܂??B
12+?????A?u?n?b?V???l????v???܂???v?Ƃ????G???[???\?????ꂽ?ꍇ?̓t?@?C???????????擾?ł??Ă??Ȃ????Ƃ??Ӗ????܂??B
--- trunk/Utility.h (nonexistent)
+++ trunk/Utility.h (revision 4)
@@ -0,0 +1,7 @@
1+#pragma once
2+
3+void ShowError(const DWORD errcode) throw();
4+
5+BSTR ReadFile(const LPCWSTR fileName) throw();
6+
7+size_t HexToBin(const LPCWSTR text, LPBYTE buf, const size_t buf_siz) throw();
--- trunk/DigestFormatParser.h (nonexistent)
+++ trunk/DigestFormatParser.h (revision 4)
@@ -0,0 +1,20 @@
1+#pragma once
2+
3+#include <atlbase.h>
4+
5+#include "DigestItem.h"
6+
7+class DigestFormatParser
8+{
9+ DigestFormatParser(const DigestFormatParser&); //<! 実装なし
10+ DigestFormatParser& operator=(const DigestFormatParser&); //<! 実装なし
11+
12+public:
13+ DigestFormatParser(DigestItemPtrList& list);
14+ ~DigestFormatParser();
15+
16+ BOOL ParseDigest(const LPCSTR text, const ALG_ID algoId) throw();
17+
18+private:
19+ DigestItemPtrList& list_;
20+};
--- trunk/Digest.cpp (nonexistent)
+++ trunk/Digest.cpp (revision 4)
@@ -0,0 +1,105 @@
1+#include "stdafx.h"
2+
3+#include "Digest.h"
4+
5+////
6+
7+DigestContext::DigestContext() throw()
8+ : hProv_(NULL)
9+{
10+}
11+
12+DigestContext::~DigestContext() throw()
13+{
14+ if (hProv_)
15+ ::CryptReleaseContext(hProv_, 0);
16+}
17+
18+BOOL DigestContext::Create() throw()
19+{
20+ ATLASSERT(!hProv_);
21+ return ::CryptAcquireContext(
22+ &hProv_,
23+ NULL,
24+ NULL,
25+ PROV_RSA_FULL,
26+ CRYPT_VERIFYCONTEXT
27+ );
28+}
29+
30+////
31+
32+Digest::Digest(DigestContext& ctx) throw ()
33+ : ctx_(ctx)
34+ , hHash_(NULL)
35+{
36+ ATLASSERT(ctx.hProv_);
37+}
38+
39+Digest::~Digest() throw()
40+{
41+ if (hHash_)
42+ ::CryptDestroyHash(hHash_);
43+}
44+
45+BOOL Digest::Create(const ALG_ID algo_id) throw()
46+{
47+ ATLASSERT(!hHash_);
48+ return ::CryptCreateHash(ctx_.hProv_, algo_id, 0, 0, &hHash_);
49+}
50+
51+BOOL Digest::Update(LPBYTE data, DWORD len) throw()
52+{
53+ ATLASSERT(hHash_);
54+ return ::CryptHashData(hHash_, data, len, 0);
55+}
56+
57+size_t Digest::GetHashSize() throw()
58+{
59+ ATLASSERT(hHash_);
60+
61+ DWORD len;
62+ DWORD sz = sizeof(DWORD);
63+ if (!::CryptGetHashParam(hHash_, HP_HASHSIZE, (BYTE*)&len, &sz, 0))
64+ return 0;
65+ return len;
66+}
67+
68+BOOL Digest::GetHashValue(LPBYTE data, DWORD len) throw()
69+{
70+ ATLASSERT(hHash_);
71+ return ::CryptGetHashParam(hHash_, HP_HASHVAL, data, &len, 0);
72+}
73+
74+///
75+
76+BOOL CalcFileDigest(const LPCWSTR fileName, Digest& digest) throw()
77+{
78+ const size_t buffer_size = 4096;
79+ BYTE buf[buffer_size];
80+
81+ HANDLE fh = ::CreateFile(
82+ fileName,
83+ GENERIC_READ,
84+ FILE_SHARE_READ,
85+ NULL,
86+ OPEN_EXISTING,
87+ FILE_FLAG_SEQUENTIAL_SCAN,
88+ NULL
89+ );
90+ if (fh == INVALID_HANDLE_VALUE)
91+ return FALSE;
92+
93+ CHandle hFileAutoCloser(fh);
94+
95+ DWORD rd;
96+ BOOL ret;
97+ while (ret = ::ReadFile(fh, buf, buffer_size, &rd, NULL))
98+ {
99+ if (rd == 0)
100+ break;
101+ if (!digest.Update(reinterpret_cast<LPBYTE>(buf), rd))
102+ return FALSE;
103+ }
104+ return ret;
105+}
--- trunk/Digest.h (nonexistent)
+++ trunk/Digest.h (revision 4)
@@ -0,0 +1,46 @@
1+#pragma once
2+
3+#include <Wincrypt.h>
4+#include <atlbase.h>
5+
6+class DigestContext
7+{
8+ friend class Digest;
9+
10+ DigestContext(const DigestContext& other) throw(); //<! 実装なし
11+ DigestContext& operator=(const DigestContext& other) throw(); //<! 実装なし
12+
13+public:
14+ DigestContext() throw();
15+ ~DigestContext() throw();
16+
17+ BOOL Create() throw();
18+
19+protected:
20+ HCRYPTPROV hProv_;
21+};
22+
23+class Digest
24+{
25+ Digest(const Digest&); //<! 実装なし
26+ Digest& operator=(const Digest&); //<! 実装なし
27+
28+public:
29+ Digest(DigestContext& ctx) throw ();
30+ ~Digest() throw();
31+
32+ BOOL Create(const ALG_ID algo_id) throw();
33+
34+ BOOL Update(LPBYTE data, DWORD len) throw();
35+
36+ size_t GetHashSize() throw();
37+
38+ BOOL GetHashValue(LPBYTE data, DWORD len) throw();
39+
40+private:
41+ DigestContext& ctx_;
42+
43+ HCRYPTHASH hHash_;
44+};
45+
46+BOOL CalcFileDigest(const LPCWSTR fileName, Digest& digest) throw();
--- trunk/main.cpp (nonexistent)
+++ trunk/main.cpp (revision 4)
@@ -0,0 +1,66 @@
1+// StaticPolymorphism.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
2+//
3+
4+#include "stdafx.h"
5+
6+#include "Utility.h"
7+#include "Digest.h"
8+#include "VerifyOperation.h"
9+
10+#if !VERIFY_ONLY
11+#include "MakeOperation.h"
12+#endif // !VERIFY_ONLY
13+
14+int APIENTRY _tWinMain(HINSTANCE hInstance,
15+ HINSTANCE hPrevInstance,
16+ LPTSTR lpCmdLine,
17+ int nCmdShow)
18+{
19+ DigestContext ctx;
20+ if (!ctx.Create())
21+ {
22+ ShowError(::GetLastError());
23+ return 1;
24+ }
25+
26+#if !VERIFY_ONLY
27+
28+ const bool makeMode = ((::GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0);
29+ const bool makeType = ((::GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0);
30+
31+ if (makeMode)
32+ {
33+ int confirm;
34+
35+ if (makeType)
36+ confirm = ::MessageBox(
37+ NULL,
38+ L"カレントディレクトリ上のファイルのSHA1ハッシュを作成しますか?\r\n"
39+ L"(MD5ハッシュを作成する場合はSHIFTキーのみ押しながら起動します。)",
40+ L"ハッシュ作成の確認",
41+ MB_ICONQUESTION | MB_YESNO
42+ );
43+ else
44+ confirm = ::MessageBox(
45+ NULL,
46+ L"カレントディレクトリ上のファイルのMD5ハッシュを作成しますか?\r\n"
47+ L"(SHA1ハッシュを作成する場合はSHIFT+CTRLキーを押しながら起動します。)",
48+ L"ハッシュ作成の確認",
49+ MB_ICONQUESTION | MB_YESNO
50+ );
51+
52+ if (confirm == IDYES)
53+ return MakeOperation(
54+ ctx,
55+ makeType ? CALG_SHA1 : CALG_MD5,
56+ makeType ? L"sha1" : L"md5"
57+ );
58+
59+ return 0;
60+ }
61+
62+#endif // !VERIFY_ONLY
63+
64+ return VerifyOperation(ctx);
65+}
66+
--- trunk/VerifyOperation.cpp (nonexistent)
+++ trunk/VerifyOperation.cpp (revision 4)
@@ -0,0 +1,144 @@
1+#include "stdafx.h"
2+
3+#include "VerifyOperation.h"
4+#include "Utility.h"
5+
6+void ReadCurrentDirectory(const LPCWSTR fname, const ALG_ID algId, DigestFormatParser& parser) throw()
7+{
8+ WIN32_FIND_DATA findData;
9+ HANDLE hFind = ::FindFirstFile(fname, &findData);
10+ if (hFind == INVALID_HANDLE_VALUE)
11+ return;
12+
13+ while(1)
14+ {
15+ if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
16+ {
17+ CComBSTR fileName(findData.cFileName);
18+
19+ BSTR buf = ReadFile(fileName);
20+ if (!buf)
21+ {
22+ ShowError(::GetLastError());
23+ break;
24+ }
25+ CComBSTR bufAutoDeleter;
26+ bufAutoDeleter.Attach(buf);
27+
28+ if (!parser.ParseDigest(reinterpret_cast<LPCSTR>(buf), algId))
29+ {
30+ ::MessageBox(
31+ NULL,
32+ L"ファイルのフォーマットが不正であるか解析に失敗しました。",
33+ fileName,
34+ MB_ICONERROR | MB_OK
35+ );
36+ }
37+ }
38+
39+ if (!::FindNextFile(hFind, &findData))
40+ {
41+ const DWORD err = ::GetLastError();
42+ if (err == ERROR_NO_MORE_FILES)
43+ break;
44+ else
45+ ShowError(err);
46+ }
47+ }
48+ ::FindClose(hFind);
49+}
50+
51+int VerifyOperation(DigestContext& ctx) throw()
52+{
53+ DigestItemPtrList list;
54+ DigestFormatParser parser(list);
55+
56+ ReadCurrentDirectory(L"*.md5", CALG_MD5, parser);
57+ ReadCurrentDirectory(L"*.sha1", CALG_SHA1, parser);
58+
59+ if (list.GetCount() == 0)
60+ {
61+ ::MessageBox(
62+ NULL,
63+ L"ダイジェストファイル(*.md5/*.sha1)がカレントディレクトリに1つも存在しないため検証できません。\r\n\r\n"
64+ L"(検証するのではなく、ダイジェストファイルを新規に作成する場合は\r\nSHIFTキー、もしくはSHIFT+CTRLキーを押しながら起動します。)",
65+ NULL,
66+ MB_ICONERROR | MB_OK
67+ );
68+ return 0;
69+ }
70+
71+ bool occureError = false;
72+ CComBSTR mes;
73+
74+ POSITION pos = list.GetHeadPosition();
75+ while (pos)
76+ {
77+ DigestItemPtr itemPtr = list.GetNext(pos);
78+
79+ Digest digest(ctx);
80+ if (!digest.Create(itemPtr->getAlgoId()))
81+ {
82+ ShowError(::GetLastError());
83+ mes.Empty();
84+ break;
85+ }
86+
87+ mes.Append(itemPtr->GetName());
88+ mes.Append(L" - ");
89+
90+ if (!CalcFileDigest(itemPtr->GetName(), digest))
91+ {
92+ mes.Append(L"ファイルが見つからないか、読み込みに失敗しました。");
93+ occureError = true;
94+ }
95+ else
96+ {
97+ const size_t siz = digest.GetHashSize();
98+ const size_t max_siz = 64;
99+ ATLASSERT(siz < max_siz);
100+
101+ BYTE verifyHash[max_siz];
102+ BYTE fileHash[max_siz];
103+
104+ if (!digest.GetHashValue(verifyHash, static_cast<DWORD>(siz)))
105+ {
106+ ShowError(::GetLastError());
107+ mes.Empty();
108+ break;
109+ }
110+
111+ const size_t cnv_siz = HexToBin(
112+ itemPtr->GetHash(),
113+ reinterpret_cast<LPBYTE>(fileHash),
114+ siz
115+ );
116+
117+ if (cnv_siz == siz && memcmp(fileHash, verifyHash, siz) == 0)
118+ mes.Append(L"OK");
119+ else
120+ {
121+ mes.Append(L"ハッシュ値が一致しません。");
122+ occureError = true;
123+ }
124+ }
125+
126+ mes.Append(L"\r\n");
127+ }
128+
129+ if (mes.Length())
130+ {
131+ const LPCWSTR messageTitle =
132+ occureError ? L"検証に失敗しました。": L"検証に成功しました。";
133+ mes.Append(L"\r\n");
134+ mes.Append(messageTitle);
135+ ::MessageBox(
136+ NULL,
137+ mes,
138+ messageTitle,
139+ occureError ? ( MB_ICONERROR | MB_OK ) : ( MB_ICONINFORMATION | MB_OK )
140+ );
141+ }
142+
143+ return 0;
144+}
--- trunk/stdafx.cpp (nonexistent)
+++ trunk/stdafx.cpp (revision 4)
@@ -0,0 +1,8 @@
1+// stdafx.cpp : 標準インクルード StaticPolymorphism.pch のみを
2+// 含むソース ファイルは、プリコンパイル済みヘッダーになります。
3+// stdafx.obj にはプリコンパイル済み型情報が含まれます。
4+
5+#include "stdafx.h"
6+
7+// TODO: このファイルではなく、STDAFX.H で必要な
8+// 追加ヘッダーを参照してください。
--- trunk/VerifyOperation.h (nonexistent)
+++ trunk/VerifyOperation.h (revision 4)
@@ -0,0 +1,10 @@
1+#pragma once
2+
3+#include <wincrypt.h>
4+#include <atlbase.h>
5+
6+#include "DigestFormatParser.h"
7+#include "Digest.h"
8+
9+void ReadCurrentDirectory(const LPCWSTR fname, const ALG_ID algId, DigestFormatParser& parser) throw();
10+int VerifyOperation(DigestContext& ctx) throw();
旧リポジトリブラウザで表示