KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > framework > tools > SecurityTools


1 /**
2  * Copyright (C) 2003-2005 Funambol
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package sync4j.framework.tools;
19
20 import java.security.MessageDigest JavaDoc;
21 import java.security.NoSuchAlgorithmException JavaDoc;
22 import java.security.SecureRandom JavaDoc;
23 import java.util.logging.Level JavaDoc;
24 import java.util.logging.Logger JavaDoc;
25
26 import javax.crypto.Mac;
27 import javax.crypto.spec.SecretKeySpec;
28
29 /**
30  * This class groups utility methods for security.
31  * <p>
32  *
33  * NOTE: when this class is first loaded, it creates and initializes a random
34  * generator that can be used to create random keys.
35  *
36  * @author Stefano Nichele @ Funambol
37  */

38 public class SecurityTools {
39
40     // ------------------------------------------------------------ Private data
41
private static SecureRandom JavaDoc random = null;
42
43     // ------------------------------------------------------------ Constructors
44

45     /** Creates a new instance of SecurityTools */
46     protected SecurityTools() {
47     }
48
49     // ---------------------------------------------------------- Public methods
50

51     /**
52      * Returns a new random password
53      *
54      * @return a new password
55      */

56     public static String JavaDoc getRandomPassword() {
57         byte[] nextNonce = new byte[16];
58         random.nextBytes(nextNonce);
59
60         int i;
61         for (int j=0; j<nextNonce.length; ++j) {
62             i = nextNonce[j] & 0x000000ff;
63             if ((i<32) || (i>128)) {
64                 nextNonce[j] = (byte)(32 + (i % 64));
65             }
66         }
67
68         return new String JavaDoc(Base64.encode(nextNonce));
69     }
70
71
72     /**
73      * Calculates the HMAC of the given parameters as specified in
74      * OMA-SyncML-DMSecurity-V1_1_2-20031209-A. Currently, only the MD5
75      * algorithm is supported.
76      *
77      * @param algorithm "MD5" for now
78      * @param msg the message on which calculate the mac
79      * @param username the username to be used in B64(H(username:password))
80      * @param password the password to be used in B64(H(username:password))
81      * @param nonce the nonce to be used
82      * @param log the <code>Logger</code> used to log the info
83      *
84      * @return the B64 encoding of the calculated MAC.
85      *
86      * @throws NoSuchAlgorithmException in the case the specified algorithm is
87      * not supported.
88      */

89     public static String JavaDoc getHMACValue( String JavaDoc algorithm,
90                                        byte[] msg ,
91                                        String JavaDoc username ,
92                                        String JavaDoc password ,
93                                        byte[] nonce ,
94                                        Logger JavaDoc log)
95         throws NoSuchAlgorithmException JavaDoc {
96
97         if (nonce == null) {
98             nonce = new byte[0];
99         }
100         if (log != null) {
101             if (log.isLoggable(Level.FINEST)) {
102                 log.finest("Calculates mac with: " +
103                            "\n\talgorith: " + algorithm +
104                            "\n\tmsg: " + msg +
105                            "\n\tusername: " + username +
106                            "\n\tpassword: " + password +
107                            "\n\tnonce: " + new String JavaDoc(Base64.encode(nonce))
108                     );
109             }
110         }
111
112         if (msg == null) {
113             return null;
114         }
115
116         String JavaDoc cred = username + ":" + password;
117
118         byte[] md5 = null;
119
120         md5 = MD5.digest(cred.getBytes()); // md5(user:password)
121

122         byte[] digest = Base64.encode(md5);
123
124         cred = new String JavaDoc(digest);
125
126         return getHMACValue(algorithm, msg, cred, nonce, log);
127     }
128
129
130     /**
131      * Calculates the HMAC of the given parameters as specified in
132      * OMA-SyncML-DMSecurity-V1_1_2-20031209-A. Currently, only the MD5
133      * algorithm is supported.
134      *
135      * @param algorithm "MD5" for now
136      * @param msg the message on which calculate the mac
137      * @param credential the credential string ( B64(H(username:password)) )
138      * @param nonce the nonce to be used
139      * @param log the <code>Logger</code> used to log the info
140      *
141      * @return the B64 encoding of the calculated MAC.
142      *
143      * @throws NoSuchAlgorithmException in the case the specified algorithm is
144      * not supported.
145      */

146     public static String JavaDoc getHMACValue(String JavaDoc algorithm ,
147                                       byte[] msg ,
148                                       String JavaDoc credential,
149                                       byte[] nonce ,
150                                       Logger JavaDoc log)
151     throws NoSuchAlgorithmException JavaDoc {
152         //
153
// Calculates mac
154
//
155

156         if (log != null) {
157             if (log.isLoggable(Level.FINEST)) {
158                 log.finest("Calculates mac with: " +
159                            "\n\talgorith: " + algorithm +
160                            "\n\tmsg: " + msg +
161                            "\n\tcredential: " + credential +
162                            "\n\tnonce: " + new String JavaDoc(Base64.encode(nonce))
163                     );
164             }
165         }
166
167         if (msg == null) {
168             return null;
169         }
170
171         MessageDigest JavaDoc md = null;
172
173         md = MessageDigest.getInstance(algorithm);
174
175         byte[] digestDataMessage = null;
176         byte[] b64DigestDataMessage = null;
177
178         byte[] digest = null;
179
180         // H(B64(H(username:password)):nonce:B64(H(message)))
181

182         // H(data)
183
digestDataMessage = md.digest(msg);
184
185         // B64(H(data))
186
b64DigestDataMessage = Base64.encode(digestDataMessage);
187
188         md.reset();
189
190         byte[] credentialBytes = credential.getBytes();
191
192         //
193
// Creates a unique buffer containing the bytes to digest
194
// B64(H(username:pw)):nonce:B64(H(trigger))
195
//
196
byte[] buf = new byte[credentialBytes.length + 2 + nonce.length + b64DigestDataMessage.length];
197
198         System.arraycopy(credentialBytes, 0, buf, 0, credentialBytes.length);
199         buf[credentialBytes.length] = (byte)':';
200         System.arraycopy(nonce, 0, buf, credentialBytes.length+1, nonce.length);
201         buf[credentialBytes.length + nonce.length + 1] = (byte)':';
202         System.arraycopy(b64DigestDataMessage, 0, buf, credentialBytes.length + nonce.length + 2, b64DigestDataMessage.length);
203
204         digest = md.digest(buf);
205
206         String JavaDoc mac = new String JavaDoc(Base64.encode(digest));
207         if (log != null) {
208             if (log.isLoggable(Level.FINEST)) {
209                 log.finest("HMAC: " + mac);
210             }
211         }
212         return mac;
213     }
214
215
216     /**
217      * Compute digest using HMAC-Sha1 keyed-hashing algorithm; see RFC 2104
218      * @param bKey the key
219      * @param message the message
220      * @throws GeneralSecurityException
221      * @return byte[] the mac
222      */

223     public static byte[] computeHmacSha1(byte[] bKey, byte[] message)
224         throws java.security.GeneralSecurityException JavaDoc {
225
226         String JavaDoc algorithm = "HmacSha1";
227         byte[] digest = null;
228
229         // Generate a key for the HMAC-MD5 keyed-hashing algorithm; see RFC 2104
230
SecretKeySpec key = new SecretKeySpec(bKey, algorithm);
231
232         // Create a MAC object using HMAC-MD5 and initialize with key
233
Mac mac = Mac.getInstance(algorithm);
234         mac.init(key);
235
236         digest = mac.doFinal(message);
237
238         return digest;
239     }
240
241
242     // ------------------------------------------------------------- Static code
243

244     static {
245         try {
246         random = SecureRandom.getInstance("SHA1PRNG");
247         } catch(Exception JavaDoc e) {
248             e.printStackTrace();
249         }
250     }
251 }
Popular Tags