package org.bouncycastle.jce.provider.test; import java.io.ByteArrayInputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.DERBitString; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; import org.bouncycastle.asn1.x509.BasicConstraints; import org.bouncycastle.asn1.x509.CRLNumber; import org.bouncycastle.asn1.x509.CRLReason; import org.bouncycastle.asn1.x509.Certificate; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.Extensions; import org.bouncycastle.asn1.x509.ExtensionsGenerator; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.asn1.x509.GeneralNames; import org.bouncycastle.asn1.x509.KeyUsage; import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.TBSCertificate; import org.bouncycastle.asn1.x509.Time; import org.bouncycastle.asn1.x509.V1TBSCertificateGenerator; import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA1Digest; import org.bouncycastle.jce.PrincipalUtil; import org.bouncycastle.x509.X509V2CRLGenerator; import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure; /** * Test Utils */ class TestUtils { private static AtomicLong serialNumber = new AtomicLong(System.currentTimeMillis()); private static Map algIds = new HashMap(); static { algIds.put("GOST3411withGOST3410", new AlgorithmIdentifier(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_94)); algIds.put("SHA1withRSA", new AlgorithmIdentifier(PKCSObjectIdentifiers.sha1WithRSAEncryption, DERNull.INSTANCE)); algIds.put("SHA256withRSA", new AlgorithmIdentifier(PKCSObjectIdentifiers.sha256WithRSAEncryption, DERNull.INSTANCE)); algIds.put("SHA1withECDSA", new AlgorithmIdentifier(X9ObjectIdentifiers.ecdsa_with_SHA1)); algIds.put("SHA256withECDSA", new AlgorithmIdentifier(X9ObjectIdentifiers.ecdsa_with_SHA256)); } public static X509Certificate createSelfSignedCert(String dn, String sigName, KeyPair keyPair) throws Exception { return createSelfSignedCert(new X500Name(dn), sigName, keyPair); } public static X509Certificate createSelfSignedCert(X500Name dn, String sigName, KeyPair keyPair) throws Exception { V1TBSCertificateGenerator certGen = new V1TBSCertificateGenerator(); long time = System.currentTimeMillis(); certGen.setSerialNumber(new ASN1Integer(serialNumber.getAndIncrement())); certGen.setIssuer(dn); certGen.setSubject(dn); certGen.setStartDate(new Time(new Date(time - 5000))); certGen.setEndDate(new Time(new Date(time + 30 * 60 * 1000))); certGen.setSignature((AlgorithmIdentifier)algIds.get(sigName)); certGen.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded())); Signature sig = Signature.getInstance(sigName, "BC"); sig.initSign(keyPair.getPrivate()); sig.update(certGen.generateTBSCertificate().getEncoded(ASN1Encoding.DER)); TBSCertificate tbsCert = certGen.generateTBSCertificate(); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(tbsCert); v.add((AlgorithmIdentifier)algIds.get(sigName)); v.add(new DERBitString(sig.sign())); return (X509Certificate)CertificateFactory.getInstance("X.509", "BC").generateCertificate(new ByteArrayInputStream(new DERSequence(v).getEncoded(ASN1Encoding.DER))); } public static X509Certificate createCert(X500Name signerName, PrivateKey signerKey, String dn, String sigName, Extensions extensions, PublicKey pubKey) throws Exception { return createCert(signerName, signerKey, new X500Name(dn), sigName, extensions, pubKey); } public static X509Certificate createCert(X500Name signerName, PrivateKey signerKey, X500Name dn, String sigName, Extensions extensions, PublicKey pubKey) throws Exception { V3TBSCertificateGenerator certGen = new V3TBSCertificateGenerator(); long time = System.currentTimeMillis(); certGen.setSerialNumber(new ASN1Integer(serialNumber.getAndIncrement())); certGen.setIssuer(signerName); certGen.setSubject(dn); certGen.setStartDate(new Time(new Date(time - 5000))); certGen.setEndDate(new Time(new Date(time + 30 * 60 * 1000))); certGen.setSignature((AlgorithmIdentifier)algIds.get(sigName)); certGen.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(pubKey.getEncoded())); certGen.setExtensions(extensions); Signature sig = Signature.getInstance(sigName, "BC"); sig.initSign(signerKey); sig.update(certGen.generateTBSCertificate().getEncoded(ASN1Encoding.DER)); TBSCertificate tbsCert = certGen.generateTBSCertificate(); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(tbsCert); v.add((AlgorithmIdentifier)algIds.get(sigName)); v.add(new DERBitString(sig.sign())); return (X509Certificate)CertificateFactory.getInstance("X.509", "BC").generateCertificate(new ByteArrayInputStream(new DERSequence(v).getEncoded(ASN1Encoding.DER))); } /** * Create a random 1024 bit RSA key pair */ public static KeyPair generateRSAKeyPair() throws Exception { KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC"); kpGen.initialize(1024, new SecureRandom()); return kpGen.generateKeyPair(); } public static X509Certificate generateRootCert(KeyPair pair) throws Exception { return createSelfSignedCert("CN=Test CA Certificate", "SHA256withRSA", pair); } public static X509Certificate generateRootCert(KeyPair pair, X500Name dn) throws Exception { return createSelfSignedCert(dn, "SHA256withRSA", pair); } public static X509Certificate generateIntermediateCert(PublicKey intKey, PrivateKey caKey, X509Certificate caCert) throws Exception { return generateIntermediateCert( intKey, new X500Name("CN=Test Intermediate Certificate"), caKey, caCert); } public static X509Certificate generateIntermediateCert(PublicKey intKey, X500Name subject, PrivateKey caKey, X509Certificate caCert) throws Exception { Certificate caCertLw = Certificate.getInstance(caCert.getEncoded()); ExtensionsGenerator extGen = new ExtensionsGenerator(); extGen.addExtension(Extension.authorityKeyIdentifier, false, new AuthorityKeyIdentifier(getDigest(caCertLw.getSubjectPublicKeyInfo()), new GeneralNames(new GeneralName(caCertLw.getIssuer())), caCertLw.getSerialNumber().getValue())); extGen.addExtension(Extension.subjectKeyIdentifier, false, new SubjectKeyIdentifier(getDigest(SubjectPublicKeyInfo.getInstance(intKey.getEncoded())))); extGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0)); extGen.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign)); return createCert( caCertLw.getSubject(), caKey, subject, "SHA256withRSA", extGen.generate(), intKey); } public static X509Certificate generateEndEntityCert(PublicKey intKey, PrivateKey caKey, X509Certificate caCert) throws Exception { return generateEndEntityCert( intKey, new X500Name("CN=Test End Certificate"), caKey, caCert); } public static X509Certificate generateEndEntityCert(PublicKey entityKey, X500Name subject, PrivateKey caKey, X509Certificate caCert) throws Exception { Certificate caCertLw = Certificate.getInstance(caCert.getEncoded()); ExtensionsGenerator extGen = new ExtensionsGenerator(); extGen.addExtension(Extension.authorityKeyIdentifier, false, new AuthorityKeyIdentifier(getDigest(caCertLw.getSubjectPublicKeyInfo()), new GeneralNames(new GeneralName(caCertLw.getIssuer())), caCertLw.getSerialNumber().getValue())); extGen.addExtension(Extension.subjectKeyIdentifier, false, new SubjectKeyIdentifier(getDigest(entityKey.getEncoded()))); extGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0)); extGen.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign | KeyUsage.cRLSign)); return createCert( caCertLw.getSubject(), caKey, subject, "SHA256withRSA", extGen.generate(), entityKey); } public static X509CRL createCRL( X509Certificate caCert, PrivateKey caKey, BigInteger serialNumber) throws Exception { X509V2CRLGenerator crlGen = new X509V2CRLGenerator(); Date now = new Date(); BigInteger revokedSerialNumber = BigInteger.valueOf(2); crlGen.setIssuerDN(PrincipalUtil.getSubjectX509Principal(caCert)); crlGen.setThisUpdate(now); crlGen.setNextUpdate(new Date(now.getTime() + 100000)); crlGen.setSignatureAlgorithm("SHA256WithRSAEncryption"); crlGen.addCRLEntry(serialNumber, now, CRLReason.privilegeWithdrawn); crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert)); crlGen.addExtension(X509Extensions.CRLNumber, false, new CRLNumber(BigInteger.valueOf(1))); return crlGen.generate(caKey, "BC"); } public static X509Certificate createExceptionCertificate(boolean exceptionOnEncode) { return new ExceptionCertificate(exceptionOnEncode); } public static X500Name getCertIssuer(X509Certificate x509Certificate) throws CertificateEncodingException { return TBSCertificate.getInstance(x509Certificate.getTBSCertificate()).getIssuer(); } public static X500Name getCertSubject(X509Certificate x509Certificate) throws CertificateEncodingException { return TBSCertificate.getInstance(x509Certificate.getTBSCertificate()).getSubject(); } private static class ExceptionCertificate extends X509Certificate { private boolean _exceptionOnEncode; public ExceptionCertificate(boolean exceptionOnEncode) { _exceptionOnEncode = exceptionOnEncode; } public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { throw new CertificateNotYetValidException(); } public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException { throw new CertificateExpiredException(); } public int getVersion() { return 0; } public BigInteger getSerialNumber() { return null; } public Principal getIssuerDN() { return null; } public Principal getSubjectDN() { return null; } public Date getNotBefore() { return null; } public Date getNotAfter() { return null; } public byte[] getTBSCertificate() throws CertificateEncodingException { throw new CertificateEncodingException(); } public byte[] getSignature() { return new byte[0]; } public String getSigAlgName() { return null; } public String getSigAlgOID() { return null; } public byte[] getSigAlgParams() { return new byte[0]; } public boolean[] getIssuerUniqueID() { return new boolean[0]; } public boolean[] getSubjectUniqueID() { return new boolean[0]; } public boolean[] getKeyUsage() { return new boolean[0]; } public int getBasicConstraints() { return 0; } public byte[] getEncoded() throws CertificateEncodingException { if (_exceptionOnEncode) { throw new CertificateEncodingException(); } return new byte[0]; } public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { throw new CertificateException(); } public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { throw new CertificateException(); } public String toString() { return null; } public PublicKey getPublicKey() { return null; } public boolean hasUnsupportedCriticalExtension() { return false; } public Set getCriticalExtensionOIDs() { return null; } public Set getNonCriticalExtensionOIDs() { return null; } public byte[] getExtensionValue(String oid) { return new byte[0]; } } private static byte[] getDigest(SubjectPublicKeyInfo spki) { return getDigest(spki.getPublicKeyData().getBytes()); } private static byte[] getDigest(byte[] bytes) { Digest digest = new SHA1Digest(); byte[] resBuf = new byte[digest.getDigestSize()]; digest.update(bytes, 0, bytes.length); digest.doFinal(resBuf, 0); return resBuf; } private static class AtomicLong { private long value; public AtomicLong(long value) { this.value = value; } public synchronized long getAndIncrement() { return value++; } } }