HEXA BLOG
ヘキサブログ
プログラム
ドングル2
お久しぶりです。
珍しく前回からネタが続く、good sunこと山口です。
USBをハードウェアキーとして利用するの続きをやってみたいと思います。
今回注目するのはライセンスキー発行に繋がる部分です。
ライセンスキーの流れは普通はこんな感じでしょうか。
まずユーザーはハードウェアキー情報をライセンス管理者に送信して、
管理者はその情報を基にライセンスキーを発行してユーザーに渡します。
アプリケーションはライセンスキー情報とハードウェアキー情報を照合して、
対になるデータであることを確認したらアプリケーションを正常起動します。
今回はハードウェアキーの情報を管理者に安全に届けるための方法を考えたいと思います。
公開鍵と秘密鍵を使った暗号化というのがあります。
公開鍵で暗号化されたデータは秘密鍵だけで復号化出来るというものです。
この仕組を利用して
アプリケーションには公開鍵情報を埋め込み、
この鍵を利用してハードウェアキー情報を暗号化して、
管理者のもつ秘密鍵で復号化してライセンスキーを作成するという流れが出来そうです。
ではどのようにこの暗号化、復号化を行うかですが…
今回もAPIを利用したコードをネットで調べてC++で動作するようにしてみました。
Windows7にてVS2010のコンソールアプリとして動作確認しています。
#include <windows.h> #include <wincrypt.h> #include <memory> #include <stdio.h> void printCode(const char* str, const BYTE* code, DWORD size) { printf("%s from>>\n", str); for(DWORD i = 0; i < size; i++){ printf("%c", code[i]); } printf("\n<<to\n"); } int main(void) { // RSA用にコンテキストを有効化します HCRYPTPROV cryptprov; CryptAcquireContext(&cryptprov, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0 ); // 鍵の自動生成 HCRYPTKEY genKey; // 第三引数の上位16bitが0の場合はデフォルトのキー長が使われる CryptGenKey(cryptprov, CALG_RSA_KEYX, CRYPT_EXPORTABLE, &genKey); // 秘密鍵です DWORD privateKeySize; CryptExportKey(genKey, 0, PRIVATEKEYBLOB, 0, NULL, &privateKeySize); std::auto_ptr<BYTE> privateKey(new BYTE[privateKeySize]); CryptExportKey(genKey, 0, PRIVATEKEYBLOB, 0, privateKey.get(), &privateKeySize); // 公開鍵です DWORD publicKeySize; CryptExportKey(genKey, 0, PUBLICKEYBLOB, 0, NULL, &publicKeySize); std::auto_ptr<BYTE> publicKey(new BYTE[publicKeySize]); CryptExportKey(genKey, 0, PUBLICKEYBLOB, 0, publicKey.get(), &publicKeySize); // 作成された鍵で暗号化と復号化が出来るか試してみる // キーをインポートしたと想定、公開鍵を読み込んで改めてキーを作成する HCRYPTKEY pubImportKey; if(!CryptImportKey(cryptprov, publicKey.get(), publicKeySize, 0, 0, &pubImportKey)){ return 0; } // まずは暗号化 const char* originalCode = "hello world"; DWORD originalSize = strlen(originalCode); DWORD encryptSize = originalSize; // 一度暗号化データのサイズを調べる CryptEncrypt(pubImportKey, 0, true, 0, (BYTE*)originalCode, &encryptSize, 0); std::auto_ptr<BYTE> encryptBuffer(new BYTE[encryptSize]); memcpy(encryptBuffer.get(), originalCode, originalSize); printCode("オリジナルコード", encryptBuffer.get(), originalSize); // 暗号化する if(!CryptEncrypt(pubImportKey, 0, true, 0, encryptBuffer.get(), &originalSize, encryptSize)){ return 0; } printCode("暗号化したコード", encryptBuffer.get(), encryptSize); // 続いて復号化 // キーをインポートしたと想定、秘密鍵を読み込んで改めてキーを作成する HCRYPTKEY prvImportKey; if(!CryptImportKey(cryptprov, privateKey.get(), privateKeySize, 0, 0, &prvImportKey)){ return 0; } if(!CryptDecrypt(prvImportKey, 0, true, 0, encryptBuffer.get(), &encryptSize)){ return 0; } printCode("復号化したコード", encryptBuffer.get(), encryptSize); // 本来は最初に鍵を作ったら何処かにとって置かないと毎回違う鍵が作られるので要注意です CryptDestroyKey(prvImportKey); CryptDestroyKey(pubImportKey); CryptDestroyKey(genKey); CryptReleaseContext(cryptprov, 0); return 0; }
APIを使えば簡単に暗号化も出来てしまいますね。
本来はこの暗号化の仕組み自体を作ると言うのも面白いのですが、
使えるものを上手く使うことは時間節約にも繋がります。
ここで浮いた時間を本来のアプリケーションにつぎ込むとより良いものになると思います。
次回も続く予定ですが、少し違った方向性で行きたいと思います。
ではまた。
CATEGORY
- about ヘキサ (166)
- 部活動 (6)
- CG (18)
- プロジェクトマネジメント (1)
- 研修 (5)
- 美学 (1)
- いいモノづくり道 (230)
- 採用 -お役立ち情報も- (149)
- プログラム (188)
- デザイン (99)
- ゲーム (274)
- 日記 (1,104)
- 書籍紹介 (113)
- その他 (875)
- 就活アドバイス (20)
- ラーメン (3)
- ライフハック (25)
- イベント紹介 (10)
- 料理 (23)
- TIPS (7)
- 怖い話 (3)
- サウンド (5)
- 子育て (1)
- 筋トレ (1)
- 商品紹介 (21)
- アプリ紹介 (31)
- ソフトウェア紹介 (33)
- ガジェット紹介 (12)
- サイト紹介 (10)
- 研究・開発 (34)
- 回路図 (4)
- アナログゲーム (40)
- 交流会 (21)
- 報告会 (3)
- インフラ (25)
- グリとブラン (6)
- カメラ (9)
- クラフト (27)
- 部活 (14)
- 画伯 (15)
- カレー (6)
- 音楽(洋楽) (6)
- 映画・舞台鑑賞 (43)
- 飼育 (5)
- いぬ (8)
- ねこ (19)
ARCHIVE
- 2024年
- 2023年
- 2022年
- 2021年
- 2020年
- 2019年
- 2018年
- 2017年
- 2016年
- 2015年
- 2014年
- 2013年
- 2012年
- 2011年
- 2010年
- 2009年
- 2008年
- 2007年