📄 manifest.java
字号:
System.out.println("done"); } /** * This method verifies the digital signature of the named manifest * file, if it has one, and if that verification succeeds, it verifies * the message digest of each file in filelist that is also named in the * manifest. This method can throw a bunch of exceptions **/ public static void verify(String manifestfile, KeyStore keystore) throws NoSuchAlgorithmException, SignatureException, InvalidKeyException, KeyStoreException, IOException { Properties manifest = new Properties(); manifest.load(new FileInputStream(manifestfile)); String digestAlgorithm = manifest.getProperty("__META.DIGESTALGORITHM"); String signername = manifest.getProperty("__META.SIGNER"); String signatureAlgorithm = manifest.getProperty("__META.SIGNATUREALGORITHM"); String hexsignature = manifest.getProperty("__META.SIGNATURE"); // Get a list of filenames in the manifest. List files = new ArrayList(); Enumeration names = manifest.propertyNames(); while(names.hasMoreElements()) { String s = (String)names.nextElement(); if (!s.startsWith("__META")) files.add(s); } int numfiles = files.size(); // If we've got a signature but no keystore, warn the user if (signername != null && keystore == null) System.out.println("Can't verify digital signature without " + "a keystore."); // If the manifest contained metadata about a digital signature, then // verify that signature first if (signername != null && keystore != null) { System.out.print("Verifying digital signature..."); System.out.flush(); // To verify the signature, we must process the files in exactly // the same order we did when we created the signature. We // guarantee this order by sorting the filenames. Collections.sort(files); // Create a Signature object to do signature verification with. // Initialize it with the signer's public key from the keystore Signature signature = Signature.getInstance(signatureAlgorithm); PublicKey publickey = keystore.getCertificate(signername).getPublicKey(); signature.initVerify(publickey); // Now loop through these files in their known sorted order For // each one, send the bytes of the filename and of the digest to // the signature object for use in computing the signature. It is // important that this be done in exactly the same order when // verifying the signature as it was done when creating the // signature. for(int i = 0; i < numfiles; i++) { String filename = (String) files.get(i); signature.update(filename.getBytes()); signature.update(hexDecode(manifest.getProperty(filename))); } // Now decode the signature read from the manifest file and pass // it to the verify() method of the signature object. If the // signature is not verified, print an error message and exit. if (!signature.verify(hexDecode(hexsignature))) { System.out.println("\nManifest has an invalid signature"); System.exit(0); } // Tell the user we're done with this lengthy computation System.out.println("verified."); } // Tell the user we're starting the next phase of verification System.out.print("Verifying file message digests"); System.out.flush(); // Get a MessageDigest object to compute digests MessageDigest md = MessageDigest.getInstance(digestAlgorithm); // Loop through all files for(int i = 0; i < numfiles; i++) { String filename = (String)files.get(i); // Look up the encoded digest from the manifest file String hexdigest = manifest.getProperty(filename); // Compute the digest for the file. byte[] digest; try { digest = getFileDigest(filename, md); } catch (IOException e) { System.out.println("\nSkipping " + filename + ": " + e); continue; } // Encode the computed digest and compare it to the encoded digest // from the manifest. If they are not equal, print an error // message. if (!hexdigest.equals(hexEncode(digest))) System.out.println("\nFile '" + filename + "' failed verification."); // Send one dot of output for each file we process. Since // computing message digests takes some time, this lets the user // know that the program is functioning and making progress System.out.print("."); System.out.flush(); } // And tell the user we're done with verification. System.out.println("done."); } /** * This convenience method is used by both create() and verify(). It * reads the contents of a named file and computes a message digest * for it, using the specified MessageDigest object. **/ public static byte[] getFileDigest(String filename, MessageDigest md) throws IOException { // Make sure there is nothing left behind in the MessageDigest md.reset(); // Create a stream to read from the file and compute the digest DigestInputStream in = new DigestInputStream(new FileInputStream(filename),md); // Read to the end of the file, discarding everything we read. // The DigestInputStream automatically passes all the bytes read to // the update() method of the MessageDigest while(in.read(buffer) != -1) /* do nothing */ ; // Finally, compute and return the digest value. return md.digest(); } /** This static buffer is used by getFileDigest() above */ public static byte[] buffer = new byte[4096]; /** This array is used to convert from bytes to hexadecimal numbers */ static final char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; /** * A convenience method to convert an array of bytes to a String. We do * this simply by converting each byte to two hexadecimal digits. * Something like Base 64 encoding is more compact, but harder to encode. **/ public static String hexEncode(byte[] bytes) { StringBuffer s = new StringBuffer(bytes.length * 2); for(int i = 0; i < bytes.length; i++) { byte b = bytes[i]; s.append(digits[(b& 0xf0) >> 4]); s.append(digits[b& 0x0f]); } return s.toString(); } /** * A convenience method to convert in the other direction, from a string * of hexadecimal digits to an array of bytes. **/ public static byte[] hexDecode(String s) throws IllegalArgumentException { try { int len = s.length(); byte[] r = new byte[len/2]; for(int i = 0; i < r.length; i++) { int digit1 = s.charAt(i*2), digit2 = s.charAt(i*2 + 1); if ((digit1 >= '0')&& (digit1 <= '9')) digit1 -= '0'; else if ((digit1 >= 'a')&& (digit1 <= 'f')) digit1 -= 'a' - 10; if ((digit2 >= '0')&& (digit2 <= '9')) digit2 -= '0'; else if ((digit2 >= 'a')&& (digit2 <= 'f')) digit2 -= 'a' - 10; r[i] = (byte)((digit1 << 4) + digit2); } return r; } catch (Exception e) { throw new IllegalArgumentException("hexDecode(): invalid input"); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -