文字列を暗号化するにはどうしたらよろしいでしょうか?
たとえば、list1.txtという文字列を暗号化キー0x58747382で暗号化するにはどうしたらよいでしょうか?
暗号化の方式は何でもいいのですが、できたら、DESの方を教えていただくとうれしいです。
後、初心者なので暗号化について基礎的なことを教えてもらえるとありがたいです。
なにか勘違いしてるかもしれないですが、わかりやすく説明よろしくお願いします。
暗号化について
-
めるぽん
Re:暗号化について
Windows で暗号化を行うなら CryptoAPI を使います。
CryptAcquireContext でプロバイダを取得して、CryptCreateHash でハッシュを作って、CryptHashData でハッシュにデータ(キーの値となる 0x58747382)を入れて、CryptDeriveKey でハッシュからキーを取得して、そのキーを使って CryptEncrypt を呼び出すことで list.txt のデータの暗号化ができます。
はい、面倒です。
http://eternalwindows.jp/#crypto
http://eternalwindows.jp/crypto/csp/csp00.html
あたりが、暗号化の基礎的な知識から CryptoAPI の仕組みや実際のコードが載ってたりしてすごく分かりやすかったですね。
CryptAcquireContext でプロバイダを取得して、CryptCreateHash でハッシュを作って、CryptHashData でハッシュにデータ(キーの値となる 0x58747382)を入れて、CryptDeriveKey でハッシュからキーを取得して、そのキーを使って CryptEncrypt を呼び出すことで list.txt のデータの暗号化ができます。
はい、面倒です。
http://eternalwindows.jp/#crypto
http://eternalwindows.jp/crypto/csp/csp00.html
あたりが、暗号化の基礎的な知識から CryptoAPI の仕組みや実際のコードが載ってたりしてすごく分かりやすかったですね。
-
ookami
Re:暗号化について
DESの場合は、キーは56ビット(パリティを入れると64ビット)のようです。
http://ja.wikipedia.org/wiki/DES_(%E6%9A%97%E5%8F%B7)
0x58747382ですとビット数が合いませんね^^;
どのような経緯で暗号化に取り組まれているのか分からないので、
ちょっと回答が難しいですが...
とりあえず「公開鍵」「秘密鍵」「ハッシュ」「パリティ」あたりの用語はどの程度理解されていますか?
http://ja.wikipedia.org/wiki/DES_(%E6%9A%97%E5%8F%B7)
0x58747382ですとビット数が合いませんね^^;
どのような経緯で暗号化に取り組まれているのか分からないので、
ちょっと回答が難しいですが...
とりあえず「公開鍵」「秘密鍵」「ハッシュ」「パリティ」あたりの用語はどの程度理解されていますか?
-
たろう
Re:暗号化について
ぬるぽんさん回答ありがとうございます。
CryptoAPIと言うのがあるのですか。
このサイト参考にありがたく使わせていただきます。
複合化のことについても載っているのでしょうか?
ookamiさん回答ありがとうございます。
>どのような経緯で暗号化に取り組まれているのか分からないので、
ちょっと回答が難しいですが...
友達に自分で作る予定のゲームを画像や音楽を隠したいので画像と音楽の入ったファイルを1つにして暗号化したいと思っています。
DESについては56ビットと言うのは知ってたのですが、どのように使えばいいのかわかりません。
暗号技術入門っという本で一度二度読んだ程度です。公開鍵は暗号キーで暗号化してを相手には別の復号化キーで複合化する。秘密鍵は、相手に暗号キーで暗号化してその暗号化キーを復号化キーにして複合化するだったような気がします。「ハッシュ」「パリティ」は聞いたことがあるくらいです。
CryptoAPIと言うのがあるのですか。
このサイト参考にありがたく使わせていただきます。
複合化のことについても載っているのでしょうか?
ookamiさん回答ありがとうございます。
>どのような経緯で暗号化に取り組まれているのか分からないので、
ちょっと回答が難しいですが...
友達に自分で作る予定のゲームを画像や音楽を隠したいので画像と音楽の入ったファイルを1つにして暗号化したいと思っています。
DESについては56ビットと言うのは知ってたのですが、どのように使えばいいのかわかりません。
暗号技術入門っという本で一度二度読んだ程度です。公開鍵は暗号キーで暗号化してを相手には別の復号化キーで複合化する。秘密鍵は、相手に暗号キーで暗号化してその暗号化キーを復号化キーにして複合化するだったような気がします。「ハッシュ」「パリティ」は聞いたことがあるくらいです。
-
ookami
Re:暗号化について
でしたら俄然オススメなのがこちら。
http://homepage2.nifty.com/natupaji/DxL ... c.html#T11
リソースの暗号化は時々話題にのぼるようですねw
http://www.play21.jp/board/formz.cgi?ac ... &rln=51927
-- 追記
あ、すいません。「DXライブラリを使っているなら」ですが。
http://homepage2.nifty.com/natupaji/DxL ... c.html#T11
リソースの暗号化は時々話題にのぼるようですねw
http://www.play21.jp/board/formz.cgi?ac ... &rln=51927
-- 追記
あ、すいません。「DXライブラリを使っているなら」ですが。

-
めるぽん
Re:暗号化について
>複合化のことについても載っているのでしょうか?
もちろんです。
ただまあ、ローカルで使われる画像や音楽の暗号化程度なら CryptoAPI を使う必要は無いでしょうね。
もちろんです。
ただまあ、ローカルで使われる画像や音楽の暗号化程度なら CryptoAPI を使う必要は無いでしょうね。
-
たろう
Re:暗号化について
回答ありがとうございます。
早速やってみたのですが、
どうしたらよいでしょうか?
早速やってみたのですが、
#include "stdafx.h"
#include <Windows.h>
#include <Wincrypt.h>
#pragma comment(lib, "Crypt32.lib")
#define PASSWORD "password"
int _tmain(int argc, _TCHAR* argv[/url])
{
// キーコンテナの取得
HCRYPTPROV hProv;
if(!CryptAcquireContext(&hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)) {
if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_AES, CRYPT_NEWKEYSET)) {
wprintf(_T("CryptAcquireContext error\n"));
return 1;
}
}
// ハッシュのインスタンス
HCRYPTHASH hHash;
if(!CryptCreateHash(hProv, CALG_SHA1, 0,0,&hHash)) {
wprintf(_T("CryptCreateHash error\n"));
return 2;
}
if(!CryptHashData(hHash, (BYTE*)PASSWORD, (DWORD)strlen(PASSWORD), 0)) {
wprintf(_T("CryptHashData error"));
return 3;
}
// 鍵の生成
#define KEYLENGTH_256 256 * 0x10000
HCRYPTKEY hKey;
if(!CryptDeriveKey(hProv, CALG_AES_256, hHash, KEYLENGTH_256, &hKey)) {
wprintf(_T("CryptDeriveKey error\n"));
return 4;
}
// ブロック暗号化のパディングを設定
DWORD padding_mode=PKCS5_PADDING;
if(!CryptSetKeyParam(hKey, KP_PADDING, (BYTE*)&padding_mode, 0)) {
wprintf(_T("CryptSetKeyParam error\n"));
return 5;
}
/*
// ブロックサイズを取得
{
DWORD blkLen;
DWORD dwDataLen=(DWORD)sizeof(DWORD);
if(!CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&blkLen, &dwDataLen, 0)) {
wprintf(_T("CryptGetKeyParam error"));
return 97;
} else {
wprintf(_T("Bolock length is %d bytes.\n"), blkLen / 8);
}
}
/**/
// 初期化ベクタ
BYTE iv[/url]={0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
if(!CryptSetKeyParam(hKey, KP_IV, iv, 0)) {
wprintf(_T("CryptSetKeyParam error\n"));
return 98;
}
// Cipherモードを設定
DWORD mode = CRYPT_MODE_CFB;
if(!CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&mode, 0)) {
wprintf(_T("CryptSetKeyParam error\n"));
return 99;
}
// 復号用にキーを複製
HCRYPTKEY hdKey;
if(!CryptDuplicateKey(hKey, NULL, 0, &hdKey)) {
wprintf(_T("CryptDuplicateKey error\n"));
return 6;
}
// 暗号化
#define BUF_LEN 100
BYTE pbData[BUF_LEN]="This is a palin text data.";
DWORD dwDataLen=(DWORD)(strlen((char*)pbData)+1);
if(!CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, (DWORD)BUF_LEN)) {
wprintf(_T("CryptEncrypt error\n"));
return 7;
} else {
WCHAR str[1000];
DWORD strLen=1000;
CryptBinaryToString(pbData, dwDataLen, CRYPT_STRING_HEXASCIIADDR, str, &strLen);
wprintf(str);
wprintf(_T("Encrypted data length is %d bytes\n"), dwDataLen);
}
// 復号
if(!CryptDecrypt(hdKey, 0, TRUE, 0, pbData, &dwDataLen)) {
wprintf(_T("CryptDecrypt error\n"));
return 8;
} else {
WCHAR str[1000];
DWORD strLen=1000;
CryptBinaryToString(pbData, dwDataLen, CRYPT_STRING_HEXASCIIADDR, str, &strLen);
wprintf(str);
wprintf(_T("Decrypted data length is %d bytes\n"), dwDataLen);
}
// 後始末
CryptDestroyKey(hKey);
CryptDestroyKey(hdKey);
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return 0;
}
でどうしても、wprintf(_T("CryptAcquireContext error\n"));で止まってしまいます。どうしたらよいでしょうか?
-
めるぽん
Re:暗号化について
うーん、直接の原因は分かりましたが、スマートな解決方法が分かりませんね・・・。
多分 Windows XP ですよね?
MS_ENH_RSA_AES_PROV を定義している部分を見てみると、
MS_ENH_RSA_AES_PROV のドキュメント(http://msdn.microsoft.com/en-us/library ... 85%29.aspx)を見てみると
<blockquote>
Windows XP: The Microsoft AES Cryptographic Provider was named Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype).
</blockquote>
とあります。なので XP では "(Prototype)" のある方の文字列を渡さないといけないのですが、なぜかそちらが選択されないようなのです。
なので MS_ENH_RSA_AES_PROV と書かずに _T("Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)") とすればうまくいったのですが、もっとスマートな方法があるような気がしますね。
多分 Windows XP ですよね?
MS_ENH_RSA_AES_PROV を定義している部分を見てみると、
#if (NTDDI_VERSION >= NTDDI_WS03) #define MS_ENH_RSA_AES_PROV_A "Microsoft Enhanced RSA and AES Cryptographic Provider" #define MS_ENH_RSA_AES_PROV_W L"Microsoft Enhanced RSA and AES Cryptographic Provider" #elif (NTDDI_VERSION == NTDDI_WINXP) #define MS_ENH_RSA_AES_PROV_A "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" #define MS_ENH_RSA_AES_PROV_W L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" #endif //(NTDDI_VERSION >= NTDDI_WS03) #if (NTDDI_VERSION >= NTDDI_WINXP) #ifdef UNICODE #define MS_ENH_RSA_AES_PROV MS_ENH_RSA_AES_PROV_W #else #define MS_ENH_RSA_AES_PROV MS_ENH_RSA_AES_PROV_A #endif #endif //(NTDDI_VERSION >= NTDDI_WINXP)となっています。自分の環境(Windows XP SP3)では NTDDI_VERSION >= NTDDI_WS03 に引っかかって、 "(Prototype)" の付いていない方が選択されていました。
MS_ENH_RSA_AES_PROV のドキュメント(http://msdn.microsoft.com/en-us/library ... 85%29.aspx)を見てみると
<blockquote>
Windows XP: The Microsoft AES Cryptographic Provider was named Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype).
</blockquote>
とあります。なので XP では "(Prototype)" のある方の文字列を渡さないといけないのですが、なぜかそちらが選択されないようなのです。
なので MS_ENH_RSA_AES_PROV と書かずに _T("Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)") とすればうまくいったのですが、もっとスマートな方法があるような気がしますね。
