RSAキーペアを生成するためにKeyPairGenerator
を使用しました。私が間違っていない場合、KeyStoreは証明書を格納するためだけに使用され、鍵は使用されません。秘密鍵をコンピューターに正しく保存するにはどうすればよいですか?
注:このコードはデモンストレーションのみを目的としています。秘密鍵は、ディスクに保存するときに暗号化する必要があります。そのまま使用しないでください。
あなたはこのようなことをすることができます:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(),
RSAPublicKeySpec.class);
saveToFile(PUBLIC_KEY_FILE,
pub.getModulus(), pub.getPublicExponent());
RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(),
RSAPrivateKeySpec.class);
saveToFile(PRIVATE_KEY_FILE,
priv.getModulus(), priv.getPrivateExponent());
保存機能:
private static void saveToFile(String fileName,
BigInteger mod, BigInteger exp)
throws SomeException {
ObjectOutputStream oout = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(fileName)));
try {
oout.writeObject(mod);
oout.writeObject(exp);
} catch (Exception e) {
throw new SomeException(e);
} finally {
oout.close();
}
}
そして、同じように読み返してください:
private static PublicKey readPublicKey() throws SomeException {
InputStream in = new FileInputStream(PUBLIC_KEY_FILE);
ObjectInputStream oin =
new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new SomeException(e);
} finally {
oin.close();
}
}
秘密鍵の読み取りも同様です。
このコードブロックは、KeyPairを生成してAndroidKeyStoreに格納します。 (注:例外キャッチは省略されます)
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
String alias = "my_key"; // replace as required or get it as a function argument
int nBefore = keyStore.size(); // debugging variable to help convince yourself this works
// Create the keys if necessary
if (!keyStore.containsAlias(alias)) {
Calendar notBefore = Calendar.getInstance();
Calendar notAfter = Calendar.getInstance();
notAfter.add(Calendar.YEAR, 1);
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
.setAlias(alias)
.setKeyType("RSA")
.setKeySize(2048)
.setSubject(new X500Principal("CN=test"))
.setSerialNumber(BigInteger.ONE)
.setStartDate(notBefore.getTime())
.setEndDate(notAfter.getTime())
.build();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
generator.initialize(spec);
KeyPair keyPair = generator.generateKeyPair();
}
int nAfter = keyStore.size();
Log.v(TAG, "Before = " + nBefore + " After = " + nAfter);
// Retrieve the keys
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();
RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();
Log.v(TAG, "private key = " + privateKey.toString());
Log.v(TAG, "public key = " + publicKey.toString());
http://snipplr.com/view/18368/
OR
http://docs.Oracle.com/javase/1.5.0/docs/api/Java/security/KeyStore.html
OR
http://Java.Sun.com/docs/books/tutorial/security/apisign/vstep2.html これは最も有望です
OR
信頼できない環境でキーを保護することは不可能です。コードを難読化したり、任意の変数からキーを作成したりできます。最終的には、標準のjavax.cryptoライブラリを使用すると想定して、Mac.getInstance()を呼び出す必要があり、後でそのインスタンスでinit()を呼び出す場合があります。あなたの鍵が欲しい人はそれを手に入れます。
ただし、解決策は、キーをプログラムではなく環境に結び付けることだと思います。署名とは、データが既知のソースから発信されたものであり、そのソースから提供されてから改ざんされていないことを意味します。現在、あなたは「私のプログラムがデータを生成したことを保証する」と言っています。代わりに、要件を「プログラムの特定のユーザーがデータを作成したことを保証する」に変更します。その後、責任はそのユーザーに移され、ユーザーのキーを処理します。
秘密鍵の形式によっては、Java keytoolで使用できる形式に変換する必要がある場合があります。
しかし、keytoolでサポートされている形式の場合は、keytoolを使用してインポートできるはずです。詳細:
http://docs.Oracle.com/javase/tutorial/security/toolfilex/rstep1.html
http://docs.Oracle.com/javase/1.5.0/docs/tooldocs/windows/keytool.html