プログラミング関係リンク・C/C++/API微妙Tips





・リンク


Borland C++ Builder関係
Borland ホームページ
BuilderML
新BuilderML
Delphian World コンポーネント検索 
MSDN


API
Classょょょ BuilderとAPIの役立つTips
読みやすいAPI解説


暗号
SHA-1元資料(FIPS180-1)
SecureHashStandard SHAに関する資料
ステガノグラフィー
IBMのセキュリティページ・暗号の動向
RSAの基礎(細かい解説)
RSAと他のいくつかの話題
RSA SecurityPKCS
サルにもわかるRSA(入門用、他のコンテンツで割と笑える)
OpenSSL
BlowFish
Rijndeal(英語)
Rijndeal(英語・ソースあり)


圧縮
BrockSortingとRangeCorderの入門・ソース(どぅぷらぷら)
DeepFreezer (「データ圧縮の基礎」など基礎読み物あり)
GCA (高圧縮)
UPX (exe compression)


乱数
IBM記事
DIEHARD
Mersenne Twister Home Page 2^19937-1周期の良質・高速な乱数
パスワード評価ツール ちょっと楽しめます


良質なソースや高度なところ
技術計算用Cソース
とってもごはん 上のGCAもここのコンテンツ。非常に高度かつ良質です。
やねうらお氏のとこ 高度。鬼知識。神。


(備考)
QueryPerformanceCountの問題
timeGetTimeの誤差について


ツール類
窓の杜 (あらゆるオンラインソフト)
バイナリエディタPowerWitch
逆アセンブラDispe
めも電卓 (少々面倒な計算をしたい時に非常に役立つ)


その他・一般
WiredNEWS テクノロジー関係の最新ニュースが日本語で読める。
C FAQ日本語訳
トレンドマイクロ(ウイルス検索など)
セキュリティセキュリティレクチャー
TCP/IPポート番号一覧 
Discover SOFT N88-BASICとほぼ上位互換の、Windowsアプリケーション開発用コンパイラ(フリー)
.NETフレームワーク概要リンク
猫でもわかるプログラミング 
とほほのperl入門


法律関係
法令データ提供システム(総務省 行政管理局)
不正アクセス防止法
経済産業省の暗号ソフト規制緩和についての情報(04 Apr 2001 00:43:25 )
経済産業省の暗号ソフト規制緩和についての情報(04 Apr 2001 00:51:10 )






・テクニック及び知識

コンパイラ依存とかの細かいことは責任持ちません(笑)が、まあどれでもほぼ同じ動作と思います。
以下は少なくともBorland C++ Builder+Win32 APIで動作します。


暗号ソフトを作るには?

暗号ソフトをデザインしてみる


暗号に関する輸出規制については?

基本的に、暗号ソフト・ソースの輸出やネットワーク上での公開のためには、外国為替及び外国貿易法に基づき大臣の許可が必要である。
以前は特に制限が厳しかったが、緩和されたそうなので以下の情報を参照。

経済産業省の暗号ソフト規制緩和についての情報(04 Apr 2001 00:43:25 )

(概要)
 WAにおける合意を受けて、通商産業省告示(輸出貿易管理令第4条第1項第5号の規定に基づき、通商産業大臣が告示で定める貨物を定める件)により、これまで許可の対象外となっていた大量市販暗号製品に係る要件のうち、対称アルゴリズムの鍵長の要件を撤廃。
 
 これにより、鍵長が64ビットを超える対称アルゴリズムを用いる暗号製品であっても、購入に際し何ら制限を受けず、暗号機能が使用者によって変更ができない等の要件を満たせば、規制対象外となる。具体的には、これらの要件を満たせば、鍵長が64ビットを超える対称アルゴリズムを有するブルートゥース等の暗号製品であっても、今後は規制対象外となる。
 
 また、今回の措置により、これまで第2種一般包括輸出許可の対象となっていた暗号製品の一部が規制対象外となることから、暗号製品に係る第2種一般包括許可の適用範囲の改正を行った。
 
(改正部分)
・輸出貿易管理令第4条第1項第5号の規定に基づき、通商産業大臣が告示で定める貨物を定める件(平成11年通商産業省告示第353号)(改正)
・その他包括関係通達(改正)


経済産業省の暗号ソフト規制緩和についての情報(04 Apr 2001 00:51:10 )

(概要)
 使用に際して供給者の技術支援が不要であるように設計されたプログラム(暗号プロ
グラムの場合には、技術支援が不要であり、かつ暗号機能が変更できず、鍵長が64ビッ
トを超えないもの)をネットワーク上にアップロードすることにより、不特定多数の者
が何ら制限されず入手可能な状態とする行為については、外為法第25条第1項の役務
取引許可を要しないものとする。
 
 また、購入に際して何ら制限なく販売(有償)される等の暗号製品・プログラムに加
え、無償で提供されるものについても、有償のものと同様に扱う
こととし、通商産業大
臣の許可を不要とする又は包括許可の対象とするとの規制緩和を実施。
 
 これらにより、インターネットを通じたプログラムの提供について、大幅に規制が緩
されることとなる。
 
(改正部分)
・外国為替及び外国貿易法第25条第1項第1号の規定に基づき許可を要する技術を提
 供する取引について(通達改正)
・一般包括輸出許可等について(輸出注意事項8第21号、改正)


要約。
・購入に際し何ら制限を受けず、暗号機能が使用者によって変更ができない等の要件を満たした対称鍵暗号法の大量市販暗号製品については鍵長の制限なし。
・技術支援が不要であり、かつ暗号機能が変更できず、鍵長が64ビットを超えないものをネットワーク上にアップロードすることにより、不特定多数の者が何ら制限されず入手可能な状態とする行為については、外為法第25条第1項の役務取引許可を要しない。
・購入に際して何ら制限なく販売(有償)される等の暗号製品・プログラムに加え、無償で提供されるものについても、有償のものと同様に扱う。

暗号ルーチンのソースコードを公開することは、「暗号機能が変更できる」のでダメらしい(たくさん公開されてるが・・・笑)。
いぜん、鍵長64ビットを超える暗号システムをネットワークを通じて公開することはダメらしい(これもだが・・・)。
アメリカ等の方式に比べて、日本は「状況による」ことが多いようだ。個別に審査される必要がある場合が多いらしい。
どこからが規制にひっかかるかが難しい。
単純に乱数とのXORを取るルーチンでも、擬似乱数の周期を増やせば簡単に鍵長64ビット超えるように改良できるしなぁ。
とりあえず、鍵長を64ビット以下に固定した暗号の、通常のプログラムをアップするのはOKなようだ(全然守られてないですが・・・涙)。

なお、上の記述には間違いがない保証はしない。したがって上の記述を鵜呑みにして行動して違反した場合などの損害に、とつげき東北は一切責任を負わない。
情報が少なくて(分散していて)集めにくく、間違っているかもしれない。もし詳しい人がいたらぜひ教えてください。
当然、とつげき東北は違法な行為をしたくないので、このガイドラインを常に守る方針でいきます。


「ランダムな乱数」「良質な乱数」を得るには?

こちらを参照


高分解能パフォーマンスカウンタの使い方

timeGetTimrなどでは充分な精度の時間処理ができない。
パフォーマンスカウンタを使おう。

BOOL QueryPerformanceFrequency(lpliPerformanceFreq)
LARGE_INTEGER *lpliPerformanceFreq; /* 現在の頻度のアドレス */

QueryPerformanceFrequency関数は、 高分解能パフォーマンス カウンタが存在する場合に、 その頻度を取得します。

パラメータ 説明
lpliPerformanceFreq 関数が現在のパフォーマンス カウンタの頻度 (カウント毎秒単位) を設定する変数を指すポインタです。インストールされているハードウェアが高分解能パフォーマンス カウンタをサポートしていない場合、 lpliPerformanceFreqは0に設定されます。

戻り値
インストールされているハードウェアが高分解能パフォーマンス カウンタをサポートしている場合は、 TRUEを返します。それ以外の場合は、 FALSEを返します。拡張エラー情報を取得するには、 GetLastError関数を使います。


BOOL QueryPerformanceCounter(lpliPerformanceCount)
LARGE_INTEGER *lpliPerformanceCount; /* 現在のカウンタ値のアドレス */

QueryPerformanceCounter関数は、 高分解能パフォーマンス カウンタが存在する場合に、 その現在値を取得します。

パラメータ 説明
lpliPerformanceCount 関数が現在のパフォーマンス カウンタ値 (カウント単位) を設定する変数を指すポインタです。インストールされているハードウェアが高分解能パフォーマンス カウンタをサポートしていない場合、
lpliPerformanceCountは0に設定されます。


戻り値
インストールされているハードウェアが高分解能パフォーマンス カウンタをサポートしている場合は、 TRUEを返します。それ以外の場合は、 FALSEを返します。拡張エラー情報を取得するには、 GetLastError関数を使います。

実装例

//{処理}にかかる時間を計測するコード

_LARGE_INTEGER l; //高分解能パフォーマンスカウンタのカウント値参照用
DWORD t; //同カウント値保持用
QueryPerformanceCounter(&l); //開始時刻
t=l.LowPart;

//時間を計測する処理を記述

QueryPerformanceCounter(&l); //終了時刻
ShowMessage(l.LowPart-t);


ファイルをメモリ上で直接いじるAPIを使うには?

一気にメモリ上に読んでしまっていじる方法。
逐次読み込み式より早く、また一括で全体のデータを利用しなければならない場合に便利。
テキストファイルなら、\0を最後につけて、全体をAnsiStringに代入することも可能。

実装例:

AnsiString Filenamestr="test.txt";
char filename[MAX_PATH];
strcpy(filename,Filenamestr.c_str());
char *cBUF;
HANDLE hFILE;
DWORD wFSIZE,wGSIZE;

// ファイルを開く
hFILE = ::CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
// ファイルサイズの取得
wFSIZE = ::GetFileSize(hFILE,NULL);
// ファイルサイズが0xFFFFFFFFの場合はファイルオープン失敗
if (wFSIZE != 0xFFFFFFFF) {
// メモリを確保する
cBUF = (char*)malloc(wFSIZE + 1);
// ファイルを一括で読込む
::ReadFile(hFILE,cBUF,wFSIZE,&wGSIZE,NULL);
// ファイルを閉じる
::CloseHandle(hFILE);

//・・・処理・・・
//cBUFがデータの先頭を指すポインタ。
//よ〜わからん人は、おなじみのfopenを使って、例えば次のようにやってみるといい。
//APIリファレンスを見てればわかると思うけど。
FILE *out;
out2=fopen("test2.txt","wb");
fwrite(cBUF,1,wFSIZE,out);
fclose(out);
//これで「test.txt」が「test2.txt」にコピーされる(stdio.hをインクルードすること)。

// メモリの解放
free(cBUF);
}


指定ディレクトリ以下に存在する全てのファイルを列挙するには?(C++Builder)

WIN32APIのFindFirstFile関数等をラップするVCLのFindFirst関数を再帰的に適用する。
なお、ヘルプにある属性以外の属性のファイルもあるようで、全てのファイルを列挙するためには、ヘルプに記述されている「全てのファイル」属性0x3fではなく0xffを用いる必要がある(;´Д`)。
ディレクトリ下のファイル数判定のための変数など入れてあるが、ここでは使っていない。各自カスタマイズして使うこと。
下の実装例は、c:\以下の全てのファイルをLabel1に順に表示するもの。

実装例:(各自適当にカスタマイズして用いること)

static int filename=0;

int TForm1::EnumDirectoryFile(AnsiString dir) //dirとして与えられたディレクトリ下の全てのファイルを列挙する
{
int internalfilenum=0;
AnsiString zenkaidirstr;
TSearchRec sr;
static int iAttributes = 0xff;
if (FindFirst(dir+"\\*.*", iAttributes, sr) == 0)
{
do
{
if ((sr.Attr & iAttributes) == sr.Attr)
{
if((sr.Name!="..")&&(sr.Name!="."))
{
if(sr.Attr&0x10)
{
EnumDirectoryFile(dir+"\\"+sr.Name);
}
else
{
filenum++;
internalfilenum++;
Label1->Caption=(dir+"\\"+sr.Name);//表示
}
}
}
} while (FindNext(sr) == 0);
FindClose(sr);
}
Application->ProcessMessages();//表示の更新
return internalfilenum;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
EnumDirectoryFile("c:");
ShowMessage(filenum);
}



時々使いそうな関数
毎回何か組むたびに作ってる気がするようなルーチンを。



・微妙な小技

「分母が0の時分子も0になる」条件の下で0除算を避けるには?

X/Y を X/(Y+DELTA) に置き換える。DELTAは、Yに対して充分小さい負の小数。例えば-0.001。
リーチ何回中何回成功したか(リーチ成功率)などの集計の場合には、リーチ数自体が0である場合、リーチ成功率も「0」と表示してしまえば良いと思われる。しかもこれ系のデータは大量に出すので、いちいち分母で場合分けするのはめんどう。
そこで上のようにする。
Yが0の時も0除算にならずに計算は実行されるが、「〜回中〜回」のように、分母が0なら必ず分子も0になるような計算であれば、結局結果は0になる。
ただしDELTAを正にすると、型によっては大きな誤差になるので注意(例えば結果がintなら1/1.001=0になるね)。
また「分母が0の時分子も0になる」条件のない計算には使えないことは明らか。
#define DELTA -0.001 などにしておくと便利。


「分母が0の時分子も0になる」条件がない場合に0除算を避けるには?

Z=X/Y を Z=Y?(X/Y):Zzero に置き換える。ZzeroはYが0の時にZに代入したい値。
Yが真(0以外)である時Zの値は(X/Y)となり、そうでない時(Y=0)Zの値はZzeroとなる。
集計ツールで全ての「率計算」ごとにif文を書いていたらソースが汚くなる。



・よくあるTips(ほぼ個人メモ用)

フォームのメモリを動的に確保するには?一応以下のコードはC++Builder専用)

Formxという名前のフォームを作成
Formx = new TForm(this);

メモリ解放
void __fastcall TFormx::FormClose(TObject *Sender, TCloseAction &Action){Action = caFree;}

プロジェクト−オプション−フォーム で、Formxを「選択可能なフォーム」にしておくこと。


TEditBoxで数値の入力以外を蹴るには?

各エディットボックスの OnKeyPressイベントに、以下を追加する。

if((Key!=VK_BACK)&&(Key!=VK_DELETE)&&( Key < '0' || Key > '9' )) Key = NULL;