- PR -

javaとC++でハイブリッド暗号の実装について

投稿者投稿内容
るな
常連さん
会議室デビュー日: 2006/03/09
投稿数: 21
投稿日時: 2006-06-16 14:12
お世話になります。
早速試したいと思います。
細かい解説ありがとうございました。
mio
ぬし
会議室デビュー日: 2005/08/25
投稿数: 734
お住まい・勤務地: 神奈川県
投稿日時: 2006-06-16 14:31
SSLをすべてスルーしているのは、なにか意味があるんでしょうか。
るな
常連さん
会議室デビュー日: 2006/03/09
投稿数: 21
投稿日時: 2006-06-16 16:04
お世話になります。

>mioさん
セキュリティ技術について初心者なのですが
OpenSSL等の事を言っているのでしょうか?
前のレスでも書きましたが
クライアントマシンにはPC以外のハードも考慮しているので
検討項目に上がっていません。
学習不足で見当違いでしたら申し訳ありません。

追記
サーバマシンはWinなのでWinAPI等が使えます
スフレ
ぬし
会議室デビュー日: 2005/05/27
投稿数: 281
お住まい・勤務地: 東京
投稿日時: 2006-06-16 16:13
引用:

クライアントマシンにはPC以外のハードも考慮しているので
検討項目に上がっていません。



クライアントでJavaが使えるのなら、SSLは標準で使える可能性が高いです。SunのJREであれば、jre/lib/jsse.jarというのがSSLのライブラリ。

あと、JavaとC++での暗号の相互運用性を気にされているようですが、暗号アルゴリズムがちゃんと揃ってれば、問題なくやりとりできます。
るな
常連さん
会議室デビュー日: 2006/03/09
投稿数: 21
投稿日時: 2006-06-23 18:18
お世話になります。
諸都合により遅くなりました...

皆様のアドバイスのお陰で大分形なってきました。有難うございます。
※SSLの件は性能問題等、追々検討するとして
・C++ ⇔ C++
・java ⇔ java
上記は行える様になったのですが予想通り?
・C++ ⇔ java
でC++で符号化した鍵をjavaで取り込もうとするとエラーになってしまいます。
javaで生成した共通鍵を符号化してC++で取り込もうとしても同様でした。
気になるのはC++はBYTE[unsigned char]でjavaはbyte[signed char]なのですが
...よく分かりませんでした。

疑似的に作ったサンプルコードを後述します。
解決策、アドバイスがありましたら宜しくお願いします。


--- java ---
String szOrgFile = "d:\\temp\\temp\\hira.txt"; // 適当な平文
String szEncFile = "d:\\temp\\temp\\enc.txt"; // 暗号化されたファイル
String szDecFile = "d:\\temp\\temp\\dec.txt"; // 復号したファイル
String szPubKeyFile = "d:\\temp\\temp\\pub.txt"; // 公開鍵保存用

// ペア鍵作成
String algorithm = "RSA";
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
KeyPair keyPair = keyPairGenerator.genKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
String aaa = publicKey.getFormat();
aaa = privateKey.getFormat();

// 読込みデータ用
byte[] in_data = new byte[1024*4];
/*
// 公開鍵読込
FileInputStream pub_F = new FileInputStream(szPubKeyFile);
int nRet = pub_F.read(in_data);
pub_F.close();
*/
// 共通鍵生成
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
keyGen.init(56);
SecretKey com_key1 = keyGen.generateKey();
byte com_key_byte1[] = com_key1.getEncoded();

// 公開鍵、秘密鍵の符号化
byte[] pub_key_byte = publicKey.getEncoded();
byte[] pri_key_byte = privateKey.getEncoded();
/*
byte[] pub_k = new byte[nRet];
for(int nLoop=0;nLoop<nRet;nLoop++){
pub_k[nLoop] = in_data[nLoop];
}
*/
// 符号化された公開鍵 -> 鍵
KeyFactory kf1 = KeyFactory.getInstance("RSA");
Key pub_key = kf1.generatePublic(new X509EncodedKeySpec(pub_key_byte));
// 公開鍵で共通鍵を暗号化
Cipher cp_pub = Cipher.getInstance("RSA");
cp_pub.init(Cipher.ENCRYPT_MODE, pub_key);
byte enc_com_key[] = cp_pub.doFinal(com_key_byte1);

// 平文を共通鍵で暗号化
FileInputStream hira_F = new FileInputStream(szOrgFile);
FileOutputStream enc_F = new FileOutputStream(szEncFile);
Cipher cp_enc = Cipher.getInstance("DES");
cp_enc.init(Cipher.ENCRYPT_MODE, com_key1);
int nReadSize = 0;
while((nReadSize=hira_F.read(in_data))>0){
byte[] in_data2 = new byte[nReadSize];
for(int nLoop=0;nLoop<nReadSize;nLoop++){
in_data2[nLoop] = in_data[nLoop];
}
byte enc[] = cp_enc.doFinal(in_data2);
enc_F.write(enc);
}
hira_F.close();
enc_F.close();
// 符号化された公開鍵 -> 鍵
KeyFactory kf2 = KeyFactory.getInstance("RSA");
Key pri_key = kf2.generatePrivate(new PKCS8EncodedKeySpec(pri_key_byte));
// 秘密鍵で共通鍵を復号
Cipher cp_pri = Cipher.getInstance("RSA");
cp_pri.init(Cipher.DECRYPT_MODE, pri_key);
byte com_key_byte2[] = cp_pri.doFinal(enc_com_key);
// 符号化された共通鍵 -> 鍵
DESKeySpec keyspec = new DESKeySpec(com_key_byte2);
SecretKeyFactory keyfac = SecretKeyFactory.getInstance("DES");
SecretKey com_key2 = keyfac.generateSecret(keyspec);

// 共通鍵で暗号化された文を復号
FileInputStream enc_F2 = new FileInputStream(szEncFile);
FileOutputStream ans_F = new FileOutputStream(szDecFile);
Cipher cp_dec = Cipher.getInstance("DES");
cp_dec.init(Cipher.DECRYPT_MODE, com_key2);
while((nReadSize=enc_F2.read(in_data))>0){
byte[] in_data2 = new byte[nReadSize];
for(int nLoop=0;nLoop<nReadSize;nLoop++){
in_data2[nLoop] = in_data[nLoop];
}
byte enc[] = cp_dec.doFinal(in_data2);
ans_F.write(enc);
}
ans_F.close();
enc_F2.close();

エラー:java.security.spec.InvalidKeySpecException: Unknown key spec: Could not decode public key from BER.



--- C++ ---
HCRYPTPROV hCryptprov;
HCRYPTKEY hKey = 0;
DWORD dwByte = 0, dwWritten;
// プロバイダ設定
if (!CryptAcquireContext(&hCryptprov, NULL, NULL, PROV_RSA_FULL, 0)) {
return FALSE;
}
// ペア鍵作成
if (!CryptGenKey(hCryptprov, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, &hKey)) {
return FALSE;
}
// 公開鍵の符号化
BYTE pbBuf_pub[1024 * 4] = "";
CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, NULL, &dwByte);
if (!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, pbBuf_pub, &dwByte)) {
return FALSE;
}
// 秘密鍵の符号化
DWORD dwByte2 = 0;
BYTE pbBuf_pri[1024 * 4] = "";
CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwByte2);
if (!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, pbBuf_pri, &dwByte2)) {
return FALSE;
}
// 公開鍵、秘密鍵の保存
HANDLE hPub, hPri;
hPub = CreateFile(szPubKeyFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
hPri = CreateFile(szPriKeyFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hPub, pbBuf_pub, dwByte, &dwWritten, NULL);
WriteFile(hPri, pbBuf_pri, dwByte2, &dwWritten, NULL);
CloseHandle(hPub);
CloseHandle(hPri);
CryptDestroyKey(hKey);
CryptReleaseContext(hCryptprov, 0);
るな
常連さん
会議室デビュー日: 2006/03/09
投稿数: 21
投稿日時: 2006-06-23 18:51
追記です。

javaで生成した共通鍵を符号化してC++で取り込むコードは下記です。

// 共通鍵Import
HCRYPTKEY hKey4;
// pbBuf_com : 符号化された共通鍵
// dwByte2 : 上記バイトサイズ
if (!CryptImportKey(hCryptprov, pbBuf_com, dwByte2, 0, 0, &hKey4)) {
return FALSE;
}

加納正和
ぬし
会議室デビュー日: 2004/01/28
投稿数: 332
お住まい・勤務地: 首都圏
投稿日時: 2006-06-26 21:20
引用:

るなさんの書き込み (2006-06-23 18:18) より:

気になるのはC++はBYTE[unsigned char]でjavaはbyte[signed char]なのですが
...よく分かりませんでした。

エラー:java.security.spec.InvalidKeySpecException: Unknown key spec: Could not decode public key from BER.




BERになってない、というエラーのようですが。
"BER"とは、Basic Encoded Ruleとかですが、
公開鍵をBER形式、要するにある決まったデータ形式にします。

http://www.trustss.co.jp/smnDataFormat410.html#SubjectPublicKeyInfo

のように

RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER } -- e

のデータ形式です。具体的には、公開鍵証明書を見たほうが早いですが、、
30 82 01 23 RSAPublickey
02 01 INTEGER
02 01 INTEGER

のような形式です。
るな
常連さん
会議室デビュー日: 2006/03/09
投稿数: 21
投稿日時: 2006-06-29 11:53
お世話になっております。

アドバイス有難うございます。
少々調べたのですが実際どのように実装すれば良いかまでは到達しておりません。
引き続き調査いたします。

スキルアップ/キャリアアップ(JOB@IT)