001: /**
002: * LibreSource
003: * Copyright (C) 2004-2008 Artenum SARL / INRIA
004: * http://www.libresource.org - contact@artenum.com
005: *
006: * This file is part of the LibreSource software,
007: * which can be used and distributed under license conditions.
008: * The license conditions are provided in the LICENSE.TXT file
009: * at the root path of the packaging that enclose this file.
010: * More information can be found at
011: * - http://dev.libresource.org/home/license
012: *
013: * Initial authors :
014: *
015: * Guillaume Bort / INRIA
016: * Francois Charoy / Universite Nancy 2
017: * Julien Forest / Artenum
018: * Claude Godart / Universite Henry Poincare
019: * Florent Jouille / INRIA
020: * Sebastien Jourdain / INRIA / Artenum
021: * Yves Lerumeur / Artenum
022: * Pascal Molli / Universite Henry Poincare
023: * Gerald Oster / INRIA
024: * Mariarosa Penzi / Artenum
025: * Gerard Sookahet / Artenum
026: * Raphael Tani / INRIA
027: *
028: * Contributors :
029: *
030: * Stephane Bagnier / Artenum
031: * Amadou Dia / Artenum-IUP Blois
032: * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
033: */package org.libresource.security;
034:
035: /**
036: * Password is a class to implement password encryption as used on Unix systems.
037: * It is compatible with the crypt(3c) system function. This version is a based
038: * on the DES encryption algorithm in Andrew Tanenbaum's book "Computer
039: * Networks". It was rewritten in C and used in Perl release 4.035. This version
040: * was rewritten in Java by David Scott, Siemens Ltd., Australia.
041: *
042: * For further details on the methods in this class, refer to the Unix man pages
043: * for crypt(3c).
044: */
045: public class Password {
046: private static byte[] InitialTr = { 58, 50, 42, 34, 26, 18, 10, 2,
047: 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14,
048: 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17,
049: 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29,
050: 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 };
051: private static byte[] FinalTr = { 40, 8, 48, 16, 56, 24, 64, 32,
052: 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62,
053: 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20,
054: 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50,
055: 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 };
056: private static byte[] swap = { 33, 34, 35, 36, 37, 38, 39, 40, 41,
057: 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
058: 57, 58, 59, 60, 61, 62, 63, 64, 1, 2, 3, 4, 5, 6, 7, 8, 9,
059: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
060: 25, 26, 27, 28, 29, 30, 31, 32 };
061: private static byte[] KeyTr1 = { 57, 49, 41, 33, 25, 17, 9, 1, 58,
062: 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3,
063: 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46,
064: 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20,
065: 12, 4 };
066: private static byte[] KeyTr2 = { 14, 17, 11, 24, 1, 5, 3, 28, 15,
067: 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41,
068: 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56,
069: 34, 53, 46, 42, 50, 36, 29, 32 };
070: private static byte[] etr = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
071: 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18,
072: 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29,
073: 28, 29, 30, 31, 32, 1 };
074: private static byte[] ptr = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15,
075: 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13,
076: 30, 6, 22, 11, 4, 25 };
077: private static byte[][] s_boxes = {
078: { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0,
079: 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
080: 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5,
081: 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0,
082: 6, 13 },
083:
084: { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3,
085: 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
086: 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2,
087: 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5,
088: 14, 9 },
089:
090: { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13,
091: 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
092: 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14,
093: 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5,
094: 2, 12 },
095:
096: { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13,
097: 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
098: 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8,
099: 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7,
100: 2, 14 },
101:
102: { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14,
103: 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
104: 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0,
105: 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4,
106: 5, 3 },
107:
108: { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10,
109: 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
110: 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11,
111: 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0,
112: 8, 13 },
113:
114: { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13,
115: 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
116: 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9,
117: 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2,
118: 3, 12 },
119:
120: { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1,
121: 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
122: 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5,
123: 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5,
124: 6, 11 }, };
125: private static int[] rots = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2,
126: 2, 2, 2, 1 };
127: private static byte[] key = new byte[64];
128: private static byte[] EP = etr;
129:
130: /* *** Methods start here *** */
131: private static void transpose(byte[] data, byte[] t, int n) {
132: byte[] x = new byte[64];
133: System.arraycopy(data, 0, x, 0, x.length);
134:
135: while (n-- > 0) {
136: data[n] = x[t[n] - 1];
137: }
138: }
139:
140: private static void rotate(byte[] key) {
141: byte[] x = new byte[64];
142: System.arraycopy(key, 0, x, 0, x.length);
143:
144: for (int i = 0; i < 55; i++) {
145: x[i] = x[i + 1];
146: }
147:
148: x[27] = key[0];
149: x[55] = key[28];
150: System.arraycopy(x, 0, key, 0, key.length);
151: }
152:
153: private static void f(int i, byte[] key, byte[] a, byte[] x) {
154: byte[] e = new byte[64];
155: byte[] ikey = new byte[64];
156: byte[] y = new byte[64];
157:
158: System.arraycopy(a, 0, e, 0, e.length);
159: transpose(e, EP, 48);
160:
161: for (int j = rots[i]; j > 0; j--) {
162: rotate(key);
163: }
164:
165: System.arraycopy(key, 0, ikey, 0, ikey.length);
166: transpose(ikey, KeyTr2, 48);
167:
168: for (int j = 0; j < 48; j++) {
169: y[j] = (byte) (e[j] ^ ikey[j]);
170: }
171:
172: for (int j = 0; j < 8; j++) {
173: int k = j + 1;
174: int r = (32 * y[(6 * k) - 6]) + (8 * y[(6 * k) - 5])
175: + (4 * y[(6 * k) - 4]) + (2 * y[(6 * k) - 3])
176: + y[(6 * k) - 2] + (16 * y[(6 * k) - 1]);
177:
178: int xb = s_boxes[j][r];
179:
180: x[(4 * k) - 4] = (byte) ((xb >> 3) & 1);
181: x[(4 * k) - 3] = (byte) ((xb >> 2) & 1);
182: x[(4 * k) - 2] = (byte) ((xb >> 1) & 1);
183: x[(4 * k) - 1] = (byte) (xb & 1);
184: }
185:
186: transpose(x, ptr, 32);
187: }
188:
189: private static void definekey(byte[] k) {
190: System.arraycopy(k, 0, key, 0, key.length);
191: transpose(key, KeyTr1, 56);
192: }
193:
194: private static void encrypt(byte[] blck, int edflag) {
195: byte[] p = blck;
196:
197: transpose(p, InitialTr, 64);
198:
199: for (int i = 15; i >= 0; i--) {
200: int j = (edflag > 0) ? i : (15 - i);
201: byte[] b = new byte[64];
202: System.arraycopy(p, 0, b, 0, b.length);
203:
204: byte[] x = new byte[64];
205:
206: for (int k = 31; k >= 0; k--) {
207: p[k] = b[k + 32];
208: }
209:
210: f(j, key, p, x);
211:
212: for (int k = 31; k >= 0; k--) {
213: p[k + 32] = (byte) (b[k] ^ x[k]);
214: }
215: }
216:
217: transpose(p, swap, 64);
218: transpose(p, FinalTr, 64);
219: blck = p;
220: }
221:
222: /**
223: * Returns a String containing the encrypted passwd
224: *
225: * @param strpw
226: * A String containing the un-encrypted password
227: * @param strsalt
228: * A 2 character String, containing the salt to encrypt the
229: * password with.
230: * @returns String containing encrypted password.
231: */
232: public static String crypt(String strpw, String strsalt) {
233: char[] pw = strpw.toCharArray();
234: char[] salt = strsalt.toCharArray();
235: byte[] pwb = new byte[66];
236: char[] result = new char[13];
237: byte[] new_etr = new byte[etr.length];
238: int n = 0;
239: int m = 0;
240:
241: while ((m < pw.length) && (n < 64)) {
242: for (int j = 6; j >= 0; j--) {
243: pwb[n++] = (byte) ((pw[m] >> j) & 1);
244: }
245:
246: m++; // Increment pw
247: pwb[n++] = 0;
248: }
249:
250: while (n < 64) {
251: pwb[n++] = 0;
252: }
253:
254: definekey(pwb);
255:
256: for (n = 0; n < 66; n++) {
257: pwb[n] = 0;
258: }
259:
260: System.arraycopy(etr, 0, new_etr, 0, new_etr.length);
261: EP = new_etr;
262:
263: for (int i = 0; i < 2; i++) {
264: char c = salt[i];
265:
266: result[i] = c;
267:
268: if (c > 'Z') {
269: c -= (6 + 7 + '.'); // c was a lowercase letter
270: } else if (c > '9') {
271: c -= (7 + '.'); // c was a uppercase letter
272: } else {
273: c -= '.'; // c was a digit, '.' or '/'
274: } // now, 0 <= c <= 63
275:
276: for (int j = 0; j < 6; j++) {
277: if (((c >> j) & 1) == 1) {
278: byte t = (byte) ((6 * i) + j);
279: byte temp = new_etr[t];
280: new_etr[t] = new_etr[t + 24];
281: new_etr[t + 24] = temp;
282: }
283: }
284: }
285:
286: if (result[1] == 0) {
287: result[1] = result[0];
288: }
289:
290: for (int i = 0; i < 25; i++) {
291: encrypt(pwb, 0);
292: }
293:
294: EP = etr;
295:
296: m = 2;
297: n = 0;
298:
299: while (n < 66) {
300: int c = 0;
301:
302: for (int j = 6; j > 0; j--) {
303: c <<= 1;
304: c |= pwb[n++];
305: }
306:
307: c += '.'; // becomes >= '.'
308:
309: if (c > '9') {
310: c += 7; // not in [./0-9], becomes upper
311: }
312:
313: if (c > 'Z') {
314: c += 6; // not in [A-Z], becomes lower
315: }
316:
317: result[m++] = (char) c;
318: }
319:
320: return (new String(result));
321: }
322: }
|