⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jadsignature.java

📁 eclipseme的最新版本的source,欢迎j2me程序员使用
💻 JAVA
字号:
/*  
 ********************************************************************
 * 
 *	File    	:   JadSignature.java
 *  Package     :   eclipseme.core.internal.signing
 *	System      :   eclipseme.core
 *	Author      :   Kevin Hunter
 *	Description :   This class provides the implementation for signing
 *					MIDlet suites.
 *	                
 * Copyright (c) 2003-2004 Kevin Hunter
 * All Rights Reserved.
 * Licensed under the Eclipse Public License - v 1.0
 * For more information see http://www.eclipse.org/legal/epl-v10.html
 *
 *  CVS
 *	$$Source: /cvsroot/eclipseme/eclipseme.core/src/eclipseme/core/internal/signing/JadSignature.java,v $$
 *	$$Author: setera $$
 *	$$Date: 2005/07/08 21:47:04 $$
 *	$$Revision: 1.6 $$
 *
 ********************************************************************
 */

package eclipseme.core.internal.signing;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;

import eclipseme.core.EclipseMECoreErrors;
import eclipseme.core.internal.EclipseMECorePlugin;
import eclipseme.core.model.IJadSignature;

/**
 * This class implements the dirty work of signing a MIDlet suite.  MIDlet
 * suites are signed by computing a signature for the JAR file, and then
 * embedding the encrypted signature, along with the certificate chain for
 * the public key used to verify the signature, in the JAD file that
 * accompanies the JAR file.
 * <p>To use this class:</p>
 * <ol>
 * <li>Load a <code>KeyChainSet</code> using the factory method 
 * <code>KeyChainSet.getInstance</code>.</li>
 * <li>Create and instance of this class, giving it the
 * <code>KeyChainSet</code> instance.</li>
 * <li>Call one of the <code>computeSignature</code> methods in order
 * to compute the signature for the JAR file</li>
 * <li>Retrieve the JAR signature string using <code>getJarSignatureString</code>
 * and add it to the JAD file using the tag "MIDlet-Jar-RSA-SHA1"</li>
 * <li>Retrieve the array of certificate strings using <code>getCertificateStrings</code>
 * and add the certificates to the JAD file using the tags
 * "MIDlet-Certificate-1-1" through "MIDlet-Certificate-1-n" (where "n" is the
 * number of certificates)</li>
 * </ol>
 * <p>Note that,
 * to make things easier for the code using this class, all low-level
 * crypto-type exceptions that can be thrown are wrapped in
 * an instance of <code>JadSignatureException</code>.</p>
 * 
 */

public class JadSignature implements IJadSignature
{
	private KeyChainSet		m_keyChainSet;		// contains the key and certificate for signing
	private byte[]			m_buffer;			// internal I/O buffer
	private String			m_strJarSignature;	// contains computed JAR file signature
	private String[]		m_strCertificates;	// contains computed certificate strings
	
	private static final int BUFFER_SIZE = 4096;// size of internal I/O buffer.
	
	/**
	 * Constructs a JadSignature instance without an associated <code>KeyChainSet</code>.
	 * <code>setKeyChainSet</code> must be called before calling <code>computeSignature</code>
	 * or an exception will be thrown.
	 *
	 */
	public JadSignature()
	{
	}
	
	/**
	 * Constructs a JadSignature instance that will use the specified <code>KeyChainSet</code>
	 * 
	 * @param kcs	The <code>KeyChainSet</code> to be used to sign the MIDlet suite.
	 */
	public JadSignature(KeyChainSet kcs)
	{
		setKeyChainSet(kcs);
	}
	
	/**
	 * Provides the <code>KeyChainSet</code> to be used to sign the MIDlet suite.
	 * 
	 * @param kcs	The <code>KeyChainSet</code> to be used to sign the MIDlet suite.
	 */
	public void setKeyChainSet(KeyChainSet kcs)
	{
		m_keyChainSet = kcs;
	}

	/**
	 * Returns the current <code>KeyChainSet</code>.
	 * 
	 * @return
	 */
	public KeyChainSet getKeyChainSet()
	{
		return(m_keyChainSet);
	}
	
	/**
	 * Returns the JAR signature string that should be added to the JAD file using the
	 * key "MIDlet-Jar-RSA-SHA1".
	 * 
	 * @return
	 */
	public String getJarSignatureString()
	{
		return(m_strJarSignature);
	}
	
	/**
	 * Returns an array of Strings containing the encoded certificates that can be used
	 * to verify the MIDlet suite signature.  These should be added to the JAD file using 
	 * the tags "MIDlet-Certificate-1-1" through "MIDlet-Certificate-1-n" (where "n" is the
	 * number of certificates)
	 * 
	 * @return
	 */
	public String[] getCertificateStrings()
	{
		return(m_strCertificates);
	}
	
	/**
	 * Computes the JAR file signature on the specified file.
	 * 
	 * @param jarFile		<code>File</code> of the JAR to be signed.
	 * @throws CoreException
	 */
	
	public void computeSignature(File jarFile) throws CoreException
	{
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		
		try
		{
			fis = new FileInputStream(jarFile);
			bis = new BufferedInputStream(fis);
			
			computeSignature(bis);
		}
		catch(Exception e)
		{
			EclipseMECorePlugin.throwCoreException(	IStatus.ERROR,
													9999,
													e);

		}
		finally
		{
			if (bis != null)
			{
				try
				{
					bis.close();
				}
				catch(IOException e)
				{
				}
			}
			
			if (fis != null)
			{
				try
				{
					fis.close();
				}
				catch(IOException e)
				{
				}
			}
		}
	}
	
	/**
	 * Computes the JAR file signature on the specified input stream.  Note that this
	 * method does not close the stream once the signature process is complete - that
	 * is left to the caller.
	 * 
	 * @param jarStream				<code>InputStream</code> of the JAR to be signed.
	 * @param strProvider			Cryptographic provider
	 * @throws IOException
	 * @throws JadSignatureException
	 */
	public void computeSignature(InputStream jarStream) 
		throws CoreException, IOException
	{
		checkKeyChainSet();
		
		X509Certificate[] chain = m_keyChainSet.getCertificateChain();
		PrivateKey key = m_keyChainSet.getKey();
		
		if (m_buffer == null)
		{
			m_buffer = new byte[BUFFER_SIZE];
		}
		
		try
		{
			m_strCertificates = new String[chain.length];
			for (int i = 0; i < chain.length; i++)
			{
				byte[] certBytes = chain[i].getEncoded();
				m_strCertificates[i] = Base64EncDec.encode(certBytes);
			}
			
	        Signature signature;
	        
	        if (m_keyChainSet.getProvider() == null)
	        {
	        	signature = Signature.getInstance("SHA1withRSA");
	        }
	        else
	        {
	        	signature = Signature.getInstance("SHA1withRSA", m_keyChainSet.getProvider());
	        }
	        
	        signature.initSign(key);
	        for(;;)
	        {
	            int nRead = jarStream.read(m_buffer);
	            if (nRead < 0)
	            {
	            	break;
	            }
	            
	            signature.update(m_buffer, 0, nRead);
	        }
		
	        byte sigBytes[] = signature.sign();
	        m_strJarSignature = Base64EncDec.encode(sigBytes);
		}
		catch(NoSuchAlgorithmException nsae)
		{
			EclipseMECoreErrors.throwCoreExceptionError(EclipseMECoreErrors.SIGNING_NO_SUCH_ALGORITHM, nsae);
		}
		catch(NoSuchProviderException nspe)
		{
			EclipseMECoreErrors.throwCoreExceptionError(EclipseMECoreErrors.SIGNING_PROVIDER_NOT_CONFIGURED, nspe);
		}
		catch(InvalidKeyException ike)
		{
			EclipseMECoreErrors.throwCoreExceptionError(EclipseMECoreErrors.SIGNING_INVALID_KEY, ike);
		}
		catch(SignatureException se)
		{
			EclipseMECoreErrors.throwCoreExceptionError(EclipseMECoreErrors.SIGNING_SIGNATURE_EXCEPTION, se);
		}
		catch(CertificateEncodingException cee)
		{
			EclipseMECoreErrors.throwCoreExceptionError(EclipseMECoreErrors.SIGNING_CERTIFICATE_ENCODING, cee);
		}
	}
	
	/**
	 * Checks the internal <code>KeyChainSet</code> to ensure that it can be used
	 * for signature purposes.
	 * 
	 * @throws JadSignatureException	If the <code>KeyChainSet</code> is not valid.
	 */
	
	public void checkKeyChainSet()
		throws CoreException
	{
		if (m_keyChainSet == null)
		{
			EclipseMECoreErrors.throwCoreExceptionError(EclipseMECoreErrors.SIGNING_INTERNAL_MISSING_KEYCHAINSET);
		}
		
		X509Certificate[] chain = m_keyChainSet.getCertificateChain();
		if (chain == null)
		{
			EclipseMECoreErrors.throwCoreExceptionError(EclipseMECoreErrors.SIGNING_MISSING_CERTIFICATES);
		}
		
		PrivateKey key = m_keyChainSet.getKey();
		String strKeyAlgorithm = key.getAlgorithm();
		if (!"RSA".equals(strKeyAlgorithm))
		{
			EclipseMECoreErrors.throwCoreExceptionError(EclipseMECoreErrors.SIGNING_BAD_KEY_TYPE);
		}
	}
}


/*
 ********************************************************************
 *	CVS History:
 *	$$Log: JadSignature.java,v $
 *	$Revision 1.6  2005/07/08 21:47:04  setera
 *	$Initial 1.1.0 changes:
 *	$- Convert to manifest files for plugin.xml
 *	$- Require JDT 3.1.0 for our feature
 *	$- Fix up build files to include new manifest files
 *	$- Fix up some of the deprecations
 *	$
 *	$Revision 1.5  2004/12/07 02:42:54  kdhunter
 *	$Switched from custom exception classes to CoreException
 *	$in signing routines.
 *	$Set up basic error code and error message handling, including
 *	$prep for internationalization
 *	$
 *	$Revision 1.4  2004/11/27 21:23:16  kdhunter
 *	$Documentation correction
 *	$
 *	$Revision 1.3  2004/11/27 21:18:10  kdhunter
 *	$Extracted an interface, switched to CoreException
 *	$for top-level routine
 *	$
 *	$Revision 1.2  2004/11/26 20:53:55  kdhunter
 *	$Added method to validate KeyChainSet
 *	$
 *	$Revision 1.1  2004/11/26 14:59:22  kdhunter
 *	$Moved here from original "external" package
 *	$$
 *
 ********************************************************************
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -