KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > security > util > SSHA


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 package com.sun.enterprise.security.util;
25
26 import java.lang.*;
27 import java.io.*;
28 import java.util.*;
29 import java.security.*;
30 import java.security.spec.*;
31
32 import com.sun.enterprise.util.i18n.StringManager;
33
34 import sun.misc.BASE64Decoder;
35 import sun.misc.BASE64Encoder;
36
37
38 /**
39  * Util class for salted SHA processing.
40  *
41  * <P>Salted SHA (aka SSHA) is computed as follows:
42  * <br> result = {SSHA}BASE64(SHA(password,salt),salt)
43  *
44  * <P>Methods are also provided to return partial results, such as
45  * SHA( password , salt) without Base64 encoding.
46  *
47  */

48 public class SSHA
49 {
50     private static final String JavaDoc SSHA_TAG = "{SSHA}";
51     private static StringManager sm =
52         StringManager.getManager("com.sun.enterprise.security.util");
53     private static MessageDigest md = null;
54
55     
56     /**
57      * Compute a salted SHA hash.
58      *
59      * @param salt Salt bytes.
60      * @param password Password bytes.
61      * @return Byte array of length 20 bytes containing hash result.
62      * @throws IASSecurityExeption Thrown if there is an error.
63      *
64      */

65     public static byte[] compute(byte[] salt, byte[] password)
66         throws IASSecurityException
67     {
68         byte[] buff = new byte[password.length + salt.length];
69         System.arraycopy(password, 0, buff, 0, password.length);
70         System.arraycopy(salt, 0, buff, password.length, salt.length);
71
72         byte[] hash = null;
73
74         synchronized (SSHA.class) {
75             
76             if (md == null) {
77                 try {
78                     md = MessageDigest.getInstance("SHA");
79                 } catch (Exception JavaDoc e) {
80                     throw new IASSecurityException(e);
81                 }
82             }
83
84             assert (md != null);
85             md.reset();
86             hash = md.digest(buff);
87         }
88
89         assert (hash.length==20); // SHA output is 160 bits
90

91         return hash;
92     }
93
94
95     /**
96      * Compute a salted SHA hash.
97      *
98      * <P>Salt bytes are obtained using SecureRandom.
99      *
100      * @param saltBytes Number of bytes of random salt value to generate.
101      * @param password Password bytes.
102      * @return Byte array of length 20 bytes containing hash result.
103      * @throws IASSecurityExeption Thrown if there is an error.
104      *
105      */

106     public static byte[] compute(int saltBytes, byte[] password)
107         throws IASSecurityException
108     {
109         SecureRandom rng=new SecureRandom();
110         byte[] salt=new byte[saltBytes];
111         rng.nextBytes(salt);
112
113         return compute(salt, password);
114     }
115
116     
117     /**
118      * Perform encoding of salt and computed hash.
119      *
120      * @param salt Salt bytes.
121      * @param hash Result of prior compute() operation.
122      * @return String Encoded string, as described in class documentation.
123      *
124      */

125     public static String JavaDoc encode(byte[] salt, byte[] hash)
126     {
127         assert (hash.length==20);
128         byte[] res = new byte[20+salt.length];
129         System.arraycopy(hash, 0, res, 0, 20);
130         System.arraycopy(salt, 0, res, 20, salt.length);
131
132         BASE64Encoder encoder = new BASE64Encoder();
133         String JavaDoc encoded = encoder.encode(res);
134
135         String JavaDoc out = SSHA_TAG + encoded;
136         return out;
137     }
138
139
140     /**
141      * Compute a salted SHA hash and return the encoded result. This is
142      * a convenience method combining compute() and encode().
143      *
144      * @param salt Salt bytes.
145      * @param password Password bytes.
146      * @return String Encoded string, as described in class documentation.
147      * @throws IASSecurityExeption Thrown if there is an error.
148      *
149      */

150     public static String JavaDoc computeAndEncode(byte[] salt, byte[] password)
151         throws IASSecurityException
152     {
153         byte[] hash = compute(salt, password);
154         return encode(salt, hash);
155     }
156
157
158     /**
159      * Compute a salted SHA hash and return the encoded result. This is
160      * a convenience method combining compute() and encode().
161      *
162      * @param saltBytes Number of bytes of random salt value to generate.
163      * @param password Password bytes.
164      * @return String Encoded string, as described in class documentation.
165      * @throws IASSecurityExeption Thrown if there is an error.
166      *
167      */

168     public static String JavaDoc computeAndEncode(int saltBytes, byte[] password)
169         throws IASSecurityException
170     {
171         SecureRandom rng=new SecureRandom();
172         byte[] salt=new byte[saltBytes];
173         rng.nextBytes(salt);
174
175         byte[] hash = compute(salt, password);
176         return encode(salt, hash);
177     }
178
179
180     /**
181      * Verifies a password.
182      *
183      * <P>The given password is verified against the provided encoded SSHA
184      * result string.
185      *
186      * @param encoded Encoded SSHA value (e.g. output of computeAndEncode())
187      * @param password Password bytes of the password to verify.
188      * @returns True if given password matches encoded SSHA.
189      * @throws IASSecurityExeption Thrown if there is an error.
190      *
191      */

192     public static boolean verify(String JavaDoc encoded, byte[] password)
193         throws IASSecurityException
194     {
195         byte[] hash = new byte[20];
196         byte[] salt = decode(encoded, hash);
197         return verify(salt, hash, password);
198     }
199
200
201     /**
202      * Verifies a password.
203      *
204      * <P>The given password is verified against the provided salt and hash
205      * buffers.
206      *
207      * @param salt Salt bytes used in the hash result.
208      * @param hash Hash result to compare against.
209      * @param password Password bytes of the password to verify.
210      * @returns True if given password matches encoded SSHA.
211      * @throws IASSecurityExeption Thrown if there is an error.
212      *
213      */

214     public static boolean verify(byte[] salt, byte[] hash, byte[] password)
215         throws IASSecurityException
216     {
217         byte[] newHash = compute(salt, password);
218         return Arrays.equals(hash, newHash);
219     }
220
221
222     /**
223      * Decodes an encoded SSHA string.
224      *
225      * @param encoded Encoded SSHA value (e.g. output of computeAndEncode())
226      * @param hashResult A byte array which must contain 20 elements. Upon
227      * succesful return from method, it will be filled by the hash
228      * value decoded from the given SSHA string. Existing values are
229      * not used and will be overwritten.
230      * @returns Byte array containing the salt obtained from the encoded SSHA
231      * string.
232      * @throws IASSecurityExeption Thrown if there is an error.
233      *
234      */

235     public static byte[] decode(String JavaDoc encoded, byte[] hashResult)
236         throws IASSecurityException
237     {
238         assert (hashResult.length==20);
239         if (!encoded.startsWith(SSHA_TAG)) {
240             String JavaDoc msg = sm.getString("ssha.badformat", encoded);
241             throw new IASSecurityException(msg);
242         }
243
244         String JavaDoc ssha = encoded.substring(SSHA_TAG.length());
245         
246         BASE64Decoder decoder = new BASE64Decoder();
247         byte[] result = null;
248       
249         try {
250             result = decoder.decodeBuffer(ssha);
251         } catch (IOException e) {
252             throw new IASSecurityException(e);
253         }
254         assert (result.length > 20);
255         
256         byte[] salt = new byte[result.length - 20];
257
258         System.arraycopy(result, 0, hashResult, 0, 20);
259         System.arraycopy(result, 20, salt, 0, result.length-20);
260
261         return salt;
262     }
263
264
265
266
267 }
268
Popular Tags