人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

現在、Win32アプリを作っています。試用版としてリリースしたいのですが、どのように試用期限のチェックをしようか悩んでいます。ぜひ、サンプルコード本体を貼り付けていただくか、サンプルコードを掲載しているサイトを教えていただけますか。ピンポイントの回答には高得点を差し上げます。宜しく御願い致します。

●質問者: er7
●カテゴリ:コンピュータ ゲーム
✍キーワード:Win32 アプリ コード サイト ピンポイント
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

1 ● kazu1107
●23ポイント

#include <iostream>

const int key[] = {20263006,9056919,28901031,34037154,41412405};

const int WORDS=5;

const int DIGITS=5;

// キーチェック関数

inline bool KeyCheck(const char** str){

int buf[WORDS] = {0,0,0,0,0};

int i;

for(i=0;i<WORDS;i++){// 区切りの数だけループ</p>

for(int j=0,wait=1;j<DIGITS;j++){// 桁の数だけループ</p>

char c;

if(str[i][j] >= '0' && str[i][j]<= '9'){

c = str[i][j]-'0';

}else if(str[i][j] >= 'A' && str[i][j]<= 'Z'){

c = str[i][j]-'A'+10;

// 今回はアルファベットの大文字小文字は区別してません

}else if(str[i][j] >= 'a' && str[i][j]<= 'z'){

c = str[i][j]-'a'+10;

}else c = 0;

buf[i] += c * wait;

wait *= 36;

}

if(key[i] != buf[i])

break;

}

return i==WORDS ? true : false;

}


// キーからコードを取得

inline void OutCode(const char** str){

int buf[WORDS] = {0,0,0,0,0};

int i;

for(i=0;i<WORDS;i++){// 区切りの数だけループ</p>

for(int j=0,wait=1;j<DIGITS;j++){// 桁の数だけループ</p>

char c;

if(str[i][j] >= '0' && str[i][j]<= '9'){

c = str[i][j]-'0';

}else if(str[i][j] >= 'A' && str[i][j]<= 'Z'){

c = str[i][j]-'A'+10;

// 今回はアルファベットの大文字小文字は区別してません

}else if(str[i][j] >= 'a' && str[i][j]<= 'z'){

c = str[i][j]-'a'+10;

}else c = 0;

buf[i] += c * wait;

wait *= 36;

}

}

// デバッグコード(認証キーから得た認証コード値を表示する)

std::cout<< buf[0] << " " << buf[1] << " "

<< buf[2] << " " << buf[3] << " " << buf[4] << std::endl;

}




int main(){

// 1つ5桁の5つのキーコード(

const char* teststr[WORDS] = {"A1B2C","3D4E5","F6G7H","I8J9K","L0MNO"};

std::cout<< "認証..." << (KeyCheck(teststr)?"Ok":"No") << std::endl;

OutCode(teststr);

while(1);

return 0;

}


WindowsにこういうのをチェックするAPIがあるのかどうか知らないので、適当に組んでみましたけどどうでしょうか?

あまりその手のテクニックに詳しくないので、どうすれば安全な仕組みになるのかいまいちわかりません。大体これぐらいなら一般にはわからないだろって程度です。

今回は内容5桁×5ワード×36(A?Z + 0?9)の組み合わせで認証しています。

プログラム側ではキーを5つのint型として保持しているので、ワードを直書きするよりは特定しにくくなるかと。

さらにチェックコードをインライン関数にすることで、認証ルーチンも特定しにくくなると思います。


やっちゃいけないのは、リソースとして保持すること。

書き換えられて0,0,0,0,0にでもされれば00000-00...で認証されます。


あと認証後の起動ですが、これは入力してもらったままの状態でならレジストリなど目に見えるところに置いても特に問題無いかと。

レジストリやiniファイルからキー文字列を取得し、起動のたびに認証すれば問題ないと思います。

(これは簡易的な認証なので、高価なソフトならもっと複雑にするべきです)

ダミー:http://q.hatena.ne.jp/

◎質問者からの返答

ありがとうございます。パスワードチェックということになるのでしょうか。今回、有効期限を設定してその期間だけ使えるようにしたいと考えています。有効期限をハードコーディングした場合に、どんな処理を書けばチェックできるのか、サンプルをご存知であれば教えていただけますか。宜しく御願い致します。


2 ● wm5775
●23ポイント

http://www.hatena.ne.jp

#URLはダミーです。

Windowsのみであれば、売り物ですが、ProtectKitというツールが便利です。

だいたい思いつくやりたいと思いつくことはすべて網羅されていると思います。

それから、ソフトにそれなりに高い金額をつけようとしているのなら、アラジンのHaspというハードウェアキーを使うのがよくあるパターンです。

両方ともDLLをアプリに組み込む必要がありますが、説明書にサンプルコードが掲載されていると思います。

◎質問者からの返答

ProtectKit2 標準価格 68,000円ですね。確かに多機能なのですが、少し高額です。。。。。良い検討対象を教えていただき、ありがとうございます。ただ、できるだけ低コストで実現したいというのもありますので、簡単な日付チェックのサンプルなどあれば教えていただければと思います。


3 ● kazu1107
●22ポイント

#include <iostream>

#include <time.h>

const char* file = "file.dat";

const time_t mask = 0xF0F0F0F0F0F0F0F0; // 時間データのマスクキー(もっとランダムにするべき)


// ファイルからリミットタイムを取得

void GetLimitTime(time_t *limitTime){

FILE *fp = fopen(file, "rb");

if(fp == NULL){

*limitTime = 0;

return;

}

fread(limitTime, sizeof(time_t), 1, fp);

*limitTime ^= mask;// XOR簡易デコード

fclose(fp);

}


// ファイルにリミットタイムを書き込み

bool SetLimitTime(const time_t *limitTime){

FILE *fp = fopen(file, "w");

if(fp == NULL){

return false;

}

time_t t = *limitTime ^ mask;// XOR簡易エンコード

fwrite(&t, sizeof(time_t), 1, fp);

fclose(fp);

return true;

}


int main(){

int probation = 0;// 初めて起動した日を除いた試用期間

// (0を設定すれば起動した日の23:59:59)(day)

time_t nowTime, limitTime;

GetLimitTime(&limitTime);

if(limitTime == 0){

time(&limitTime);

limitTime += 86400 * probation; // 1日の秒数 * 日数

SetLimitTime(&limitTime);

}else{

time(&nowTime);

nowTime += 86400*1;

tm t_now, t_limit;

t_now = *localtime(&nowTime);

t_limit = *localtime(&limitTime);

// nowTimeとlimitTimeの比較でも良いですけど、

// 秒単位でリミットを決めることになります。

// limitTime自体はUCT基準なので、計算や時差取得が面倒でこの方法にしました(汗)

if( (t_limit.tm_year < t_now.tm_year) ||

(t_limit.tm_yday < t_now.tm_yday))

{

std::cout << "試用期間切れです。" << std::endl;

return 0;

}

}


struct tm t_st;

t_st = *localtime(&limitTime);

std::cout <<"試用期間は" <<

t_st.tm_year+1900 << "/"<<

t_st.tm_mon+1 << "/" <<

t_st.tm_mday << " " <<

"までです。" << std::endl;

return 0;

}


先の解答は全く的外れだったようで、ごめんなさい。。。

SetLimitTime,GetLimitTimeの動作はもっと工夫しないと現状ではファイル消されれば一発リセットてなかんじですが。。。

単純な日付計算と判断についてはこんな感じではないでしょうか?

http://q.hatena.ne.jp/

◎質問者からの返答

ほぼ、このコードで問題ありません。ありがとうございます!ここからは自力でも可能かもしれませんが、以下のような処理のコードも、あれば貼り付けていただけると助かります。ポイントも加算するように致します。

「char[] limit = "2006/11/28"」という感じに試用期限を文字列としてハードコーディングしている場合に、現在日時を取得して上記limitと比較をして、有効期限を確かめるサンプル。ファイルのI/Oが発生しないパターンです。

回答者1人につき3件まで回答できるように変更しました。宜しくお願い致します。


4 ● kazu1107
●22ポイント

#include <iostream>

#include <time.h>


int main(){

charlimit[] = "2006/11/29";

intlimitYear, limitMon, limitDay;

time_tnowTime;

tmtm_now;

sscanf(limit ,"%d/%d/%d", &limitYear, &limitMon, &limitDay);

// localtimeの仕様にあわせてデータ値を変更

limitYear-= 1900;

limitMon--;

// 現在の日付を取得

time(&nowTime);

tm_now = *localtime(&nowTime);

if( (limitYear < tm_now.tm_year) ||

(limitMon < tm_now.tm_mon) ||

(limitDay < tm_now.tm_mday))

{

std::cout << "使用期限切れです。" << std::endl;

return 0;

}

std::cout << "使用期限は" << limit << "までです。" << std::endl;

return 0;

}

かなりCライクなプログラムなので、VS.NET2005だと警告吐いたりするけど、とりあえず動きます。。。


http://q.hatena.ne.jp/

◎質問者からの返答

ありがとうございます!大変助かりました!!

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ