X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=getdown%2Fsrc%2Fgetdown%2Fcore%2Fsrc%2Fmain%2Fjava%2Fcom%2Fthreerings%2Fgetdown%2Ftools%2FDigester.java;fp=getdown%2Fsrc%2Fgetdown%2Fcore%2Fsrc%2Fmain%2Fjava%2Fcom%2Fthreerings%2Fgetdown%2Ftools%2FDigester.java;h=b04a6539ba237fef72680aa663fa4cb38dd4a635;hb=890092d4ca9b8c17a3f356eeb12f49440d5fc51c;hp=0000000000000000000000000000000000000000;hpb=15c6c6724878a5445e9f5bc6594719dbe81c1735;p=jalview.git diff --git a/getdown/src/getdown/core/src/main/java/com/threerings/getdown/tools/Digester.java b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/tools/Digester.java new file mode 100644 index 0000000..b04a653 --- /dev/null +++ b/getdown/src/getdown/core/src/main/java/com/threerings/getdown/tools/Digester.java @@ -0,0 +1,129 @@ +// +// Getdown - application installer, patcher and launcher +// Copyright (C) 2004-2018 Getdown authors +// https://github.com/threerings/getdown/blob/master/LICENSE + +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 com.threerings.getdown.data.Application; +import com.threerings.getdown.data.Digest; +import com.threerings.getdown.data.EnvConfig; +import com.threerings.getdown.data.Resource; +import com.threerings.getdown.util.Base64; + +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * 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 + { + switch (args.length) { + case 1: + createDigests(new File(args[0]), null, null, null); + break; + case 4: + createDigests(new File(args[0]), new File(args[1]), args[2], args[3]); + break; + default: + System.err.println("Usage: Digester app_dir [keystore_path password alias]"); + System.exit(255); + } + } + + /** + * Creates digest file(s) and optionally signs them if {@code keystore} is not null. + */ + public static void createDigests (File appdir, File keystore, String password, String alias) + throws IOException, GeneralSecurityException + { + for (int version = 1; version <= Digest.VERSION; version++) { + createDigest(version, appdir); + if (keystore != null) { + signDigest(version, appdir, keystore, password, alias); + } + } + } + + /** + * Creates a digest file in the specified application directory. + */ + public static void createDigest (int version, File appdir) + throws IOException + { + File target = new File(appdir, Digest.digestFile(version)); + System.out.println("Generating digest file '" + target + "'..."); + + // create our application and instruct it to parse its business + Application app = new Application(new EnvConfig(appdir)); + app.init(false); + + List rsrcs = new ArrayList<>(); + rsrcs.add(app.getConfigResource()); + rsrcs.addAll(app.getCodeResources()); + rsrcs.addAll(app.getResources()); + for (Application.AuxGroup ag : app.getAuxGroups()) { + rsrcs.addAll(ag.codes); + rsrcs.addAll(ag.rsrcs); + } + + // now generate the digest file + Digest.createDigest(version, rsrcs, target); + } + + /** + * Creates a digest file in the specified application directory. + */ + public static void signDigest (int version, File appdir, + File storePath, String storePass, String storeAlias) + throws IOException, GeneralSecurityException + { + String filename = Digest.digestFile(version); + File inputFile = new File(appdir, filename); + File signatureFile = new File(appdir, filename + Application.SIGNATURE_SUFFIX); + + try (FileInputStream storeInput = new FileInputStream(storePath); + FileInputStream dataInput = new FileInputStream(inputFile); + FileOutputStream signatureOutput = new FileOutputStream(signatureFile)) { + + // initialize the keystore + KeyStore store = KeyStore.getInstance("JKS"); + store.load(storeInput, storePass.toCharArray()); + PrivateKey key = (PrivateKey)store.getKey(storeAlias, storePass.toCharArray()); + + // sign the digest file + String algo = Digest.sigAlgorithm(version); + Signature sig = Signature.getInstance(algo); + 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 + String signed = Base64.encodeToString(sig.sign(), Base64.DEFAULT); + signatureOutput.write(signed.getBytes(UTF_8)); + } + } +}