Генерация X509Certificate с BouncyCastle с Java
Это то, что у меня есть прямо сейчас, чтобы создать цифровой сертификат. И теперь я могу создать цифровой сертификат с паролем защищен закрытый ключ.
public static void main(String[] args) throws Exception {
Security.addProvider(new BouncyCastleProvider());
testKeyStore();
}
public static void testKeyStore() throws Exception {
try {
String storeName = "d://suresh_test.cer";
java.security.KeyPairGenerator keyPairGenerator = KeyPairGenerator
.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
X509Certificate trustCert = createCertificate("CN=CA", "CN=CA",
publicKey, privateKey);
java.security.cert.Certificate[] outChain = {
createCertificate("CN=Client", "CN=CA", publicKey,
privateKey), trustCert };
KeyStore outStore = KeyStore.getInstance("PKCS12");
outStore.load(null, "suresh_".toCharArray());
outStore.setKeyEntry("mykey", privateKey, "suresh_".toCharArray(),
outChain);
OutputStream outputStream = new FileOutputStream(storeName);
outStore.store(outputStream, "suresh_".toCharArray());
outputStream.flush();
outputStream.close();
KeyStore inStore = KeyStore.getInstance("PKCS12");
inStore.load(new FileInputStream(storeName),
"suresh_".toCharArray());
} catch (Exception e) {
e.printStackTrace();
throw new AssertionError(e.getMessage());
}
}
private static X509Certificate createCertificate(String dn, String issuer,
PublicKey publicKey, PrivateKey privateKey) throws Exception {
X509V3CertificateGenerator certGenerator = new X509V3CertificateGenerator();
certGenerator.setSerialNumber(BigInteger.valueOf(Math.abs(new Random()
.nextLong())));
certGenerator.setIssuerDN(new X509Name(dn));
certGenerator.setSubjectDN(new X509Name(dn));
certGenerator.setIssuerDN(new X509Name(issuer)); // Set issuer!
certGenerator.setNotBefore(Calendar.getInstance().getTime());
certGenerator.setNotAfter(Calendar.getInstance().getTime());
certGenerator.setPublicKey(publicKey);
certGenerator.setSignatureAlgorithm("SHA1WithRSAEncryption");
X509Certificate certificate = (X509Certificate) certGenerator.generate(
privateKey, "BC");
return certificate;
}
Как сделать это самостоятельно знак ?
У меня нет зацепок.
Как я могу приступить к этому ?
Спасибо за любые подсказки.
2 ответов
У вас был весь код, необходимый для создания самозаверяющего сертификата. Вам просто нужно было убедиться, что ваша цепочка содержит только один сертификат.
public static void testKeyStore() throws Exception {
try {
String storeName = "path/to/store";
java.security.KeyPairGenerator keyPairGenerator = KeyPairGenerator
.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
X509Certificate selfCert = createCertificate("CN=Client", "CN=Client",
publicKey, privateKey);
// Note: if you just want to store this certificate then write the
// contents of selfCert.getEncoded() to file
java.security.cert.Certificate[] outChain = { selfCert };
KeyStore outStore = KeyStore.getInstance("PKCS12");
outStore.load(null, PASSWORD.toCharArray());
outStore.setKeyEntry("mykey", privateKey, PASSWORD.toCharArray(),
outChain);
OutputStream outputStream = new FileOutputStream(storeName);
outStore.store(outputStream, PASSWORD.toCharArray());
outputStream.flush();
outputStream.close();
KeyStore inStore = KeyStore.getInstance("PKCS12");
inStore.load(new FileInputStream(storeName), PASSWORD.toCharArray());
} catch (Exception e) {
e.printStackTrace();
throw new AssertionError(e.getMessage());
}
}
Я бы посоветовал вам не бросать AssertionError
. Это должно использоваться только самой Java для указания assert
утверждение ложно.
проведя выходные, чтобы перенести нашу версию BC с 143 на 154, я публикую lessions узнал, надеясь, что это сэкономит некоторое время для кого-то в будущем.
1) API расширения PKI из BC был перемещен в собственный jar. Я ломал голову, чтобы найти Пемпарсер в bcprov-jdk15on-154.сосуд. Реализация для PemParser находится в bcpkix-jdk15on-154.сосуд. Излишне говорить, что pkix jar зависит от core BC jar.
2) класс PEMReader не доступен в последней версии Версия 154. Это было заменено PemParser.
3) чтение публичного сертификата из файла на диске:
Security.addProvider(new BouncyCastleProvider());
File file = new File("c:/mycert.crt");
X509Certificate cert = null;
PEMParser pemParser = new PEMParser(new FileReader(file));
Object object = pemParser.readObject();
if (object instanceof X509CertificateHolder) {
X509CertificateHolder holder = (X509CertificateHolder)object;
cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(holder);
}
if (cert == null) {
throw new Exception("mycert.crt" + " doesn't contain X509Certificate!");
}
return cert;
//If you need publicKey use cert.getPublicKey() method.
4) чтение защищенного паролем закрытого ключа с диска:
Security.addProvider(new BouncyCastleProvider());
KeyPair keyPair = null;
File file = new File("c:/myprivate.key");
PEMParser pemParser = new PEMParser(new FileReader(file));
Object object = pemParser.readObject();
if (object instanceof PEMEncryptedKeyPair) {
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
PEMEncryptedKeyPair ckp = (PEMEncryptedKeyPair) object;
PEMDecryptorProvider decProv =
new JcePEMDecryptorProviderBuilder().build("strongpasswordfor_myprivate.key".toCharArray());
keyPair = converter.getKeyPair(ckp.decryptKeyPair(decProv));
}
return keyPair;
//Once we have the keypair, we can get keyPair.getPrivate() [PrivateKey.class]
//or keyPair.getPublic() [PublicKey.class]
5) чтение сертификата на основе строки, как правило, это тот случай, когда мы хотим сделать взаимную аутентификацию SSL, и веб-сервер перенаправляет сертификат клиента на сервер приложений в заголовке Http-запроса:
Security.addProvider(new BouncyCastleProvider());
X509Certificate cert = null;
String myClientCert = "-----BEGIN CERTIFICATE----- CERTCONTENTS -----END CERTIFICATE-----"
String cert1 = myClientCert.replaceAll("-----BEGIN CERTIFICATE-----", "").replaceAll("-----END CERTIFICATE-----", "").replaceAll(" ", System.lineSeparator());
int ind = cert1.lastIndexOf(System.lineSeparator());
cert1 = new StringBuilder(cert1).replace(ind, ind + System.lineSeparator().length(), "").toString();
cert1 = BEGIN_CERT + cert1 + END_CERT;
PEMParser pemParser = new PEMParser(new StringReader(cert1));
Object object = pemParser.readObject();
if (object instanceof X509CertificateHolder) {
X509CertificateHolder holder = (X509CertificateHolder)object;
cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(holder);
}
return cert;
6) Излишне говорить, добавить ошибку обработка, управление исключениями и очистка на ваш вкус.