001: /* Copyright (c) 2001-2004, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb.lib;
032:
033: import java.io.UnsupportedEncodingException;
034: import java.security.MessageDigest;
035: import java.security.NoSuchAlgorithmException;
036:
037: // boucherb@users 20030705 - patch 1.7.2 - renamed methods to allow sp/sf calls
038: // under HSQLDB's current inability to resolve method name overloads.
039:
040: /**
041: * Provides a static utility interface to an MD5 digest algorithm
042: * obtained through the java.security.MessageDigest spi. <p>
043: *
044: * Database end-users may wish to access the services of this class
045: * to provide, for instance, application user lookup tables with
046: * one-way password encryption. For example: <p>
047: *
048: * <pre>
049: * -- DDL
050: * CREATE TABLE USERS(UID INTEGER IDENTITY, UNAME VARCHAR, UPASS VARCHAR, UNIQUE(UNAME))
051: * CREATE ALIAS MD5 FOR "org.hsqldb.lib.MD5.encodeString"
052: *
053: * -- DML & DQL
054: * INSERT INTO USERS(UNAME, UPASS) VALUES('joe', MD5('passwd'))
055: * UPDATE USERS SET UPASS = MD5('newpasswd') WHERE UNAME = 'joe' AND UPASS = MD5('oldpasswd')
056: * SELECT UID FROM USERS WHERE UNAME = 'joe' AND UPASS = MD5('logonpasswd')
057: * </pre>
058: *
059: * <b>NOTE:</b> <p>
060: *
061: * Although it is possible that a particular JVM / application installation may
062: * encounter NoSuchAlgorithmException when attempting to get a jce MD5 message
063: * digest generator, the likelyhood is very small for almost all JDK/JRE 1.1
064: * and later JVM implementations, as the Sun java.security package has come,
065: * by default, with a jce MD5 message digest generator since JDK 1.1 was
066: * released. The HSLQLDB project could have provided an MD5 implementation to
067: * guarantee presence, but this class is much more lightweight and still allows
068: * clients to install / use custom implementations through the
069: * java.security.MessageDigest spi, for instance if there is no service
070: * provided by default under the target JVM of choice or if a client has
071: * developed / provides, say, a faster MD5 message digest implementation.
072: * In short, this class is a convenience that allows HSQLDB SQL Function and
073: * Stored Procedure style access to any underlying MD5 message digest algorithm
074: * obtained via the java.security.MessageDigest spi
075: *
076: * @author boucherb@users.sourceforge.net
077: * @version 1.7.2
078: * @since 1.7.2
079: */
080: public final class MD5 {
081:
082: /**
083: * The jce MD5 message digest generator.
084: */
085: private static MessageDigest md5;
086:
087: /**
088: * Retrieves a hexidecimal character sequence representing the MD5
089: * digest of the specified character sequence, using the specified
090: * encoding to first convert the character sequence into a byte sequence.
091: * If the specified encoding is null, then ISO-8859-1 is assumed
092: *
093: * @param string the string to encode.
094: * @param encoding the encoding used to convert the string into the
095: * byte sequence to submit for MD5 digest
096: * @return a hexidecimal character sequence representing the MD5
097: * digest of the specified string
098: * @throws HsqlUnsupportedOperationException if an MD5 digest
099: * algorithm is not available through the
100: * java.security.MessageDigest spi or the requested
101: * encoding is not available
102: */
103: public static final String encodeString(String string,
104: String encoding) throws RuntimeException {
105: return StringConverter
106: .byteToHex(digestString(string, encoding));
107: }
108:
109: /**
110: * Retrieves a byte sequence representing the MD5 digest of the
111: * specified character sequence, using the specified encoding to
112: * first convert the character sequence into a byte sequence.
113: * If the specified encoding is null, then ISO-8859-1 is
114: * assumed.
115: *
116: * @param string the string to digest.
117: * @param encoding the character encoding.
118: * @return the digest as an array of 16 bytes.
119: * @throws HsqlUnsupportedOperationException if an MD5 digest
120: * algorithm is not available through the
121: * java.security.MessageDigest spi or the requested
122: * encoding is not available
123: */
124: public static byte[] digestString(String string, String encoding)
125: throws RuntimeException {
126:
127: byte[] data;
128:
129: if (encoding == null) {
130: encoding = "ISO-8859-1";
131: }
132:
133: try {
134: data = string.getBytes(encoding);
135: } catch (UnsupportedEncodingException x) {
136: throw new RuntimeException(x.toString());
137: }
138:
139: return digestBytes(data);
140: }
141:
142: /**
143: * Retrieves a byte sequence representing the MD5 digest of the
144: * specified byte sequence.
145: *
146: * @param data the data to digest.
147: * @return the MD5 digest as an array of 16 bytes.
148: * @throws HsqlUnsupportedOperationException if an MD5 digest
149: * algorithm is not available through the
150: * java.security.MessageDigest spi
151: */
152: public static final byte[] digestBytes(byte[] data)
153: throws RuntimeException {
154:
155: synchronized (MD5.class) {
156: if (md5 == null) {
157: try {
158: md5 = MessageDigest.getInstance("MD5");
159: } catch (NoSuchAlgorithmException e) {
160: throw new RuntimeException(e.toString());
161: }
162: }
163:
164: return md5.digest(data);
165: }
166: }
167: }
|