diff --git a/build-proguard.xml b/build-proguard.xml index 3fc6ca8..f56c1d2 100644 --- a/build-proguard.xml +++ b/build-proguard.xml @@ -54,6 +54,9 @@ + + + @@ -72,7 +75,7 @@ - + diff --git a/src/main/java/com/threerings/getdown/tools/Digester.java b/src/main/java/com/threerings/getdown/tools/Digester.java new file mode 100644 index 0000000..a059f2c --- /dev/null +++ b/src/main/java/com/threerings/getdown/tools/Digester.java @@ -0,0 +1,124 @@ +// +// $Id$ +// +// Getdown - application installer, patcher and launcher +// Copyright (C) 2004-2010 Three Rings Design, Inc. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials provided +// with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package com.threerings.getdown.tools; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.Signature; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.codec.binary.Base64; + +import com.threerings.getdown.data.Application; +import com.threerings.getdown.data.Digest; +import com.threerings.getdown.data.Resource; + +/** + * Handles the generation of the digest.txt file. + */ +public class Digester +{ + /** + * A command line entry point for the digester. + */ + public static void main (String[] args) + throws IOException, GeneralSecurityException + { + if (args.length != 1 || args.length != 4) { + System.err.println("Usage: Digester app_dir [keystore_path password alias]"); + System.exit(255); + } + + createDigest(new File(args[0])); + if (args.length == 4) { + signDigest(new File(args[0]), new File(args[1]), args[2], args[3]); + } + } + + /** + * Creates a digest file in the specified application directory. + */ + public static void createDigest (File appdir) + throws IOException + { + File target = new File(appdir, Digest.DIGEST_FILE); + System.out.println("Generating digest file '" + target + "'..."); + + // create our application and instruct it to parse its business + Application app = new Application(appdir, null); + app.init(false); + + List rsrcs = new ArrayList(); + rsrcs.add(app.getConfigResource()); + rsrcs.addAll(app.getCodeResources()); + rsrcs.addAll(app.getResources()); + for (String auxgroup : app.getAuxGroups()) { + rsrcs.addAll(app.getResources(auxgroup)); + } + + // now generate the digest file + Digest.createDigest(rsrcs, target); + } + + /** + * Creates a digest file in the specified application directory. + */ + public static void signDigest (File appdir, File storePath, String storePass, String storeAlias) + throws IOException, GeneralSecurityException + { + File inputFile = new File(appdir, Digest.DIGEST_FILE); + File signatureFile = new File(appdir, Digest.DIGEST_FILE + Application.SIGNATURE_SUFFIX); + + // initialize the keystore + KeyStore store = KeyStore.getInstance("JKS"); + FileInputStream storeInput = new FileInputStream(storePath); + store.load(storeInput, storePass.toCharArray()); + PrivateKey key = (PrivateKey)store.getKey(storeAlias, storePass.toCharArray()); + + // sign the digest file + Signature sig = Signature.getInstance("SHA1withRSA"); + FileInputStream dataInput = new FileInputStream(inputFile); + byte[] buffer = new byte[8192]; + int length; + + sig.initSign(key); + while ((length = dataInput.read(buffer)) != -1) { + sig.update(buffer, 0, length); + } + + // Write out the signature + FileOutputStream signatureOutput = new FileOutputStream(signatureFile); + String signed = new String(Base64.encodeBase64(sig.sign())); + signatureOutput.write(signed.getBytes("utf8")); + } +} diff --git a/src/main/java/com/threerings/getdown/tools/DigesterTask.java b/src/main/java/com/threerings/getdown/tools/DigesterTask.java index ac4be17..821a06e 100644 --- a/src/main/java/com/threerings/getdown/tools/DigesterTask.java +++ b/src/main/java/com/threerings/getdown/tools/DigesterTask.java @@ -25,24 +25,13 @@ package com.threerings.getdown.tools; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.Signature; -import org.apache.commons.codec.binary.Base64; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; -import com.threerings.getdown.data.Application; -import com.threerings.getdown.data.Digest; -import com.threerings.getdown.data.Resource; - /** * An ant task used to create a digest.txt for a Getdown * application deployment. @@ -102,9 +91,9 @@ public class DigesterTask extends Task } try { - createDigest(_appdir); + Digester.createDigest(_appdir); if (_storepath != null) { - signDigest(_appdir, _storepath, _storepass, _storealias); + Digester.signDigest(_appdir, _storepath, _storepass, _storealias); } } catch (IOException ioe) { throw new BuildException("Error creating digest: " + ioe.getMessage(), ioe); @@ -113,63 +102,6 @@ public class DigesterTask extends Task } } - /** - * Creates a digest file in the specified application directory. - */ - public static void createDigest (File appdir) - throws IOException - { - File target = new File(appdir, Digest.DIGEST_FILE); - System.out.println("Generating digest file '" + target + "'..."); - - // create our application and instruct it to parse its business - Application app = new Application(appdir, null); - app.init(false); - - ArrayList rsrcs = new ArrayList(); - rsrcs.add(app.getConfigResource()); - rsrcs.addAll(app.getCodeResources()); - rsrcs.addAll(app.getResources()); - for (String auxgroup : app.getAuxGroups()) { - rsrcs.addAll(app.getResources(auxgroup)); - } - - // now generate the digest file - Digest.createDigest(rsrcs, target); - } - - /** - * Creates a digest file in the specified application directory. - */ - public static void signDigest (File appdir, File storePath, String storePass, String storeAlias) - throws IOException, GeneralSecurityException - { - File inputFile = new File(appdir, Digest.DIGEST_FILE); - File signatureFile = new File(appdir, Digest.DIGEST_FILE + Application.SIGNATURE_SUFFIX); - - // initialize the keystore - KeyStore store = KeyStore.getInstance("JKS"); - FileInputStream storeInput = new FileInputStream(storePath); - store.load(storeInput, storePass.toCharArray()); - PrivateKey key = (PrivateKey)store.getKey(storeAlias, storePass.toCharArray()); - - // sign the digest file - Signature sig = Signature.getInstance("SHA1withRSA"); - FileInputStream dataInput = new FileInputStream(inputFile); - byte[] buffer = new byte[8192]; - int length; - - sig.initSign(key); - while ((length = dataInput.read(buffer)) != -1) { - sig.update(buffer, 0, length); - } - - // Write out the signature - FileOutputStream signatureOutput = new FileOutputStream(signatureFile); - String signed = new String(Base64.encodeBase64(sig.sign())); - signatureOutput.write(signed.getBytes("utf8")); - } - /** The application directory in which we're creating a digest file. */ protected File _appdir;