001: /*
002:
003: Copyright 2004, Martian Software, Inc.
004:
005: Licensed under the Apache License, Version 2.0 (the "License");
006: you may not use this file except in compliance with the License.
007: You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016:
017: */
018:
019: package com.martiansoftware.nailgun.examples;
020:
021: import java.security.MessageDigest;
022: import java.security.Provider;
023: import java.security.Security;
024: import java.util.Iterator;
025: import java.util.Set;
026:
027: import com.martiansoftware.nailgun.NGContext;
028:
029: /**
030: * Hashes the client's stdin to the client's stdout in the form of
031: * a hexadecimal string. Command line requires one parameter: either the name
032: * of the algorithm to use (e.g., "MD5"), or "?" to request a list of
033: * available algorithms.
034: *
035: * @author <a href="http://www.martiansoftware.com/contact.html">Marty Lamb</a>
036: */
037: public class Hash {
038:
039: // used to turn byte[] to string
040: private static final char[] HEXCHARS = { '0', '1', '2', '3', '4',
041: '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
042:
043: /**
044: * Provides a list of algorithms for the specified service (which, for
045: * our purposes, is "MessageDigest".
046: *
047: * This method was only very slightly adapted (to use a TreeSet) from
048: * the Java Almanac at http://javaalmanac.com/egs/java.security/ListServices.html
049: * @param serviceType The name of the service we're looking for. It's "MessageDigest"
050: */
051: private static Set getCryptoImpls(String serviceType) {
052: Set result = new java.util.TreeSet();
053:
054: // All all providers
055: Provider[] providers = Security.getProviders();
056: for (int i = 0; i < providers.length; i++) {
057: // Get services provided by each provider
058: Set keys = providers[i].keySet();
059: for (Iterator it = keys.iterator(); it.hasNext();) {
060: String key = (String) it.next();
061: key = key.split(" ")[0];
062:
063: if (key.startsWith(serviceType + ".")) {
064: result.add(key.substring(serviceType.length() + 1));
065: } else if (key.startsWith("Alg.Alias." + serviceType
066: + ".")) {
067: // This is an alias
068: result
069: .add(key
070: .substring(serviceType.length() + 11));
071: }
072: }
073: }
074: return (result);
075: }
076:
077: /**
078: * Hashes client stdin, displays hash result to client stdout.
079: * Requires one command line parameter, either the name of the hash
080: * algorithm to use (e.g., "MD5") or "?" to request a list of
081: * available algorithms. Any exceptions become the problem of the user.
082: */
083: public static void nailMain(NGContext context)
084: throws java.security.NoSuchAlgorithmException,
085: java.io.IOException {
086: String[] args = context.getArgs();
087:
088: if (args.length == 0) {
089: // display available algorithms
090: Set algs = getCryptoImpls("MessageDigest");
091: for (Iterator i = algs.iterator(); i.hasNext();) {
092: context.out.println(i.next());
093: }
094: } else {
095: // perform the actual hash. throw any exceptions back to the user.
096: MessageDigest md = MessageDigest.getInstance(args[0]);
097:
098: byte[] b = new byte[1024];
099: int bytesRead = context.in.read(b);
100: while (bytesRead != -1) {
101: md.update(b, 0, bytesRead);
102: bytesRead = System.in.read(b);
103: }
104: byte[] result = md.digest();
105:
106: // convert hash result to a string of hex characters and print it to the client.
107: StringBuffer buf = new StringBuffer();
108: for (int i = 0; i < result.length; ++i) {
109: buf.append(HEXCHARS[(result[i] >> 4) & 0x0f]);
110: buf.append(HEXCHARS[result[i] & 0x0f]);
111: }
112: context.out.println(buf);
113: }
114: }
115:
116: }
|