1.3 Java暗号とWindows暗号の連携
Windowsで暗号化したデータを、Javaで復号する方法を説明します。
1.3.4 Windowsで暗号化する (AES暗号)
WindowsのAPIでテキストデータを暗号化します。以下のコードは、共通鍵による簡単な暗号化[http://www.trustss.co.jp/cng/1000.html]で説明したコードと同様ですが、暗号化のアルゴリズムは128ビットAESを選択しています。暗号化モードは、ECBとし初期化ベクターを不要にしています。
#include <Windows.h>
#include <Bcrypt.h>
#pragma comment(lib,"Bcrypt.lib")
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFULL ((NTSTATUS)0xC0000001L)
// データ
static const BYTE rgbPlainText[] = { "This is an original Message" };
// 共通鍵
static const BYTE rgbAES128Key[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
int _tmain(int argc, _TCHAR* argv[])
{
BCRYPT_ALG_HANDLE hAesAlg = NULL;
BCRYPT_KEY_HANDLE hKey = NULL;
BYTE pbCipherText[100];
DWORD cbKeyObject = 0,
cbCipherText = 100,
cbData;
PBYTE pbKeyObject = NULL;
NTSTATUS status = STATUS_UNSUCCESSFULL;
// Open an algorithm handle.
status = BCryptOpenAlgorithmProvider(
&hAesAlg,
BCRYPT_AES_ALGORITHM,
NULL,
0);
if(!NT_SUCCESS(status)) {
printf("*** Error 0x%x returned by the function\n", status);
return 1;
}
// 暗号化モード
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);
return 1;
}
// 鍵オブジェクトの大きさを計算
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);
return 1;
}
// 鍵オブジェクト用の領域を確保
bKeyObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbKeyObject);
if(!pbKeyObject) {
printf("*** memory allocation failed\n");
return 1;
}
// 鍵オブジェクトを鍵データから作成
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);
return 1;
}
// 暗号化
status = BCryptEncrypt(
hKey,
(PBYTE)rgbPlainText,
sizeof(rgbPlainText),
NULL,
NULL,
0,
pbCipherText,
cbCipherText,
&cbData,
BCRYPT_BLOCK_PADDING);
if(!NT_SUCCESS(status)) {
printf("*** Error 0x%x returned by the function\n", status);
return 1;
}
// 暗号化データをファイルに書き出す
FILE *fp;
fopen_s(&fp, "a.enc", "wb");
fwrite(pbCipherText, 1, cbData, fp);
fclose(fp);
// 後始末
status = BCryptDestroyKey(hKey);
if(!NT_SUCCESS(status)) {
printf("*** Error 0x%x returned by the function\n", status);
return 1;
}
return 0;
}
鍵は、共通鍵鍵ですので同じものを復号時に使います。また、暗号化したデータはa.encという名前で保存します。次は、このファイルからデータを読み出し、復号します。
1.3.5 Javaで復号する
import java.io.*;
import javax.crypto.Cipher;
import javax.crypto.spec.*;
public class AesJavaDec {
public static void main(String[] args) {
try {
// 鍵
byte[] kagi = { 0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15 };
SecretKeySpec sks = new SecretKeySpec(kagi, 0, 16, "AES");
// 暗号化データ読み込み
byte[] input = new byte[32];
FileInputStream fe =new FileInputStream("a.enc");
fe.read(input);
fe.close();
// 復号
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, sks);
byte output[] = c.doFinal(input);
System.out.println(new String(output));
} catch(Exception e) {
e.printStackTrace();
}
}
}
復号されたデータが表示されます。
ご質問・ご要望
ご質問やご要望をお送りください。(匿名でも送信ください。ご質問やご要望内容は、公表しません。)
| ご協力をお願いします、この記事は役に立ちましたか? | |
| ご質問・ご要望 | |
| メールアドレス | |
(記載の会社名および製品名は、各社の登録商標および商標です。)