1 /*****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 ****************************************************************/
19
20 package org.apache.james.security;
21
22 import javax.mail.MessagingException;
23 import javax.mail.internet.MimeUtility;
24
25 import java.io.ByteArrayOutputStream;
26 import java.io.FileInputStream;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.security.MessageDigest;
31 import java.security.NoSuchAlgorithmException;
32 import java.util.Locale;
33
34
35 /***
36 * Computes and verifies digests of files and strings
37 *
38 *
39 * @version $Revision: 494012 $
40 */
41 public class DigestUtil {
42
43 /***
44 * Command line interface. Use -help for arguments.
45 *
46 * @param args the arguments passed in on the command line
47 */
48 public static void main(String[] args) {
49
50 String alg = "SHA";
51 boolean file = false;
52
53 if (args.length == 0 || args.length > 4) {
54 printUsage();
55 return;
56 }
57
58 for (int i = 0; i < args.length; i++) {
59 String currArg = args[i].toLowerCase(Locale.US);
60 if (currArg.equals("-help")
61 || currArg.equals("-usage")) {
62 printUsage();
63 return;
64 }
65 if (currArg.equals("-alg")) {
66 alg = args[i+1];
67 }
68 if (currArg.equals("-file")) {
69 file = true;
70 }
71 }
72
73 if (file) {
74 digestFile(args[args.length - 1], alg);
75 return ;
76 } else {
77 try {
78 String hash = digestString(args[args.length - 1], alg);
79 System.out.println("Hash is: " + hash);
80 return;
81 } catch (NoSuchAlgorithmException nsae) {
82 System.out.println("No such algorithm available");
83 }
84 }
85 }
86
87 /***
88 * Print the command line usage string.
89 */
90 public static void printUsage() {
91 System.out.println("Usage: "
92 + "java org.apache.james.security.DigestUtil"
93 + " [-alg algorithm]"
94 + " [-file] filename|string");
95 }
96
97 /***
98 * Calculate digest of given file with given algorithm.
99 * Writes digest to file named filename.algorithm .
100 *
101 * @param filename the String name of the file to be hashed
102 * @param algorithm the algorithm to be used to compute the digest
103 */
104 public static void digestFile(String filename, String algorithm) {
105 byte[] b = new byte[65536];
106 int count = 0;
107 int read = 0;
108 FileInputStream fis = null;
109 FileOutputStream fos = null;
110 try {
111 MessageDigest md = MessageDigest.getInstance(algorithm);
112 fis = new FileInputStream(filename);
113 while (fis.available() > 0) {
114 read = fis.read(b);
115 md.update(b, 0, read);
116 count += read;
117 }
118 byte[] digest = md.digest();
119 StringBuffer fileNameBuffer =
120 new StringBuffer(128)
121 .append(filename)
122 .append(".")
123 .append(algorithm);
124 fos = new FileOutputStream(fileNameBuffer.toString());
125 OutputStream encodedStream = MimeUtility.encode(fos, "base64");
126 encodedStream.write(digest);
127 fos.flush();
128 } catch (Exception e) {
129 System.out.println("Error computing Digest: " + e);
130 } finally {
131 try {
132 fis.close();
133 fos.close();
134 } catch (Exception ignored) {}
135 }
136 }
137
138 /***
139 * Calculate digest of given String using given algorithm.
140 * Encode digest in MIME-like base64.
141 *
142 * @param pass the String to be hashed
143 * @param algorithm the algorithm to be used
144 * @return String Base-64 encoding of digest
145 *
146 * @throws NoSuchAlgorithmException if the algorithm passed in cannot be found
147 */
148 public static String digestString(String pass, String algorithm )
149 throws NoSuchAlgorithmException {
150
151 MessageDigest md;
152 ByteArrayOutputStream bos;
153
154 try {
155 md = MessageDigest.getInstance(algorithm);
156 byte[] digest = md.digest(pass.getBytes("iso-8859-1"));
157 bos = new ByteArrayOutputStream();
158 OutputStream encodedStream = MimeUtility.encode(bos, "base64");
159 encodedStream.write(digest);
160 return bos.toString("iso-8859-1");
161 } catch (IOException ioe) {
162 throw new RuntimeException("Fatal error: " + ioe);
163 } catch (MessagingException me) {
164 throw new RuntimeException("Fatal error: " + me);
165 }
166 }
167
168 /***
169 * Private constructor to prevent instantiation of the class
170 */
171 private DigestUtil() {}
172 }