📄 jadsignature.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 + -