Я собрал пример, который показывает один из способов сделать это. Большая часть этого кода была украдена из библиотек bouncycastle pkix или lwcrypto, но любые ошибки почти наверняка мои. Наиболее важным способом сосредоточиться на ниже является generateCert
. Остальная часть кода является тестовой жгутом для тестирования.
Код специально написан для использования только bounycastle bcpkix и lwcrypto jars. Его можно было бы укоротить, если вместо lwcrypto использовать bcprov jar.
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.TBSCertificate;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.bc.BcX509v3CertificateBuilder;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import javax.security.auth.x500.X500Principal;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Date;
public class Main {
private static class TBSCertPlusSignature {
private final byte[] encodedTbsCert;
private final byte[] signature;
public TBSCertPlusSignature(byte[] encodedTbsCert, byte[] signature) {
this.encodedTbsCert = encodedTbsCert;
this.signature = signature;
}
public byte[] getEncodedTbsCert() {
return encodedTbsCert;
}
public byte[] getSignature() {
return signature;
}
}
private static TBSCertPlusSignature makeTestCert(KeyPair keyPair) throws Exception {
Date now = new Date();
Date nowPlus1Hour = new Date(now.getTime() + 1000 * 60 * 60 * 1L);
byte[] encodedName = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US").getEncoded();
X500Name issuer = X500Name.getInstance(encodedName);
X500Name subject = issuer;
RSAPublicKey rsaPub = (RSAPublicKey) keyPair.getPublic();
RSAKeyParameters rsaPubParams = new RSAKeyParameters(false, rsaPub.getModulus(), rsaPub.getPublicExponent());
BcX509v3CertificateBuilder certBuilder = new BcX509v3CertificateBuilder(
issuer,
BigInteger.valueOf(100L),
now,
nowPlus1Hour,
subject,
rsaPubParams
);
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSA");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
RSAPrivateCrtKey rsaPriv = (RSAPrivateCrtKey) keyPair.getPrivate();
RSAPrivateCrtKeyParameters rsaPrivParams = new RSAPrivateCrtKeyParameters(
rsaPriv.getModulus(),
rsaPriv.getPublicExponent(),
rsaPriv.getPrivateExponent(),
rsaPriv.getPrimeP(),
rsaPriv.getPrimeQ(),
rsaPriv.getPrimeExponentP(),
rsaPriv.getPrimeExponentQ(),
rsaPriv.getCrtCoefficient()
);
ContentSigner contentSigner = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(rsaPrivParams);
final X509CertificateHolder x509CertificateHolder = certBuilder.build(contentSigner);
byte[] tbsCertDER = x509CertificateHolder.toASN1Structure().getTBSCertificate().getEncoded();
byte[] signature = x509CertificateHolder.getSignature();
return new TBSCertPlusSignature(tbsCertDER, signature);
}
private static X509Certificate generateCert(byte[] tbsCertEncoded, byte[] signature) throws Exception {
// Given the der encoded TBS cert and signature, create the corresponding X509 certificate
TBSCertificate tbsCert = TBSCertificate.getInstance(tbsCertEncoded);
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(tbsCert);
v.add(tbsCert.getSignature());
v.add(new DERBitString(signature));
DERSequence derSequence = new DERSequence(v);
ByteArrayInputStream baos = new ByteArrayInputStream(derSequence.getEncoded());
return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(baos);
}
public static void main(String[] args) throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair keyPair = kpg.generateKeyPair();
TBSCertPlusSignature testData = makeTestCert(keyPair);
X509Certificate x509Cert = generateCert(testData.getEncodedTbsCert(), testData.getSignature());
// Verify the signature
x509Cert.verify(keyPair.getPublic());
// Print the cert
PublicKey publicKey = x509Cert.getPublicKey();
System.out.println(x509Cert);
}
}