001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020 package org.apache.james.user.lib.util;
021
022 import javax.mail.MessagingException;
023 import javax.mail.internet.MimeUtility;
024
025 import java.io.ByteArrayOutputStream;
026 import java.io.FileInputStream;
027 import java.io.FileOutputStream;
028 import java.io.IOException;
029 import java.io.OutputStream;
030 import java.security.MessageDigest;
031 import java.security.NoSuchAlgorithmException;
032 import java.util.Locale;
033
034 /**
035 * Computes and verifies digests of files and strings
036 */
037 public class DigestUtil {
038
039 /**
040 * Command line interface. Use -help for arguments.
041 *
042 * @param args
043 * the arguments passed in on the command line
044 */
045 public static void main(String[] args) {
046
047 String alg = "SHA";
048 boolean file = false;
049
050 if (args.length == 0 || args.length > 4) {
051 printUsage();
052 return;
053 }
054
055 for (int i = 0; i < args.length; i++) {
056 String currArg = args[i].toLowerCase(Locale.US);
057 if (currArg.equals("-help") || currArg.equals("-usage")) {
058 printUsage();
059 return;
060 }
061 if (currArg.equals("-alg")) {
062 alg = args[i + 1];
063 }
064 if (currArg.equals("-file")) {
065 file = true;
066 }
067 }
068
069 if (file) {
070 digestFile(args[args.length - 1], alg);
071 return;
072 } else {
073 try {
074 String hash = digestString(args[args.length - 1], alg);
075 System.out.println("Hash is: " + hash);
076 return;
077 } catch (NoSuchAlgorithmException nsae) {
078 System.out.println("No such algorithm available");
079 }
080 }
081 }
082
083 /**
084 * Print the command line usage string.
085 */
086 public static void printUsage() {
087 System.out.println("Usage: " + "java org.apache.james.security.DigestUtil" + " [-alg algorithm]" + " [-file] filename|string");
088 }
089
090 /**
091 * Calculate digest of given file with given algorithm. Writes digest to
092 * file named filename.algorithm .
093 *
094 * @param filename
095 * the String name of the file to be hashed
096 * @param algorithm
097 * the algorithm to be used to compute the digest
098 */
099 public static void digestFile(String filename, String algorithm) {
100 byte[] b = new byte[65536];
101 int count = 0;
102 int read = 0;
103 FileInputStream fis = null;
104 FileOutputStream fos = null;
105 try {
106 MessageDigest md = MessageDigest.getInstance(algorithm);
107 fis = new FileInputStream(filename);
108 while (fis.available() > 0) {
109 read = fis.read(b);
110 md.update(b, 0, read);
111 count += read;
112 }
113 byte[] digest = md.digest();
114 StringBuffer fileNameBuffer = new StringBuffer(128).append(filename).append(".").append(algorithm);
115 fos = new FileOutputStream(fileNameBuffer.toString());
116 OutputStream encodedStream = MimeUtility.encode(fos, "base64");
117 encodedStream.write(digest);
118 fos.flush();
119 } catch (Exception e) {
120 System.out.println("Error computing Digest: " + e);
121 } finally {
122 try {
123 fis.close();
124 fos.close();
125 } catch (Exception ignored) {
126 }
127 }
128 }
129
130 /**
131 * Calculate digest of given String using given algorithm. Encode digest in
132 * MIME-like base64.
133 *
134 * @param pass
135 * the String to be hashed
136 * @param algorithm
137 * the algorithm to be used
138 * @return String Base-64 encoding of digest
139 *
140 * @throws NoSuchAlgorithmException
141 * if the algorithm passed in cannot be found
142 */
143 public static String digestString(String pass, String algorithm) throws NoSuchAlgorithmException {
144
145 MessageDigest md;
146 ByteArrayOutputStream bos;
147
148 try {
149 md = MessageDigest.getInstance(algorithm);
150 byte[] digest = md.digest(pass.getBytes("iso-8859-1"));
151 bos = new ByteArrayOutputStream();
152 OutputStream encodedStream = MimeUtility.encode(bos, "base64");
153 encodedStream.write(digest);
154 return bos.toString("iso-8859-1");
155 } catch (IOException ioe) {
156 throw new RuntimeException("Fatal error: " + ioe);
157 } catch (MessagingException me) {
158 throw new RuntimeException("Fatal error: " + me);
159 }
160 }
161
162 /**
163 * Private constructor to prevent instantiation of the class
164 */
165 private DigestUtil() {
166 }
167 }