📄 manifest.java
字号:
/* * Copyright (c) 2000 David Flanagan. All rights reserved. * This code is from the book Java Examples in a Nutshell, 2nd Edition. * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied. * You may study, use, and modify it for any non-commercial purpose. * You may distribute it non-commercially as long as you retain this notice. * For a commercial use license, or to purchase the book (recommended), * visit http://www.davidflanagan.com/javaexamples2. */package com.davidflanagan.examples.security;import java.security.*;import java.io.*;import java.util.*;/** * This program creates a manifest file for the specified files, or verifies * an existing manifest file. By default the manifest file is named * MANIFEST, but the -m option can be used to override this. The -v * option specifies that the manifest should be verified. Verification is * also the default option if no files are specified. **/public class Manifest { public static void main(String[] args) throws Exception { // Set the default values of the command-line arguments boolean verify = false; // Verify manifest or create one? String manifestfile = "MANIFEST"; // Manifest file name String digestAlgorithm = "MD5"; // Algorithm for message digests String signername = null; // Signer. No sig. by default String signatureAlgorithm = "DSA"; // Algorithm for digital sig. String password = null; // Private keys are protected File keystoreFile = null; // Where are keys stored String keystoreType = null; // What kind of keystore String keystorePassword = null; // How to access keystore List filelist = new ArrayList(); // The files to digest // Parse the command-line arguments, overriding the defaults above for(int i = 0; i < args.length; i++) { if (args[i].equals("-v")) verify = true; else if (args[i].equals("-m")) manifestfile = args[++i]; else if (args[i].equals("-da")&& !verify) digestAlgorithm = args[++i]; else if (args[i].equals("-s")&& !verify) signername = args[++i]; else if (args[i].equals("-sa")&& !verify) signatureAlgorithm = args[++i]; else if (args[i].equals("-p")) password = args[++i]; else if (args[i].equals("-keystore")) keystoreFile = new File(args[++i]); else if (args[i].equals("-keystoreType")) keystoreType = args[++i]; else if (args[i].equals("-keystorePassword")) keystorePassword = args[++i]; else if (!verify) filelist.add(args[i]); else throw new IllegalArgumentException(args[i]); } // If certain arguments weren't supplied, get default values. if (keystoreFile == null) { File dir = new File(System.getProperty("user.home")); keystoreFile = new File(dir, ".keystore"); } if (keystoreType == null) keystoreType = KeyStore.getDefaultType(); if (keystorePassword == null) keystorePassword = password; if (!verify && signername != null && password == null) { System.out.println("Use -p to specify a password."); return; } // Get the keystore we'll use for signing or verifying signatures // If no password was provided, then assume we won't be dealing with // signatures, and skip the keystore. KeyStore keystore = null; if (keystorePassword != null) { keystore = KeyStore.getInstance(keystoreType); InputStream in = new BufferedInputStream(new FileInputStream(keystoreFile)); keystore.load(in, keystorePassword.toCharArray()); } // If -v was specified or no file were given, verify a manifest // Otherwise, create a new manifest for the specified files if (verify || (filelist.size() == 0)) verify(manifestfile, keystore); else create(manifestfile, digestAlgorithm, signername, signatureAlgorithm, keystore, password, filelist); } /** * This method creates a manifest file with the specified name, for * the specified vector of files, using the named message digest * algorithm. If signername is non-null, it adds a digital signature * to the manifest, using the named signature algorithm. This method can * throw a bunch of exceptions. **/ public static void create(String manifestfile, String digestAlgorithm, String signername, String signatureAlgorithm, KeyStore keystore, String password, List filelist) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, KeyStoreException, UnrecoverableKeyException, IOException { // For computing a signature, we have to process the files in a fixed, // repeatable order, so sort them alphabetically. Collections.sort(filelist); int numfiles = filelist.size(); Properties manifest = new Properties(), metadata = new Properties(); MessageDigest md = MessageDigest.getInstance(digestAlgorithm); Signature signature = null; byte[] digest; // If a signer name was specified, then prepare to sign the manifest if (signername != null) { // Get a Signature object signature = Signature.getInstance(signatureAlgorithm); // Look up the private key of the signer from the keystore PrivateKey key = (PrivateKey) keystore.getKey(signername, password.toCharArray()); // No prepare to create a signature for the specified signer signature.initSign(key); } // Now, loop through the files, in a well-known alphabetical order System.out.print("Computing message digests"); for(int i = 0; i < numfiles; i++) { String filename = (String)filelist.get(i); // Compute the digest for each, and skip files that don't exist. try { digest = getFileDigest(filename, md); } catch (IOException e) { System.err.println("\nSkipping " + filename + ": " + e); continue; } // If we're computing a signature, use the bytes of the filename // and of the digest as part of the data to sign. if (signature != null) { signature.update(filename.getBytes()); signature.update(digest); } // Store the filename and the encoded digest bytes in the manifest manifest.put(filename, hexEncode(digest)); System.out.print('.'); System.out.flush(); } // If a signer was specified, compute signature for the manifest byte[] signaturebytes = null; if (signature != null) { System.out.print("done\nComputing digital signature..."); System.out.flush(); // Compute the digital signature by encrypting a message digest of // all the bytes passed to the update() method using the private // key of the signer. This is a time consuming operation. signaturebytes = signature.sign(); } // Tell the user what comes next System.out.print("done\nWriting manifest..."); System.out.flush(); // Store some metadata about this manifest, including the name of the // message digest algorithm it uses metadata.put("__META.DIGESTALGORITHM", digestAlgorithm); // If we're signing the manifest, store some more metadata if (signername != null) { // Store the name of the signer metadata.put("__META.SIGNER", signername); // Store the name of the algorithm metadata.put("__META.SIGNATUREALGORITHM", signatureAlgorithm); // And generate the signature, encode it, and store it metadata.put("__META.SIGNATURE", hexEncode(signaturebytes)); } // Now, save the manifest data and the metadata to the manifest file FileOutputStream f = new FileOutputStream(manifestfile); manifest.store(f, "Manifest message digests"); metadata.store(f, "Manifest metadata");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -