org.bouncycastle.mail.smime.SMIMESigned Maven / Gradle / Ivy
Show all versions of bcmail-jdk14 Show documentation
package org.bouncycastle.mail.smime;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.activation.CommandMap;
import javax.activation.MailcapCommandMap;
import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessable;
import org.bouncycastle.cms.CMSSignedData;
/**
* general class for handling a pkcs7-signature message.
*
* A simple example of usage - note, in the example below the validity of
* the certificate isn't verified, just the fact that one of the certs
* matches the given signer...
*
*
* CertStore certs = s.getCertificates("Collection", "BC");
* SignerInformationStore signers = s.getSignerInfos();
* Collection c = signers.getSigners();
* Iterator it = c.iterator();
*
* while (it.hasNext())
* {
* SignerInformation signer = (SignerInformation)it.next();
* Collection certCollection = certs.getCertificates(signer.getSID());
*
* Iterator certIt = certCollection.iterator();
* X509Certificate cert = (X509Certificate)certIt.next();
*
* if (signer.verify(cert.getPublicKey()))
* {
* verified++;
* }
* }
*
* * Note: if you are using this class with AS2 or some other protocol * that does not use 7bit as the default content transfer encoding you * will need to use the constructor that allows you to specify the default * content transfer encoding, such as "binary". *
*/ public class SMIMESigned extends CMSSignedData { Object message; MimeBodyPart content; private static InputStream getInputStream( Part bodyPart) throws MessagingException { try { if (bodyPart.isMimeType("multipart/signed")) { throw new MessagingException("attempt to create signed data object from multipart content - use MimeMultipart constructor."); } return bodyPart.getInputStream(); } catch (IOException e) { throw new MessagingException("can't extract input stream: " + e); } } static { final MailcapCommandMap mc = (MailcapCommandMap)CommandMap.getDefaultCommandMap(); mc.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature"); mc.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime"); mc.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature"); mc.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime"); mc.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed"); AccessController.doPrivileged(new PrivilegedAction() { public Object run() { CommandMap.setDefaultCommandMap(mc); return null; } }); } /** * base constructor using a defaultContentTransferEncoding of 7bit * * @exception MessagingException on an error extracting the signature or * otherwise processing the message. * @exception CMSException if some other problem occurs. */ public SMIMESigned( MimeMultipart message) throws MessagingException, CMSException { super(new CMSProcessableBodyPartInbound(message.getBodyPart(0)), getInputStream(message.getBodyPart(1))); this.message = message; this.content = (MimeBodyPart)message.getBodyPart(0); } /** * base constructor with settable contentTransferEncoding * * @param message the signed message * @param defaultContentTransferEncoding new default to use * @exception MessagingException on an error extracting the signature or * otherwise processing the message. * @exception CMSException if some other problem occurs. */ public SMIMESigned( MimeMultipart message, String defaultContentTransferEncoding) throws MessagingException, CMSException { super(new CMSProcessableBodyPartInbound(message.getBodyPart(0), defaultContentTransferEncoding), getInputStream(message.getBodyPart(1))); this.message = message; this.content = (MimeBodyPart)message.getBodyPart(0); } /** * base constructor for a signed message with encapsulated content. * * @exception MessagingException on an error extracting the signature or * otherwise processing the message. * @exception SMIMEException if the body part encapsulated in the message cannot be extracted. * @exception CMSException if some other problem occurs. */ public SMIMESigned( Part message) throws MessagingException, CMSException, SMIMEException { super(getInputStream(message)); this.message = message; CMSProcessable cont = this.getSignedContent(); if (cont != null) { byte[] contBytes = (byte[])cont.getContent(); this.content = SMIMEUtil.toMimeBodyPart(contBytes); } } /** * return the content that was signed. */ public MimeBodyPart getContent() { return content; } /** * Return the content that was signed as a mime message. * * @param session * @return a MimeMessage holding the content. * @throws MessagingException */ public MimeMessage getContentAsMimeMessage(Session session) throws MessagingException, IOException { Object content = getSignedContent().getContent(); byte[] contentBytes = null; if (content instanceof byte[]) { contentBytes = (byte[])content; } else if (content instanceof MimePart) { MimePart part = (MimePart)content; ByteArrayOutputStream out; if (part.getSize() > 0) { out = new ByteArrayOutputStream(part.getSize()); } else { out = new ByteArrayOutputStream(); } part.writeTo(out); contentBytes = out.toByteArray(); } else { String type = " "; if (content != null) { type = content.getClass().getName(); } throw new MessagingException( "Could not transfrom content of type " + type + " into MimeMessage."); } if (contentBytes != null) { ByteArrayInputStream in = new ByteArrayInputStream(contentBytes); return new MimeMessage(session, in); } return null; } /** * return the content that was signed - depending on whether this was * unencapsulated or not it will return a MimeMultipart or a MimeBodyPart */ public Object getContentWithSignature() { return message; } }