<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://www.jexp.ru/index.php?action=history&amp;feed=atom&amp;title=Java%2FDevelopment_Class%2FManifest</id>
		<title>Java/Development Class/Manifest - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://www.jexp.ru/index.php?action=history&amp;feed=atom&amp;title=Java%2FDevelopment_Class%2FManifest"/>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java/Development_Class/Manifest&amp;action=history"/>
		<updated>2026-04-19T01:51:14Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://www.jexp.ru/index.php?title=Java/Development_Class/Manifest&amp;diff=8471&amp;oldid=prev</id>
		<title>Admin: 1 версия</title>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java/Development_Class/Manifest&amp;diff=8471&amp;oldid=prev"/>
				<updated>2010-06-01T07:07:14Z</updated>
		
		<summary type="html">&lt;p&gt;1 версия&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr style=&quot;vertical-align: top;&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: white; color:black; text-align: center;&quot;&gt;Версия 07:07, 1 июня 2010&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; style=&quot;text-align: center;&quot; lang=&quot;ru&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(нет различий)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Admin</name></author>	</entry>

	<entry>
		<id>http://www.jexp.ru/index.php?title=Java/Development_Class/Manifest&amp;diff=8470&amp;oldid=prev</id>
		<title> в 18:01, 31 мая 2010</title>
		<link rel="alternate" type="text/html" href="http://www.jexp.ru/index.php?title=Java/Development_Class/Manifest&amp;diff=8470&amp;oldid=prev"/>
				<updated>2010-05-31T18:01:46Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Manifest class  ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- start source code --&amp;gt;&lt;br /&gt;
   &lt;br /&gt;
    &amp;lt;source lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright (c) 2000 David Flanagan.  All rights reserved.&lt;br /&gt;
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.&lt;br /&gt;
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.&lt;br /&gt;
 * You may study, use, and modify it for any non-commercial purpose.&lt;br /&gt;
 * You may distribute it non-commercially as long as you retain this notice.&lt;br /&gt;
 * For a commercial use license, or to purchase the book (recommended),&lt;br /&gt;
 * visit http://www.davidflanagan.ru/javaexamples2.&lt;br /&gt;
 */&lt;br /&gt;
import java.io.BufferedInputStream;&lt;br /&gt;
import java.io.File;&lt;br /&gt;
import java.io.FileInputStream;&lt;br /&gt;
import java.io.FileOutputStream;&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
import java.io.InputStream;&lt;br /&gt;
import java.security.DigestInputStream;&lt;br /&gt;
import java.security.InvalidKeyException;&lt;br /&gt;
import java.security.KeyStore;&lt;br /&gt;
import java.security.KeyStoreException;&lt;br /&gt;
import java.security.MessageDigest;&lt;br /&gt;
import java.security.NoSuchAlgorithmException;&lt;br /&gt;
import java.security.PrivateKey;&lt;br /&gt;
import java.security.PublicKey;&lt;br /&gt;
import java.security.Signature;&lt;br /&gt;
import java.security.SignatureException;&lt;br /&gt;
import java.security.UnrecoverableKeyException;&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
import java.util.Collections;&lt;br /&gt;
import java.util.Enumeration;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
import java.util.Properties;&lt;br /&gt;
/**&lt;br /&gt;
 * This program creates a manifest file for the specified files, or verifies an&lt;br /&gt;
 * existing manifest file. By default the manifest file is named MANIFEST, but&lt;br /&gt;
 * the -m option can be used to override this. The -v option specifies that the&lt;br /&gt;
 * manifest should be verified. Verification is also the default option if no&lt;br /&gt;
 * files are specified.&lt;br /&gt;
 */&lt;br /&gt;
public class Manifest {&lt;br /&gt;
  public static void main(String[] args) throws Exception {&lt;br /&gt;
    // Set the default values of the command-line arguments&lt;br /&gt;
    boolean verify = false; // Verify manifest or create one?&lt;br /&gt;
    String manifestfile = &amp;quot;MANIFEST&amp;quot;; // Manifest file name&lt;br /&gt;
    String digestAlgorithm = &amp;quot;MD5&amp;quot;; // Algorithm for message digests&lt;br /&gt;
    String signername = null; // Signer. No sig. by default&lt;br /&gt;
    String signatureAlgorithm = &amp;quot;DSA&amp;quot;; // Algorithm for digital sig.&lt;br /&gt;
    String password = null; // Private keys are protected&lt;br /&gt;
    File keystoreFile = null; // Where are keys stored&lt;br /&gt;
    String keystoreType = null; // What kind of keystore&lt;br /&gt;
    String keystorePassword = null; // How to access keystore&lt;br /&gt;
    List filelist = new ArrayList(); // The files to digest&lt;br /&gt;
    // Parse the command-line arguments, overriding the defaults above&lt;br /&gt;
    for (int i = 0; i &amp;lt; args.length; i++) {&lt;br /&gt;
      if (args[i].equals(&amp;quot;-v&amp;quot;))&lt;br /&gt;
        verify = true;&lt;br /&gt;
      else if (args[i].equals(&amp;quot;-m&amp;quot;))&lt;br /&gt;
        manifestfile = args[++i];&lt;br /&gt;
      else if (args[i].equals(&amp;quot;-da&amp;quot;) &amp;amp;&amp;amp; !verify)&lt;br /&gt;
        digestAlgorithm = args[++i];&lt;br /&gt;
      else if (args[i].equals(&amp;quot;-s&amp;quot;) &amp;amp;&amp;amp; !verify)&lt;br /&gt;
        signername = args[++i];&lt;br /&gt;
      else if (args[i].equals(&amp;quot;-sa&amp;quot;) &amp;amp;&amp;amp; !verify)&lt;br /&gt;
        signatureAlgorithm = args[++i];&lt;br /&gt;
      else if (args[i].equals(&amp;quot;-p&amp;quot;))&lt;br /&gt;
        password = args[++i];&lt;br /&gt;
      else if (args[i].equals(&amp;quot;-keystore&amp;quot;))&lt;br /&gt;
        keystoreFile = new File(args[++i]);&lt;br /&gt;
      else if (args[i].equals(&amp;quot;-keystoreType&amp;quot;))&lt;br /&gt;
        keystoreType = args[++i];&lt;br /&gt;
      else if (args[i].equals(&amp;quot;-keystorePassword&amp;quot;))&lt;br /&gt;
        keystorePassword = args[++i];&lt;br /&gt;
      else if (!verify)&lt;br /&gt;
        filelist.add(args[i]);&lt;br /&gt;
      else&lt;br /&gt;
        throw new IllegalArgumentException(args[i]);&lt;br /&gt;
    }&lt;br /&gt;
    // If certain arguments weren&amp;quot;t supplied, get default values.&lt;br /&gt;
    if (keystoreFile == null) {&lt;br /&gt;
      File dir = new File(System.getProperty(&amp;quot;user.home&amp;quot;));&lt;br /&gt;
      keystoreFile = new File(dir, &amp;quot;.keystore&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    if (keystoreType == null)&lt;br /&gt;
      keystoreType = KeyStore.getDefaultType();&lt;br /&gt;
    if (keystorePassword == null)&lt;br /&gt;
      keystorePassword = password;&lt;br /&gt;
    if (!verify &amp;amp;&amp;amp; signername != null &amp;amp;&amp;amp; password == null) {&lt;br /&gt;
      System.out.println(&amp;quot;Use -p to specify a password.&amp;quot;);&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    // Get the keystore we&amp;quot;ll use for signing or verifying signatures&lt;br /&gt;
    // If no password was provided, then assume we won&amp;quot;t be dealing with&lt;br /&gt;
    // signatures, and skip the keystore.&lt;br /&gt;
    KeyStore keystore = null;&lt;br /&gt;
    if (keystorePassword != null) {&lt;br /&gt;
      keystore = KeyStore.getInstance(keystoreType);&lt;br /&gt;
      InputStream in = new BufferedInputStream(new FileInputStream(&lt;br /&gt;
          keystoreFile));&lt;br /&gt;
      keystore.load(in, keystorePassword.toCharArray());&lt;br /&gt;
    }&lt;br /&gt;
    // If -v was specified or no file were given, verify a manifest&lt;br /&gt;
    // Otherwise, create a new manifest for the specified files&lt;br /&gt;
    if (verify || (filelist.size() == 0))&lt;br /&gt;
      verify(manifestfile, keystore);&lt;br /&gt;
    else&lt;br /&gt;
      create(manifestfile, digestAlgorithm, signername,&lt;br /&gt;
          signatureAlgorithm, keystore, password, filelist);&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * This method creates a manifest file with the specified name, for the&lt;br /&gt;
   * specified vector of files, using the named message digest algorithm. If&lt;br /&gt;
   * signername is non-null, it adds a digital signature to the manifest,&lt;br /&gt;
   * using the named signature algorithm. This method can throw a bunch of&lt;br /&gt;
   * exceptions.&lt;br /&gt;
   */&lt;br /&gt;
  public static void create(String manifestfile, String digestAlgorithm,&lt;br /&gt;
      String signername, String signatureAlgorithm, KeyStore keystore,&lt;br /&gt;
      String password, List filelist) throws NoSuchAlgorithmException,&lt;br /&gt;
      InvalidKeyException, SignatureException, KeyStoreException,&lt;br /&gt;
      UnrecoverableKeyException, IOException {&lt;br /&gt;
    // For computing a signature, we have to process the files in a fixed,&lt;br /&gt;
    // repeatable order, so sort them alphabetically.&lt;br /&gt;
    Collections.sort(filelist);&lt;br /&gt;
    int numfiles = filelist.size();&lt;br /&gt;
    Properties manifest = new Properties(), metadata = new Properties();&lt;br /&gt;
    MessageDigest md = MessageDigest.getInstance(digestAlgorithm);&lt;br /&gt;
    Signature signature = null;&lt;br /&gt;
    byte[] digest;&lt;br /&gt;
    // If a signer name was specified, then prepare to sign the manifest&lt;br /&gt;
    if (signername != null) {&lt;br /&gt;
      // Get a Signature object&lt;br /&gt;
      signature = Signature.getInstance(signatureAlgorithm);&lt;br /&gt;
      // Look up the private key of the signer from the keystore&lt;br /&gt;
      PrivateKey key = (PrivateKey) keystore.getKey(signername, password&lt;br /&gt;
          .toCharArray());&lt;br /&gt;
      // No prepare to create a signature for the specified signer&lt;br /&gt;
      signature.initSign(key);&lt;br /&gt;
    }&lt;br /&gt;
    // Now, loop through the files, in a well-known alphabetical order&lt;br /&gt;
    System.out.print(&amp;quot;Computing message digests&amp;quot;);&lt;br /&gt;
    for (int i = 0; i &amp;lt; numfiles; i++) {&lt;br /&gt;
      String filename = (String) filelist.get(i);&lt;br /&gt;
      // Compute the digest for each, and skip files that don&amp;quot;t exist.&lt;br /&gt;
      try {&lt;br /&gt;
        digest = getFileDigest(filename, md);&lt;br /&gt;
      } catch (IOException e) {&lt;br /&gt;
        System.err.println(&amp;quot;\nSkipping &amp;quot; + filename + &amp;quot;: &amp;quot; + e);&lt;br /&gt;
        continue;&lt;br /&gt;
      }&lt;br /&gt;
      // If we&amp;quot;re computing a signature, use the bytes of the filename&lt;br /&gt;
      // and of the digest as part of the data to sign.&lt;br /&gt;
      if (signature != null) {&lt;br /&gt;
        signature.update(filename.getBytes());&lt;br /&gt;
        signature.update(digest);&lt;br /&gt;
      }&lt;br /&gt;
      // Store the filename and the encoded digest bytes in the manifest&lt;br /&gt;
      manifest.put(filename, hexEncode(digest));&lt;br /&gt;
      System.out.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
      System.out.flush();&lt;br /&gt;
    }&lt;br /&gt;
    // If a signer was specified, compute signature for the manifest&lt;br /&gt;
    byte[] signaturebytes = null;&lt;br /&gt;
    if (signature != null) {&lt;br /&gt;
      System.out.print(&amp;quot;done\nComputing digital signature...&amp;quot;);&lt;br /&gt;
      System.out.flush();&lt;br /&gt;
      // Compute the digital signature by encrypting a message digest of&lt;br /&gt;
      // all the bytes passed to the update() method using the private&lt;br /&gt;
      // key of the signer. This is a time consuming operation.&lt;br /&gt;
      signaturebytes = signature.sign();&lt;br /&gt;
    }&lt;br /&gt;
    // Tell the user what comes next&lt;br /&gt;
    System.out.print(&amp;quot;done\nWriting manifest...&amp;quot;);&lt;br /&gt;
    System.out.flush();&lt;br /&gt;
    // Store some metadata about this manifest, including the name of the&lt;br /&gt;
    // message digest algorithm it uses&lt;br /&gt;
    metadata.put(&amp;quot;__META.DIGESTALGORITHM&amp;quot;, digestAlgorithm);&lt;br /&gt;
    // If we&amp;quot;re signing the manifest, store some more metadata&lt;br /&gt;
    if (signername != null) {&lt;br /&gt;
      // Store the name of the signer&lt;br /&gt;
      metadata.put(&amp;quot;__META.SIGNER&amp;quot;, signername);&lt;br /&gt;
      // Store the name of the algorithm&lt;br /&gt;
      metadata.put(&amp;quot;__META.SIGNATUREALGORITHM&amp;quot;, signatureAlgorithm);&lt;br /&gt;
      // And generate the signature, encode it, and store it&lt;br /&gt;
      metadata.put(&amp;quot;__META.SIGNATURE&amp;quot;, hexEncode(signaturebytes));&lt;br /&gt;
    }&lt;br /&gt;
    // Now, save the manifest data and the metadata to the manifest file&lt;br /&gt;
    FileOutputStream f = new FileOutputStream(manifestfile);&lt;br /&gt;
    manifest.store(f, &amp;quot;Manifest message digests&amp;quot;);&lt;br /&gt;
    metadata.store(f, &amp;quot;Manifest metadata&amp;quot;);&lt;br /&gt;
    System.out.println(&amp;quot;done&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * This method verifies the digital signature of the named manifest file, if&lt;br /&gt;
   * it has one, and if that verification succeeds, it verifies the message&lt;br /&gt;
   * digest of each file in filelist that is also named in the manifest. This&lt;br /&gt;
   * method can throw a bunch of exceptions&lt;br /&gt;
   */&lt;br /&gt;
  public static void verify(String manifestfile, KeyStore keystore)&lt;br /&gt;
      throws NoSuchAlgorithmException, SignatureException,&lt;br /&gt;
      InvalidKeyException, KeyStoreException, IOException {&lt;br /&gt;
    Properties manifest = new Properties();&lt;br /&gt;
    manifest.load(new FileInputStream(manifestfile));&lt;br /&gt;
    String digestAlgorithm = manifest.getProperty(&amp;quot;__META.DIGESTALGORITHM&amp;quot;);&lt;br /&gt;
    String signername = manifest.getProperty(&amp;quot;__META.SIGNER&amp;quot;);&lt;br /&gt;
    String signatureAlgorithm = manifest&lt;br /&gt;
        .getProperty(&amp;quot;__META.SIGNATUREALGORITHM&amp;quot;);&lt;br /&gt;
    String hexsignature = manifest.getProperty(&amp;quot;__META.SIGNATURE&amp;quot;);&lt;br /&gt;
    // Get a list of filenames in the manifest.&lt;br /&gt;
    List files = new ArrayList();&lt;br /&gt;
    Enumeration names = manifest.propertyNames();&lt;br /&gt;
    while (names.hasMoreElements()) {&lt;br /&gt;
      String s = (String) names.nextElement();&lt;br /&gt;
      if (!s.startsWith(&amp;quot;__META&amp;quot;))&lt;br /&gt;
        files.add(s);&lt;br /&gt;
    }&lt;br /&gt;
    int numfiles = files.size();&lt;br /&gt;
    // If we&amp;quot;ve got a signature but no keystore, warn the user&lt;br /&gt;
    if (signername != null &amp;amp;&amp;amp; keystore == null)&lt;br /&gt;
      System.out.println(&amp;quot;Can&amp;quot;t verify digital signature without &amp;quot;&lt;br /&gt;
          + &amp;quot;a keystore.&amp;quot;);&lt;br /&gt;
    // If the manifest contained metadata about a digital signature, then&lt;br /&gt;
    // verify that signature first&lt;br /&gt;
    if (signername != null &amp;amp;&amp;amp; keystore != null) {&lt;br /&gt;
      System.out.print(&amp;quot;Verifying digital signature...&amp;quot;);&lt;br /&gt;
      System.out.flush();&lt;br /&gt;
      // To verify the signature, we must process the files in exactly&lt;br /&gt;
      // the same order we did when we created the signature. We&lt;br /&gt;
      // guarantee this order by sorting the filenames.&lt;br /&gt;
      Collections.sort(files);&lt;br /&gt;
      // Create a Signature object to do signature verification with.&lt;br /&gt;
      // Initialize it with the signer&amp;quot;s public key from the keystore&lt;br /&gt;
      Signature signature = Signature.getInstance(signatureAlgorithm);&lt;br /&gt;
      PublicKey publickey = keystore.getCertificate(signername)&lt;br /&gt;
          .getPublicKey();&lt;br /&gt;
      signature.initVerify(publickey);&lt;br /&gt;
      // Now loop through these files in their known sorted order For&lt;br /&gt;
      // each one, send the bytes of the filename and of the digest to&lt;br /&gt;
      // the signature object for use in computing the signature. It is&lt;br /&gt;
      // important that this be done in exactly the same order when&lt;br /&gt;
      // verifying the signature as it was done when creating the&lt;br /&gt;
      // signature.&lt;br /&gt;
      for (int i = 0; i &amp;lt; numfiles; i++) {&lt;br /&gt;
        String filename = (String) files.get(i);&lt;br /&gt;
        signature.update(filename.getBytes());&lt;br /&gt;
        signature.update(hexDecode(manifest.getProperty(filename)));&lt;br /&gt;
      }&lt;br /&gt;
      // Now decode the signature read from the manifest file and pass&lt;br /&gt;
      // it to the verify() method of the signature object. If the&lt;br /&gt;
      // signature is not verified, print an error message and exit.&lt;br /&gt;
      if (!signature.verify(hexDecode(hexsignature))) {&lt;br /&gt;
        System.out.println(&amp;quot;\nManifest has an invalid signature&amp;quot;);&lt;br /&gt;
        System.exit(0);&lt;br /&gt;
      }&lt;br /&gt;
      // Tell the user we&amp;quot;re done with this lengthy computation&lt;br /&gt;
      System.out.println(&amp;quot;verified.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    // Tell the user we&amp;quot;re starting the next phase of verification&lt;br /&gt;
    System.out.print(&amp;quot;Verifying file message digests&amp;quot;);&lt;br /&gt;
    System.out.flush();&lt;br /&gt;
    // Get a MessageDigest object to compute digests&lt;br /&gt;
    MessageDigest md = MessageDigest.getInstance(digestAlgorithm);&lt;br /&gt;
    // Loop through all files&lt;br /&gt;
    for (int i = 0; i &amp;lt; numfiles; i++) {&lt;br /&gt;
      String filename = (String) files.get(i);&lt;br /&gt;
      // Look up the encoded digest from the manifest file&lt;br /&gt;
      String hexdigest = manifest.getProperty(filename);&lt;br /&gt;
      // Compute the digest for the file.&lt;br /&gt;
      byte[] digest;&lt;br /&gt;
      try {&lt;br /&gt;
        digest = getFileDigest(filename, md);&lt;br /&gt;
      } catch (IOException e) {&lt;br /&gt;
        System.out.println(&amp;quot;\nSkipping &amp;quot; + filename + &amp;quot;: &amp;quot; + e);&lt;br /&gt;
        continue;&lt;br /&gt;
      }&lt;br /&gt;
      // Encode the computed digest and compare it to the encoded digest&lt;br /&gt;
      // from the manifest. If they are not equal, print an error&lt;br /&gt;
      // message.&lt;br /&gt;
      if (!hexdigest.equals(hexEncode(digest)))&lt;br /&gt;
        System.out.println(&amp;quot;\nFile &amp;quot;&amp;quot; + filename&lt;br /&gt;
            + &amp;quot;&amp;quot; failed verification.&amp;quot;);&lt;br /&gt;
      // Send one dot of output for each file we process. Since&lt;br /&gt;
      // computing message digests takes some time, this lets the user&lt;br /&gt;
      // know that the program is functioning and making progress&lt;br /&gt;
      System.out.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
      System.out.flush();&lt;br /&gt;
    }&lt;br /&gt;
    // And tell the user we&amp;quot;re done with verification.&lt;br /&gt;
    System.out.println(&amp;quot;done.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * This convenience method is used by both create() and verify(). It reads&lt;br /&gt;
   * the contents of a named file and computes a message digest for it, using&lt;br /&gt;
   * the specified MessageDigest object.&lt;br /&gt;
   */&lt;br /&gt;
  public static byte[] getFileDigest(String filename, MessageDigest md)&lt;br /&gt;
      throws IOException {&lt;br /&gt;
    // Make sure there is nothing left behind in the MessageDigest&lt;br /&gt;
    md.reset();&lt;br /&gt;
    // Create a stream to read from the file and compute the digest&lt;br /&gt;
    DigestInputStream in = new DigestInputStream(new FileInputStream(&lt;br /&gt;
        filename), md);&lt;br /&gt;
    // Read to the end of the file, discarding everything we read.&lt;br /&gt;
    // The DigestInputStream automatically passes all the bytes read to&lt;br /&gt;
    // the update() method of the MessageDigest&lt;br /&gt;
    while (in.read(buffer) != -1)&lt;br /&gt;
      /* do nothing */;&lt;br /&gt;
    // Finally, compute and return the digest value.&lt;br /&gt;
    return md.digest();&lt;br /&gt;
  }&lt;br /&gt;
  /** This static buffer is used by getFileDigest() above */&lt;br /&gt;
  public static byte[] buffer = new byte[4096];&lt;br /&gt;
  /** This array is used to convert from bytes to hexadecimal numbers */&lt;br /&gt;
  static final char[] digits = { &amp;quot;0&amp;quot;, &amp;quot;1&amp;quot;, &amp;quot;2&amp;quot;, &amp;quot;3&amp;quot;, &amp;quot;4&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;6&amp;quot;, &amp;quot;7&amp;quot;, &amp;quot;8&amp;quot;,&lt;br /&gt;
      &amp;quot;9&amp;quot;, &amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;quot;d&amp;quot;, &amp;quot;e&amp;quot;, &amp;quot;f&amp;quot; };&lt;br /&gt;
  /**&lt;br /&gt;
   * A convenience method to convert an array of bytes to a String. We do this&lt;br /&gt;
   * simply by converting each byte to two hexadecimal digits. Something like&lt;br /&gt;
   * Base 64 encoding is more compact, but harder to encode.&lt;br /&gt;
   */&lt;br /&gt;
  public static String hexEncode(byte[] bytes) {&lt;br /&gt;
    StringBuffer s = new StringBuffer(bytes.length * 2);&lt;br /&gt;
    for (int i = 0; i &amp;lt; bytes.length; i++) {&lt;br /&gt;
      byte b = bytes[i];&lt;br /&gt;
      s.append(digits[(b &amp;amp; 0xf0) &amp;gt;&amp;gt; 4]);&lt;br /&gt;
      s.append(digits[b &amp;amp; 0x0f]);&lt;br /&gt;
    }&lt;br /&gt;
    return s.toString();&lt;br /&gt;
  }&lt;br /&gt;
  /**&lt;br /&gt;
   * A convenience method to convert in the other direction, from a string of&lt;br /&gt;
   * hexadecimal digits to an array of bytes.&lt;br /&gt;
   */&lt;br /&gt;
  public static byte[] hexDecode(String s) throws IllegalArgumentException {&lt;br /&gt;
    try {&lt;br /&gt;
      int len = s.length();&lt;br /&gt;
      byte[] r = new byte[len / 2];&lt;br /&gt;
      for (int i = 0; i &amp;lt; r.length; i++) {&lt;br /&gt;
        int digit1 = s.charAt(i * 2), digit2 = s.charAt(i * 2 + 1);&lt;br /&gt;
        if ((digit1 &amp;gt;= &amp;quot;0&amp;quot;) &amp;amp;&amp;amp; (digit1 &amp;lt;= &amp;quot;9&amp;quot;))&lt;br /&gt;
          digit1 -= &amp;quot;0&amp;quot;;&lt;br /&gt;
        else if ((digit1 &amp;gt;= &amp;quot;a&amp;quot;) &amp;amp;&amp;amp; (digit1 &amp;lt;= &amp;quot;f&amp;quot;))&lt;br /&gt;
          digit1 -= &amp;quot;a&amp;quot; - 10;&lt;br /&gt;
        if ((digit2 &amp;gt;= &amp;quot;0&amp;quot;) &amp;amp;&amp;amp; (digit2 &amp;lt;= &amp;quot;9&amp;quot;))&lt;br /&gt;
          digit2 -= &amp;quot;0&amp;quot;;&lt;br /&gt;
        else if ((digit2 &amp;gt;= &amp;quot;a&amp;quot;) &amp;amp;&amp;amp; (digit2 &amp;lt;= &amp;quot;f&amp;quot;))&lt;br /&gt;
          digit2 -= &amp;quot;a&amp;quot; - 10;&lt;br /&gt;
        r[i] = (byte) ((digit1 &amp;lt;&amp;lt; 4) + digit2);&lt;br /&gt;
      }&lt;br /&gt;
      return r;&lt;br /&gt;
    } catch (Exception e) {&lt;br /&gt;
      throw new IllegalArgumentException(&amp;quot;hexDecode(): invalid input&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
           &lt;br /&gt;
       &amp;lt;/source&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
   &lt;br /&gt;
  &amp;lt;!-- end source code --&amp;gt;&lt;/div&gt;</summary>
			</entry>

	</feed>