📄 smimeutilities.java
字号:
/*** $Id: SMimeUtilities.java,v 1.7 2001/05/07 12:37:22 kunugi Exp $**** Copyright (c) 2000-2001 Jeff Gay** on behalf of ICEMail.org <http://www.icemail.org>** Copyright (c) 1998-2000 by Timothy Gerard Endres** ** This program is free software.** ** You may redistribute it and/or modify it under the terms of the GNU** General Public License as published by the Free Software Foundation.** Version 2 of the license should be included with this distribution in** the file LICENSE, as well as License.html. If the license is not** included with this distribution, you may find a copy at the FSF web** site at 'www.gnu.org' or 'www.fsf.org', or you may write to the** Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.**** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR** REDISTRIBUTION OF THIS SOFTWARE. */package org.icemail.mail.smime;import java.awt.Frame;import java.io.*;import java.util.*;import java.security.PrivateKey;import java.security.Principal;import java.security.SignatureException;import java.security.AlgorithmParameters;import java.security.spec.AlgorithmParameterSpec;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.security.InvalidAlgorithmParameterException;import java.security.spec.InvalidParameterSpecException;import javax.crypto.spec.RC2ParameterSpec;import javax.mail.*;import javax.mail.internet.*;import javax.swing.JDialog;import javax.swing.JOptionPane;import javax.activation.*;import iaik.asn1.ASN1;import iaik.asn1.structures.Attribute;import iaik.asn1.structures.ChoiceOfTime;import iaik.asn1.ASN1Object;import iaik.asn1.DerCoder;import iaik.asn1.ObjectID;import iaik.asn1.CodingException;import iaik.asn1.structures.AlgorithmID;import iaik.pkcs.PKCSException;import iaik.pkcs.PKCSParsingException;import iaik.pkcs.pkcs7.ContentInfo;import iaik.pkcs.pkcs7.Data;import iaik.pkcs.pkcs7.DigestedData;import iaik.pkcs.pkcs7.EncryptedData;import iaik.pkcs.pkcs7.EnvelopedData;import iaik.pkcs.pkcs7.EncryptedContentInfo;import iaik.pkcs.pkcs7.IssuerAndSerialNumber;import iaik.pkcs.pkcs7.PKCS7Content;import iaik.pkcs.pkcs7.RecipientInfo;import iaik.pkcs.pkcs7.SignedAndEnvelopedData;import iaik.pkcs.pkcs7.SignedData;import iaik.pkcs.pkcs7.SignerInfo;import iaik.pkcs.pkcs12.NetscapeP12;import iaik.pkcs.pkcs12.MicrosoftP12;import java.security.spec.RSAPrivateKeySpec;import javax.crypto.SecretKey;import iaik.x509.X509Certificate;import com.entrust.security.exceptions.EntrustBaseException;import org.icemail.Package;import org.icemail.mail.MessageUtilities;import org.icemail.smime.SMIMELibrary;import org.icemail.smime.MissingCertificateException;import org.icemail.smime.PasswordCancelException;import org.icemail.util.AWTUtilities;import org.icemail.util.StreamUtilities;import org.icemail.util.UserProperties;/** * This class provides the ICEMail "SMIME API". You can replace this class * with a dummy if you can not deal with the current dependency on the * Entrust library. Or, replace it with your own, which will require an * almost complete replacement of this package. For that I apologize. This * API will be moving to a "factory like" API that produces the API that * can provide SMIME and all will be funneled through a very thin Interface. * * The primary model is that an SMIME message is parsed by this class, and * you then access the SMIME aspects of the message via this class until a * new message is parsed, at which time the information is replaced with * that of the newly parsed message. */public class SMimeUtilities implements SMIMELibrary{ private static final int Debug_ = Package.DEBUG ? Package.getLevel( "SMimeUtilities" ) : 0; static { // initialize the Entrust library com.entrust.util.Util.initCiphers(); } protected boolean signed_ = false; protected boolean enveloped_ = false; protected AlgorithmID algorithm_ = new AlgorithmID(); protected RecipientInfo[] recipientInfos_ = new RecipientInfo[1]; protected SignerInfo[] signerInfos_ = new SignerInfo[1]; protected X509Certificate[] certificates_ = new X509Certificate[1]; protected Part part_ = null; public SMimeUtilities() { } public JDialog getConfiguration( Frame parent ) { return (JDialog)new SecurityConfigDialog( parent ); } public boolean isSigned( Part part ) { return signed_; } public boolean isEnveloped( Part part ) { return enveloped_; } public SignerInfo[] getSignerInfos() { return signerInfos_; } public RecipientInfo[] getRecipientInfos() { return recipientInfos_; } public X509Certificate[] getCertificates() { return certificates_; } public void showEnvelope( Part part ) { RecipientInfo[] recips = getRecipientInfos(); String message = "There were " + recips.length + " enveloped recipients.\n" + "The encryption algorithm used was '" + algorithm_.getName() + "'."; JOptionPane.showMessageDialog( null, message, "Algorithm", JOptionPane.INFORMATION_MESSAGE ); } public void showSigners( Part part ) { SignerInfo[] signers = getSignerInfos(); if ( signers.length < 1 ) return; if ( false ) { for ( int i = 0 ; i < signers.length ; ++i ) { SignerInfo si = signers[i]; System.err.println( "SIGNER["+i+"] = '" + si + "'" ); } } IssuerAndSerialNumber iasn = signers[0].getIssuerAndSerialNumber(); X509Certificate[] certs = getCertificates(); if ( false ) { for ( int i = 0 ; i < certs.length ; ++i ) System.err.println( "CERT["+i+"] = " + certs[i].toString(true) ); } X509Certificate signCert = null; for ( int i = 0 ; i < certs.length ; ++i ) { if ( iasn.isIssuerOf( certs[i] ) && iasn.getSerialNumber().equals( certs[i].getSerialNumber() ) ) { if ( false ) { System.err.println( "USING SIGNING CERTIFICATE # "+i ); } signCert = certs[i]; break; } } // Walk up the certificate chain by matching the current // "issuer DN" to the "subject DN"s of all certs until we // fail to find a match. Vector cV = new Vector(); cV.addElement( signCert ); X509Certificate currCert = signCert; for ( ; ; ) { boolean located = false; Principal currI = currCert.getIssuerDN(); for ( int i = 0 ; i < certs.length ; ++i ) { Principal p = certs[i].getSubjectDN(); if ( p.equals( currI ) ) { located = true; currCert = certs[i]; cV.insertElementAt( currCert, 0 ); break; } } if ( ! located ) break; if ( currCert.getIssuerDN().equals( currCert.getSubjectDN() ) ) break; } X509Certificate[] chain = new X509Certificate[ cV.size() ]; cV.copyInto( chain ); CertificateDialog dlg = new CertificateDialog( null, "Certificates", chain, true ); dlg.setLocation( AWTUtilities.computeDialogLocation( dlg ) ); dlg.show(); } /** * Determine if the given part contains an SMime message. * The method uses the standards from RFC 2311 - S/MIME Version 2 Message Specification * * MIME type: application/pkcs7-mime * MIME type: application/x-pkcs7-mime (early implementation) * parameters: any (smime-type certs-only enveloped-data signed-data) * file suffix: any * * MIME type: application/pkcs10 * MIME type: application/x-pkcs10 (early implementation) * parameters: any * file suffix: any * * MIME type: multipart/signed * parameters: micalg=<algorithm> * parameters: protocol="application/pkcs7-signature" * parameters: protocol="application/x-pkcs7-signature" (early implementation) * file suffix: any * * MIME type: application/octet-stream * parameters: any * file suffix: .p7m (application/pkcs7-mime) * .p7s (application/pkcs7-signature) * .aps * .p7c (application/pkcs7-mime, degenerate signedData "certs-only" message) * .p10 (application/pkcs10) */ public boolean isSMimeMessage( Part part ) throws MessagingException { if ( Package.DEBUG && Package.isTraceable( "SMimeUtilities" ) ) { System.out.println( "SMimeUtilities.isSMimeMessage(p)" ); } if ( part.isMimeType( "application/pkcs7-mime" ) || part.isMimeType( "application/x-pkcs7-mime" ) ) { return true; } if ( part.isMimeType( "application/pkcs10" ) ) { return true; } if ( part.isMimeType( "multipart/signed" ) ) { ContentType xct = new ContentType( part.getContentType() ); String xprotocol = xct.getParameter( "protocol" ); String xmicalg = xct.getParameter( "micalg" ); if ( xprotocol != null && xmicalg != null && ( xprotocol.equals( "application/pkcs7-signature" ) || xprotocol.equals( "application/x-pkcs7-signature" ) ) ) { return true; } } if ( part.isMimeType( "application/ocet-stream" ) ) { String xfilename = part.getFileName(); if ( xfilename != null ) { if ( xfilename.endsWith( ".p7m" ) || xfilename.endsWith( ".p7s" ) || xfilename.endsWith( ".aps" ) || xfilename.endsWith( ".p7c" ) || xfilename.endsWith( ".p10" ) ) { return true; } } } return false; } /** * Clear the previous state of the library, and any parsed messages. */ public void clearState() { if ( Package.DEBUG && Package.isTraceable( "SMimeUtilities" ) ) { System.out.println( "SMimeUtilities.clearState()" ); } signed_ = false; enveloped_ = false; certificates_ = null; recipientInfos_ = null; signerInfos_ = null; } public Part getContentMessage( Session session, Part msg ) throws MessagingException { if ( Package.DEBUG && Package.isTraceable( "SMimeUtilities" ) ) { System.out.println( "SMimeUtilities.getContentMessage(s,p)" ); } // determine contents if ( ! isSMimeMessage( msg ) ) return msg; Part result = msg; try { Part p7sPart = null; if ( msg.isMimeType( "multipart/signed" ) ) { signed_ = true; enveloped_ = false; // Look for the 'smime.p7s' attachment... Multipart mPart = (Multipart)MessageUtilities.getPartContent( msg ); for ( int i = 0, partCount = mPart.getCount() ; i < partCount ; i++ ) { Part bodyPart = mPart.getBodyPart(i); if ( bodyPart.isMimeType( "application/pkcs7-signature" ) || bodyPart.isMimeType( "application/x-pkcs7-signature" ) ) { p7sPart = bodyPart; } else { part_ = bodyPart; } } if ( Debug_ > 0 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -