/** * Validates that a signed entity has a valid message and signature. The signer's certificate is * validated to ensure authenticity of the message. Message tampering is also checked with the * message's digest and the signed digest in the message signature. * * @param signedEntity The entity containing the original signed part and the message signature. * @param signerCertificate The certificate used to sign the message. * @param anchors A collection of certificate anchors used to determine if the certificates used * in the signature can be validated as trusted certificates. */ public void checkSignature( SignedEntity signedEntity, X509Certificate signerCertificate, Collection<X509Certificate> anchors) throws SignatureValidationException { CMSSignedData signatureEnvelope = deserializeSignatureEnvelope(signedEntity); try { // there may be multiple signatures in the signed part... iterate through all the signing // certificates until one // is verified with the signerCertificate for (SignerInformation sigInfo : (Collection<SignerInformation>) signatureEnvelope.getSignerInfos().getSigners()) if (sigInfo.verify(signerCertificate, CryptoExtensions.getJCEProviderName())) return; // verified... return // at this point the signerCertificate cannot be verified with one of the signing // certificates.... throw new SignatureValidationException("Signature validation failure."); } catch (SignatureValidationException sve) { throw sve; } catch (Exception e) { throw new SignatureValidationException("Signature validation failure.", e); } }
private MimeBodyPart createEncryptedEnvelope( MimeBodyPart bodyPart, Collection<X509Certificate> encryptingCertificates) { if (bodyPart == null || encryptingCertificates == null || encryptingCertificates.size() == 0) { throw new IllegalArgumentException(); } if (LOGGER.isDebugEnabled()) { writePreEncypt(EntitySerializer.Default.serializeToBytes(bodyPart)); } SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator(); for (X509Certificate cert : encryptingCertificates) gen.addKeyTransRecipient(cert); MimeBodyPart retVal = null; try { retVal = gen.generate( bodyPart, toEncyAlgorithmOid(this.m_encryptionAlgorithm), CryptoExtensions.getJCEProviderName()); } catch (Exception e) { throw new MimeException(MimeError.Unexpected, e); } return retVal; }
private X509Certificate certFromData(byte[] data) { X509Certificate retVal = null; try { ByteArrayInputStream bais = new ByteArrayInputStream(data); // lets try this a as a PKCS12 data stream first try { KeyStore localKeyStore = KeyStore.getInstance("PKCS12", CryptoExtensions.getJCEProviderName()); localKeyStore.load(bais, "".toCharArray()); Enumeration<String> aliases = localKeyStore.aliases(); // we are really expecting only one alias if (aliases.hasMoreElements()) { String alias = aliases.nextElement(); X509Certificate cert = (X509Certificate) localKeyStore.getCertificate(alias); // check if there is private key Key key = localKeyStore.getKey(alias, "".toCharArray()); if (key != null && key instanceof PrivateKey) { retVal = X509CertificateEx.fromX509Certificate(cert, (PrivateKey) key); } else retVal = cert; } } catch (Exception e) { // must not be a PKCS12 stream, go on to next step } if (retVal == null) { // try X509 certificate factory next bais.reset(); bais = new ByteArrayInputStream(data); retVal = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(bais); } bais.close(); } catch (Exception e) { throw new NHINDException("Data cannot be converted to a valid X.509 Certificate", e); } return retVal; }
/** * Decrypts an entity with the provided certificates' private key. * * @param encryptedEntity The entity that will be decrypted. * @param decryptingCertificate The certificates whose private keys will be used to decrypt the * message. * @return A MimeEntity containing the decrypted part. */ public MimeEntity decrypt( MimeEntity encryptedEntity, Collection<X509CertificateEx> decryptingCertificates) { if (decryptingCertificates == null || decryptingCertificates.size() == 0) { throw new IllegalArgumentException(); } MimeEntity retEntity = null; try { if (LOGGER.isDebugEnabled()) { byte[] encryptedContent = encryptedEntity.getContentAsBytes(); writePreDecrypt(encryptedContent); } SMIMEEnveloped m = new SMIMEEnveloped(encryptedEntity); X509CertificateEx decryptCert = decryptingCertificates.iterator().next(); RecipientId recId = generateRecipientSelector(decryptCert); RecipientInformationStore recipients = m.getRecipientInfos(); RecipientInformation recipient = recipients.get(recId); byte[] decryptedPayload = recipient.getContent(decryptCert.getPrivateKey(), CryptoExtensions.getJCEProviderName()); if (LOGGER.isDebugEnabled()) { writePostDecrypt(decryptedPayload); } ByteArrayInputStream inStream = new ByteArrayInputStream(decryptedPayload); retEntity = new MimeEntity(inStream); } catch (MessagingException e) { throw new MimeException(MimeError.InvalidMimeEntity, e); } catch (Exception e) { throw new MimeException(MimeError.Unexpected, e); } return retEntity; }
static { initJVMParams(); CryptoExtensions.registerJCEProviders(); }
private X509Certificate certFromData(byte[] data) { X509Certificate retVal = null; try { // first check for wrapped data final CertContainer container = CertUtils.toCertContainer(data); if (container.getWrappedKeyData() != null) { // this is a wrapped key // make sure we have a KeyStoreManager configured if (this.mgr == null) { throw new NHINDException( AgentError.Unexpected, "Resolved certifiate has wrapped data, but resolver has not been configured to unwrap it."); } // create a new wrapped certificate object retVal = WrappedOnDemandX509CertificateEx.fromX509Certificate( mgr, container.getCert(), container.getWrappedKeyData()); return retVal; } ByteArrayInputStream bais = new ByteArrayInputStream(data); // lets try this a as a PKCS12 data stream first try { KeyStore localKeyStore = KeyStore.getInstance("PKCS12", CryptoExtensions.getJCEProviderName()); localKeyStore.load(bais, "".toCharArray()); Enumeration<String> aliases = localKeyStore.aliases(); // we are really expecting only one alias if (aliases.hasMoreElements()) { String alias = aliases.nextElement(); X509Certificate cert = (X509Certificate) localKeyStore.getCertificate(alias); // check if there is private key Key key = localKeyStore.getKey(alias, "".toCharArray()); if (key != null && key instanceof PrivateKey) { retVal = X509CertificateEx.fromX509Certificate(cert, (PrivateKey) key); } else retVal = cert; } } catch (Exception e) { // must not be a PKCS12 stream, go on to next step } if (retVal == null) { // try X509 certificate factory next bais.reset(); bais = new ByteArrayInputStream(data); retVal = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(bais); } bais.close(); } catch (Exception e) { throw new NHINDException("Data cannot be converted to a valid X.509 Certificate", e); } return retVal; }
private MimeMultipart createSignatureEntity( byte[] entity, Collection<X509Certificate> signingCertificates) { MimeMultipart retVal = null; try { MimeBodyPart signedContent = new MimeBodyPart(new ByteArrayInputStream(entity)); ASN1EncodableVector signedAttrs = new ASN1EncodableVector(); SMIMECapabilityVector caps = new SMIMECapabilityVector(); caps.addCapability(SMIMECapability.dES_EDE3_CBC); caps.addCapability(SMIMECapability.rC2_CBC, 128); caps.addCapability(SMIMECapability.dES_CBC); caps.addCapability(new DERObjectIdentifier("1.2.840.113549.1.7.1")); caps.addCapability(x509CertificateObjectsIdent); signedAttrs.add(new SMIMECapabilitiesAttribute(caps)); List certList = new ArrayList(); CMSSignedDataGenerator generator = new CMSSignedDataGenerator(); for (X509Certificate signer : signingCertificates) { if (signer instanceof X509CertificateEx) { generator.addSigner( ((X509CertificateEx) signer).getPrivateKey(), signer, toDigestAlgorithmOid(this.m_digestAlgorithm), createAttributeTable(signedAttrs), null); certList.add(signer); } } CertStore certsAndcrls = CertStore.getInstance( "Collection", new CollectionCertStoreParameters(certList), CryptoExtensions.getJCEProviderName()); generator.addCertificatesAndCRLs(certsAndcrls); CMSProcessableBodyPart content = new CMSProcessableBodyPart(signedContent); CMSSignedData signedData = generator.generate(content, false, CryptoExtensions.getJCEProviderName()); String header = "signed; protocol=\"application/pkcs7-signature\"; micalg=" + toDigestAlgorithmMicalg(this.m_digestAlgorithm); String encodedSig = Base64.encodeBase64String(signedData.getEncoded()); retVal = new MimeMultipart(header.toString()); MimeBodyPart sig = new MimeBodyPart(new InternetHeaders(), encodedSig.getBytes("ASCII")); sig.addHeader( "Content-Type", "application/pkcs7-signature; name=smime.p7s; smime-type=signed-data"); sig.addHeader("Content-Disposition", "attachment; filename=\"smime.p7s\""); sig.addHeader("Content-Description", "S/MIME Cryptographic Signature"); sig.addHeader("Content-Transfer-Encoding", "base64"); retVal.addBodyPart(signedContent); retVal.addBodyPart(sig); } catch (MessagingException e) { throw new MimeException(MimeError.InvalidMimeEntity, e); } catch (IOException e) { throw new SignatureException(SignatureError.InvalidMultipartSigned, e); } catch (Exception e) { throw new NHINDException(MimeError.Unexpected, e); } return retVal; }