1.3 Java暗号とWindows暗号の連携
Javaの開発環境は、JDK1.5以上を想定しています。
別に、XML文書への暗号化や電子署名 を説明しています。
別に、XML文書への暗号化や電子署名 を説明しています。
1.3.1 概要
Javaで暗号化(AES共通鍵暗号化)したデータをWindows APIで復号する方法を解説します。
Windows環境は、以下を対象とします。
OS: Windows XP,2003,Vista
開発環境: Visual Studio 2005 C++
Javaによる暗号化の詳細はこちら[http://www.trustss.co.jp/Java/JEncrypt100.html]、Windowsによる暗号化の詳細はこちら[http://www.trustss.co.jp/cng/1000.html]を参照してください。
Windows環境は、以下を対象とします。
OS: Windows XP,2003,Vista
開発環境: Visual Studio 2005 C++
Javaによる暗号化の詳細はこちら[http://www.trustss.co.jp/Java/JEncrypt100.html]、Windowsによる暗号化の詳細はこちら[http://www.trustss.co.jp/cng/1000.html]を参照してください。
1.3.2 Javaで暗号化する (AES暗号)
ここでは、AES暗号アルゴリズムを使って解説します。
実際のアプリケーションで暗号化を実施する場合は、暗号化の鍵を直接指定せずあらかじめ与えられたパスワードやPINなどの情報から利用するアルゴリズムに適した長さの共通鍵を生成するのが容易です。ここでは、わかりやすくするために暗号化の鍵を直接指定して暗号化・復号を行う方法を説明します。
暗号鍵を指定した暗号化とパスワードなどから鍵を生成して暗号化する方法の解説は、それぞれのページを参照してください。
まず、Javaでテキストデータを暗号化します。以下のコードは、暗号鍵を指定した暗号化で説明したコードと同様ですが、暗号化のアルゴリズムは128ビットAESを選択しています。暗号化モードは、ECBとし初期化ベクターを不要にしています。
なお日本国内であれば、AES鍵長を128ビットばかりではなく192ビットや512ビットで使うことができます。JCEの初期状態では利用できませんが、「1.4 JCEを無制限強度にする[http://www.trustss.co.jp/Java/JEncrypt140.html]
」の手順に従えば、利用できるようになります。
実際のアプリケーションで暗号化を実施する場合は、暗号化の鍵を直接指定せずあらかじめ与えられたパスワードやPINなどの情報から利用するアルゴリズムに適した長さの共通鍵を生成するのが容易です。ここでは、わかりやすくするために暗号化の鍵を直接指定して暗号化・復号を行う方法を説明します。
暗号鍵を指定した暗号化とパスワードなどから鍵を生成して暗号化する方法の解説は、それぞれのページを参照してください。
まず、Javaでテキストデータを暗号化します。以下のコードは、暗号鍵を指定した暗号化で説明したコードと同様ですが、暗号化のアルゴリズムは128ビットAESを選択しています。暗号化モードは、ECBとし初期化ベクターを不要にしています。
なお日本国内であれば、AES鍵長を128ビットばかりではなく192ビットや512ビットで使うことができます。JCEの初期状態では利用できませんが、「1.4 JCEを無制限強度にする[http://www.trustss.co.jp/Java/JEncrypt140.html]
」の手順に従えば、利用できるようになります。
import java.io.*;
import javax.crypto.Cipher;
import javax.crypto.spec.*;
public class AesJavaEnc {
public static void main(String[] args) {
try {
// 鍵
byte[] kagi = { 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f };
SecretKeySpec sks = new SecretKeySpec(kagi,0,16,"AES");
// 暗号化
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, sks);
byte input[] = "This ia an original message.".getBytes();
byte encrypted[] = c.doFinal(input);
// 暗号化したデータを保存
FileOutputStream fe = new FileOutputStream("a.enc");
fe.write(encrypted);
fe.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
鍵は、共通鍵鍵ですので同じものを復号時に使います。また、暗号化したデータはa.encという名前で保存します。次は、このファイルからデータを読み出し、復号します。
1.3.3 Windows APIで復号する
Windowsでは、CNG(Cryptography Next Genaration)APIを使って復号します。詳細は、CNG APIによる暗号化[http://www.trustss.co.jp/cng/1000.html]を参照してください。
#include <BCrypt.h>
#pragma comment(lib, "BCrypt.lib")
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
// 共通鍵(暗号化で用いたものと全く同じ)
static const BYTE rgbAES128Key[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
void main(int argc, char **argv)
{
BCRYPT_ALG_HANDLE hAesAlg = NULL;
BCRYPT_HANDLE hAlg = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
BYTE pbCipherText[1000];
BYTE pbPlainText[1000];
DWORD cbCipherText = 1000,
cbPlainText = 1000,
cbKeyObject = 0,
cbData;
PBYTE pbPlainText = NULL,
pbKeyObject = NULL;
// アルゴリズムハンドル
status = BCryptOpenAlgorithmProvider(
&hAesAlg,
BCRYPT_AES_ALGORITHM,
NULL,
0);
if(!NT_SUCCESS(status)) {
printf("*** Error 0x%x returned by the function\n", status);
goto Cleanup;
}
// 暗号化モード
status = BCryptSetProperty(
hAesAlg,
BCRYPT_CHAINING_MODE,
(PBYTE)BCRYPT_CHAIN_MODE_ECB,
sizeof(BCRYPT_CHAIN_MODE_ECB),
0);
if(!NT_SUCCESS(status)) {
printf("*** Error 0x%x returned by the function\n", status);
goto Cleanup;
}
// 鍵オブジェクトの大きさを計算
status = BCryptGetProperty(
hAesAlg,
BCRYPT_OBJECT_LENGTH,
(PBYTE)&cbKeyObject,
sizeof(DWORD),
&cbData,
0);
if(!NT_SUCCESS(status)) {
printf("*** Error 0x%x returned by the function\n", status);
goto Cleanup;
}
// 鍵オブジェクト用の領域を確保
pbKeyObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbKeyObject);
if(!pbKeyObject) {
printf("*** memory allocation failed\n");
goto Cleanup;
}
// 鍵オブジェクトを鍵データから生成
status = BCryptGenerateSymmetricKey(
hAesAlg,
&hKey,
pbKeyObject,
cbKeyObject,
(PBYTE)rgbAES128Key,
sizeof(rgbAES128Key),
0);
if(!NT_SUCCESS(status)) {
printf("*** Error 0x%x returned by the function\n", status);
goto Cleanup;
}
// 暗号化データをファイルから読み出す
FILE *fp;
fopen_s(&fp, "a.enc", "rb");
cbCipherText = (DWORD)fread(pbCipherText, 1, cbCipherText, fp);
fclose(fp);
// 復号
status = BCryptDecrypt(
hKey,
pbCipherText,
cbCipherText,
NULL,
NULL,
0,
pbPlainText,
cbPlainText,
&cbPlainText,
BCRYPT_BLOCK_PADDING); // PKCS#5パディング
if(!NT_SUCCESS(status)) {
printf("*** Error 0x%x returned by the function\n", status);
goto Cleanup;
}
Cleanup:
if(hAesAlg) { BCryptCloseAlgorithmProvider(hAesAlg, 0); }
if(hKey) { BCryptDestroyKey(hKey); }
if(pbKeyObject) { HeapFree(GetProcessHeap(), 0, pbKeyObject); }
}
復号されたデータは、pbPlainTextに入り、その大きさはcbPlainTextバイトです。
次は、Windowsで暗号化したデータをJavaで復号します。
ご質問・ご要望
ご質問やご要望をお送りください。(匿名でも送信ください。ご質問やご要望内容は、公表しません。)
| ご協力をお願いします、この記事は役に立ちましたか? | |
| ご質問・ご要望 | |
| メールアドレス | |
(記載の会社名および製品名は、各社の登録商標および商標です。)