/*
* Created on 07-Jun-2004
* Created by Paul Gardner
* Copyright (C) 2004, 2005, 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/
package org.gudy.azureus2.core3.util.jar;
/**
* @author parg
*
*/
public class
AEJarSigner
{
}
/*
import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import java.util.jar.*;
import org.gudy.azureus2.core3.util.Debug;
import sun.misc.BASE64Encoder;
import sun.security.util.ManifestDigester;
import sun.security.util.SignatureFile;
public class
WUJarSigner
{
protected static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
protected String alias;
protected PrivateKey privateKey;
protected X509Certificate[] certChain;
public
WUJarSigner(
String _alias,
PrivateKey _privateKey,
X509Certificate[] _certChain )
{
alias = _alias;
privateKey = _privateKey;
certChain = _certChain;
}
protected Manifest
getManifestFile(
JarFile jarFile )
throws IOException
{
Manifest manifest = new Manifest();
JarEntry entry = jarFile.getJarEntry( MANIFEST_NAME );
if ( entry != null ){
manifest.read( jarFile.getInputStream( entry ) );
}
return manifest;
}
protected Map
removeMissingEntriesFromManifest(
Manifest manifest,
JarFile jarFile )
throws IOException
{
Map map = manifest.getEntries();
Iterator elements = map.keySet().iterator();
while( elements.hasNext() ){
String element = (String)elements.next();
if ( jarFile.getEntry( element ) == null ){
elements.remove();
}
}
return( map );
}
private Map
createEntries(
Manifest manifest,
JarFile jarFile )
throws IOException
{
Map entries = null;
if( manifest.getEntries().size() > 0 ){
// already existing manifest, just remove any extra entries
entries = removeMissingEntriesFromManifest( manifest, jarFile );
}else{
// new manifest, stick in default values
Attributes attributes = manifest.getMainAttributes();
attributes.putValue( Attributes.Name.MANIFEST_VERSION.toString(), "1.0" );
attributes.putValue( "Created-By", System.getProperty( "java.version" ) + " (" + System.getProperty( "java.vendor" ) + ")" );
entries = manifest.getEntries();
}
return entries;
}
protected String
updateDigest(
MessageDigest digest,
InputStream inputStream )
throws IOException
{
byte[] buffer = new byte[8192];
while( true ){
int len = inputStream.read( buffer);
if ( len <= 0 ){
break;
}
digest.update( buffer, 0, len );
}
inputStream.close();
return( new BASE64Encoder().encode( digest.digest()));
}
protected Map
updateManifestEntries(
Manifest manifest,
JarFile jar_file,
MessageDigest message_digest,
Map entries )
throws IOException
{
Enumeration jar_entries = jar_file.entries();
while ( jar_entries.hasMoreElements()){
JarEntry entry = (JarEntry)jar_entries.nextElement();
if ( entry.getName().startsWith( "META-INF" ) ){
continue;
}else if ( manifest.getAttributes( entry.getName() ) != null ){
Attributes attributes = manifest.getAttributes( entry.getName() );
attributes.putValue(
"SHA1-Digest",
updateDigest( message_digest, jar_file.getInputStream( entry ) ));
}else if ( !entry.isDirectory()){
Attributes attributes = new Attributes();
attributes.putValue(
"SHA1-Digest",
updateDigest( message_digest, jar_file.getInputStream( entry ) ));
entries.put( entry.getName(), attributes );
}
}
return( entries );
}
protected byte[]
serialiseManifest(
Manifest manifest )
throws IOException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write( baos );
baos.flush();
baos.close();
return( baos.toByteArray());
}
protected SignatureFile
createSignatureFile(
Manifest manifest,
MessageDigest messageDigest )
throws IOException
{
ManifestDigester manifestDigester = new ManifestDigester( serialiseManifest( manifest ) );
return( new SignatureFile(
new MessageDigest[]{ messageDigest },
manifest,
manifestDigester,
alias, true ));
}
protected void
writeJarEntry(
JarEntry entry,
JarFile jar_file,
JarOutputStream jos )
throws IOException
{
jos.putNextEntry( new JarEntry( entry.getName()));
byte[] buffer = new byte[8192];
InputStream is = jar_file.getInputStream( entry );
while( true ){
int len = is.read( buffer );
if ( len <= 0 ){
break;
}
jos.write( buffer, 0, len );
}
jos.closeEntry();
}
public void
signJarFile(
JarFile jar_file,
OutputStream output_stream )
throws NoSuchAlgorithmException, InvalidKeyException, CertificateException,
SignatureException, IOException
{
Manifest manifest = getManifestFile( jar_file );
Map entries = createEntries( manifest, jar_file );
MessageDigest messageDigest = MessageDigest.getInstance( "SHA1" );
updateManifestEntries( manifest, jar_file, messageDigest, entries );
SignatureFile signatureFile = createSignatureFile( manifest, messageDigest );
SignatureFile.Block block = signatureFile.generateBlock( privateKey, certChain, true );
String manifestFileName = MANIFEST_NAME;
JarOutputStream jos =
output_stream instanceof JarOutputStream?(JarOutputStream)output_stream:new JarOutputStream( output_stream );
JarEntry manifestFile = new JarEntry( manifestFileName );
jos.putNextEntry( manifestFile );
byte[] manifest_bytes = serialiseManifest( manifest );
jos.write( manifest_bytes );
jos.closeEntry();
String signatureFileName = signatureFile.getMetaName();
JarEntry signatureFileEntry = new JarEntry( signatureFileName );
jos.putNextEntry( signatureFileEntry );
signatureFile.write( jos );
jos.closeEntry();
String signatureBlockName = block.getMetaName();
JarEntry signatureBlockEntry = new JarEntry( signatureBlockName );
jos.putNextEntry( signatureBlockEntry );
block.write( jos );
jos.closeEntry();
Enumeration metaEntries = jar_file.entries();
while( metaEntries.hasMoreElements() ){
JarEntry metaEntry = (JarEntry)metaEntries.nextElement();
if ( metaEntry.getName().startsWith( "META-INF" ) &&
!( manifestFileName.equalsIgnoreCase( metaEntry.getName()) ||
signatureFileName.equalsIgnoreCase( metaEntry.getName()) ||
signatureBlockName.equalsIgnoreCase( metaEntry.getName()))){
writeJarEntry( metaEntry, jar_file, jos );
}
}
Enumeration allEntries = jar_file.entries();
while( allEntries.hasMoreElements() ){
JarEntry entry = (JarEntry)allEntries.nextElement();
if( !entry.getName().startsWith( "META-INF" )){
writeJarEntry( entry, jar_file, jos );
}
}
jos.flush();
jos.finish();
jar_file.close();
}
public void
signJarStream(
InputStream is,
OutputStream os )
throws NoSuchAlgorithmException, InvalidKeyException, CertificateException,
SignatureException, IOException
{
File temp_file = File.createTempFile("AZU", null );
FileOutputStream fos = null;
try{
byte[] buffer = new byte[8192];
fos = new FileOutputStream( temp_file );
while(true){
int len = is.read( buffer );
if ( len <= 0 ){
break;
}
fos.write( buffer, 0, len );
}
fos.close();
fos = null;
signJarFile( new JarFile(temp_file), os );
}finally{
try{
is.close();
}catch( Throwable e ){
Debug.printStackTrace( e );
}
if ( fos != null ){
try{
fos.close();
}catch( Throwable e ){
Debug.printStackTrace( e );
}
}
temp_file.delete();
}
}
}
*/