Java APIを使用してRSA鍵ペアを生成すると、公開鍵はX.509形式でエンコードされ、秘密鍵はPKCS#8形式でエンコードされます。両方をPKCS#1としてエンコードします。これは可能ですか?Javaドキュメントを確認するのにかなりの時間を費やしましたが、解決策が見つかりませんでした。結果は、使用しても同じです。 JavaおよびBouncyCastleプロバイダー。
コードのスニペットは次のとおりです。
KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA","BC");
keygen.initialize(1024);
KeyPair pair = keygen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();
byte[] privBytes = priv.getEncoded();
byte[] pubBytes = pub.getEncoded();
結果として得られる2つのバイト配列は、X.509(パブリック)およびPKCS#8(プライベート)としてフォーマットされます。
どんな助けでも大歓迎です。同様の投稿がいくつかありますが、私の質問に実際に答えるものはありません。
ありがとうございました
BouncyCastleが必要になります:
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
以下のコードスニペットがチェックされ、Bouncy Castle1.52で動作することがわかりました。
秘密鍵をPKCS8からPKCS1に変換します。
PrivateKey priv = pair.getPrivate();
byte[] privBytes = priv.getEncoded();
PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes);
ASN1Encodable encodable = pkInfo.parsePrivateKey();
ASN1Primitive primitive = encodable.toASN1Primitive();
byte[] privateKeyPKCS1 = primitive.getEncoded();
PKCS1の秘密鍵をPEMに変換します。
PemObject pemObject = new PemObject("RSA PRIVATE KEY", privateKeyPKCS1);
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.writeObject(pemObject);
pemWriter.close();
String pemString = stringWriter.toString();
コマンドラインOpenSSLで、キー形式が期待どおりであることを確認します。
openssl rsa -in rsa_private_key.pem -noout -text
公開鍵をX.509SubjectPublicKeyInfoからPKCS1に変換します。
PublicKey pub = pair.getPublic();
byte[] pubBytes = pub.getEncoded();
SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(pubBytes);
ASN1Primitive primitive = spkInfo.parsePublicKey();
byte[] publicKeyPKCS1 = primitive.getEncoded();
PKCS1の公開鍵をPEMに変換します。
PemObject pemObject = new PemObject("RSA PUBLIC KEY", publicKeyPKCS1);
StringWriter stringWriter = new StringWriter();
PemWriter pemWriter = new PemWriter(stringWriter);
pemWriter.writeObject(pemObject);
pemWriter.close();
String pemString = stringWriter.toString();
コマンドラインOpenSSLで、キー形式が期待どおりであることを確認します。
openssl rsa -in rsa_public_key.pem -RSAPublicKey_in -noout -text
次の投稿の作者に感謝します。
これらの投稿には有用な情報が含まれていましたが、古いバージョンのBouncyCastleの場合もあり、この投稿を作成するのに役立ちました。
RFC5208 から、PKCS#8の暗号化されていない形式はPrivateKeyInfo
構造で構成されます。
PrivateKeyInfo :: = SEQUENCE { バージョンバージョン、 privateKeyAlgorithm PrivateKeyAlgorithmIdentifier、 privateKey PrivateKey、 属性[0]暗黙の属性オプション}
ここで、privateKey
は次のとおりです。
「...内容が秘密鍵の値であるオクテット文字列。内容の解釈は、秘密鍵アルゴリズムの登録で定義されます。たとえば、RSA秘密鍵の場合、内容は次のBERエンコーディングです。タイプRSAPrivateKeyの値。」
このRSAPrivateKey
構造は、キーのPKCS#1エンコーディングであり、BouncyCastleを使用して抽出できます。
// pkcs8Bytes contains PKCS#8 DER-encoded key as a byte[]
PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pkcs8Bytes);
RSAPrivateKeyStructure pkcs1Key = RSAPrivateKeyStructure.getInstance(
pki.getPrivateKey());
byte[] pkcs1Bytes = pkcs1Key.getEncoded(); // etc.
Pkcs8秘密鍵をpkcs1に変換するCプログラムを作成しました。できます!
/*****************************************
convert pkcs8 private key file to pkcs1
2013-1-25 Larry Wu created
****************************************/
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/engine.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <stdarg.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <vector>
using namespace std;
#define MY_TRACE_ERROR printf
/*
gcc -Wall -o pkcs_8to1 pkcs_8to1.cpp -g -lstdc++ -lcrypto -lssl
*/
int main(int argc, char **argv)
{
EVP_PKEY * pkey = NULL;
string kin_fname;
FILE *kin_file = NULL;
string kout_fname;
FILE *kout_file = NULL;
// param
if(argc != 3)
{
printf("Usage: %s <pkcs8_key_file> <pkcs1_key_file>\n", argv[0]);
return 1;
}
kin_fname = argv[1];
kout_fname = argv[2];
// init
OpenSSL_add_all_digests();
ERR_load_crypto_strings();
// read key
if((kin_file = fopen(kin_fname.c_str(), "r")) == NULL)
{
MY_TRACE_ERROR("kin_fname open fail:%s\n", kin_fname.c_str());
return 1;
}
if ((pkey = PEM_read_PrivateKey(kin_file, NULL, NULL, NULL)) == NULL)
{
ERR_print_errors_fp(stderr);
MY_TRACE_ERROR("PEM_read_PrivateKey fail\n");
fclose(kin_file);
return 2;
}
// write key
if((kout_file = fopen(kout_fname.c_str(), "w")) == NULL)
{
MY_TRACE_ERROR("kout_fname open fail:%s\n", kout_fname.c_str());
return 1;
}
if (!PEM_write_PrivateKey(kout_file, pkey, NULL, NULL, 0, NULL, NULL))
{
ERR_print_errors_fp(stderr);
MY_TRACE_ERROR("PEM_read_PrivateKey fail\n");
fclose(kout_file);
return 2;
}
// clean
fclose(kin_file);
fclose(kout_file);
EVP_PKEY_free(pkey);
return 0;
}