/** * Generate a CMS (Cryptographic Message Syntax) signature for a given byte content. The resulting * signature might contains the content itself and the certificate chain of the key used to sign. * * @param data the data to be signed * @param keyPair the certified key pair used for signing * @param certificateProvider Optionally, a certificate provider for obtaining the chain of * certificate to embed. If null, no certificate are embedded with the signature. * @param existingSignature if not null, a existing signature on the same data that should be * kept. * @param embedContent if true, the signed content is embedded with the signature. * @return the resulting signature encoded ASN.1 and in accordance with RFC 3852. * @throws GeneralSecurityException on error. */ public byte[] cmsSign( byte[] data, CertifiedKeyPair keyPair, CertificateProvider certificateProvider, CMSSignedDataVerified existingSignature, boolean embedContent) throws GeneralSecurityException { CMSSignedDataGeneratorParameters parameters = new CMSSignedDataGeneratorParameters() .addSigner(CertifyingSigner.getInstance(true, keyPair, signerFactory)); if (existingSignature != null) { for (CMSSignerInfo existingSigner : existingSignature.getSignatures()) { parameters.addSignature(existingSigner); } } Set<CertifiedPublicKey> certs = new HashSet<CertifiedPublicKey>(); if (existingSignature != null && existingSignature.getCertificates() != null) { certs.addAll(existingSignature.getCertificates()); } if (certificateProvider != null) { if (existingSignature != null) { for (CMSSignerInfo existingSigner : existingSignature.getSignatures()) { if (existingSigner.getSubjectKeyIdentifier() != null) { addCertificateChain( certificateProvider.getCertificate(existingSigner.getSubjectKeyIdentifier()), certificateProvider, certs); } else { addCertificateChain( certificateProvider.getCertificate( existingSigner.getIssuer(), existingSigner.getSerialNumber()), certificateProvider, certs); } } } addCertificateChain(keyPair.getCertificate(), certificateProvider, certs); } if (!certs.isEmpty()) { parameters.addCertificates(certs); } return cmsSignedDataGenerator.generate(data, parameters, embedContent); }
/** * Create an intermediate CA certificate. * * @param issuer the certified keypair for issuing the certificate * @param publicKey the public key to certify * @param dn the distinguished name for the new the certificate. * @param validity the validity of the certificate from now in days. * @return a certified public key. * @throws IOException in case on error while reading the public key. * @throws GeneralSecurityException in case of error. */ public CertifiedPublicKey issueIntermediateCertificate( CertifiedKeyPair issuer, PublicKeyParameters publicKey, String dn, int validity) throws IOException, GeneralSecurityException { return certificateGeneratorFactory .getInstance( CertifyingSigner.getInstance(true, issuer, signerFactory), new X509CertificateGenerationParameters( validity, extensionBuilder .get() .addBasicConstraints(0) .addKeyUsage(EnumSet.of(KeyUsage.keyCertSign, KeyUsage.cRLSign)) .build())) .generate(new DistinguishedName(dn), publicKey, new X509CertificateParameters()); }
/** * Create an end entity certificate. By default, the key can be used for encryption and signing. * If the end entity contains some alternate subject names of type X509Rfc822Name a extended email * protection usage is added. If the end entity contains some alternate subject names of type * X509DnsName or X509IpAddress extended server and client authentication usages are added. * * @param issuer the keypair for issuing the certificate * @param publicKey the public key to certify * @param dn the distinguished name for the new the certificate. * @param validity the validity of the certificate from now in days. * @param subjectAltName the alternative names for the certificate * @return a certified public key. * @throws IOException in case on error while reading the public key. * @throws GeneralSecurityException in case of error. */ public CertifiedPublicKey issueCertificate( CertifiedKeyPair issuer, PublicKeyParameters publicKey, String dn, int validity, List<X509GeneralName> subjectAltName) throws IOException, GeneralSecurityException { X509CertificateParameters params; X509ExtensionBuilder builder = extensionBuilder .get() .addKeyUsage(EnumSet.of(KeyUsage.digitalSignature, KeyUsage.dataEncipherment)); if (subjectAltName != null) { params = new X509CertificateParameters( extensionBuilder .get() .addSubjectAltName(false, subjectAltName.toArray(new X509GeneralName[] {})) .build()); Set<String> extUsage = new HashSet<String>(); for (X509GeneralName genName : subjectAltName) { if (genName instanceof X509Rfc822Name) { extUsage.add(ExtendedKeyUsages.EMAIL_PROTECTION); } else if (genName instanceof X509DnsName || genName instanceof X509IpAddress) { extUsage.add(ExtendedKeyUsages.SERVER_AUTH); extUsage.add(ExtendedKeyUsages.CLIENT_AUTH); } builder.addExtendedKeyUsage(false, new ExtendedKeyUsages(extUsage)); } } else { params = new X509CertificateParameters(); } return certificateGeneratorFactory .getInstance( CertifyingSigner.getInstance(true, issuer, signerFactory), new X509CertificateGenerationParameters(validity, builder.build())) .generate(new DistinguishedName(dn), publicKey, params); }