//$Header: /cvsroot-fuse/mec-as2/39/mendelson/util/Crypt.java,v 1.1 2012/04/18 14:10:41 heller Exp $ package de.mendelson.util; /** *Crypt is a class to implement password encryption as used *on Unix systems. It is compatible with the crypt(3c) system function. *This version is a based on the DES encryption algorithm in *Andrew Tanenbaum's book "Computer Networks". It was rewritten *in C and used in Perl release 4.035. This version was rewritten *in Java by David Scott, Siemens Ltd., Australia. * *For further details on the methods in this class, refer to the *Unix man pages for crypt(3c). */ public class Crypt{ private static byte[] InitialTr = { 58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4, 62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8, 57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3, 61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7 }; private static byte[] FinalTr = { 40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31, 38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29, 36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27, 34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25 }; private static byte[] swap = { 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32 }; private static byte[] KeyTr1 = { 57,49,41,33,25,17, 9, 1,58,50,42,34,26,18, 10, 2,59,51,43,35,27,19,11, 3,60,52,44,36, 63,55,47,39,31,23,15, 7,62,54,46,38,30,22, 14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4 }; private static byte[] KeyTr2 = { 14,17,11,24, 1, 5, 3,28,15, 6,21,10, 23,19,12, 4,26, 8,16, 7,27,20,13, 2, 41,52,31,37,47,55,30,40,51,45,33,48, 44,49,39,56,34,53,46,42,50,36,29,32 }; private static byte[] etr = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9,10,11,12,13,12,13,14,15,16,17, 16,17,18,19,20,21,20,21,22,23,24,25, 24,25,26,27,28,29,28,29,30,31,32, 1 }; private static byte[] ptr = { 16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10, 2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25 }; private static byte s_boxes[][] = { { 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13 }, { 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9 }, { 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12 }, { 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14 }, { 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3 }, { 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8, 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13 }, { 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6, 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12 }, { 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11 }, }; private static int rots[] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 }; private static byte[] key = new byte[64] ; private static byte[] EP = etr; /* *** Methods start here *** */ private static void transpose( byte[] data, byte[] t, int n ) { byte[] x = new byte[64] ; System.arraycopy( data, 0, x, 0, x.length ) ; while ( n-- > 0 ) { data[n] = x[t[n]-1] ; } } private static void rotate( byte[] key ) { byte[] x = new byte[64] ; System.arraycopy( key, 0, x, 0, x.length ) ; for ( int i = 0 ; i < 55 ; i++ ) { x[i] = x[i+1] ; } x[27] = key[0] ; x[55] = key[28] ; System.arraycopy( x, 0, key, 0, key.length ) ; } private static void f( int i, byte[] key, byte[] a, byte[] x ) { byte[]e = new byte[64] ; byte[]ikey = new byte[64] ; byte[]y = new byte[64] ; System.arraycopy( a, 0, e, 0, e.length ) ; transpose( e, EP, 48 ) ; for ( int j = rots[i] ; j > 0 ; j-- ) { rotate(key) ; } System.arraycopy( key, 0, ikey, 0, ikey.length ) ; transpose( ikey, KeyTr2, 48 ) ; for ( int j = 0 ; j < 48 ; j++ ) { y[j] = (byte)(e[j] ^ ikey[j]) ; } for ( int j = 0 ; j < 8 ; j++ ) { int k = j+1 ; int r = 32 * y[6*k - 6] + 8 * y[6*k - 5] + 4 * y[6*k - 4] + 2 * y[6*k - 3] + y[6*k - 2] + 16 * y[6*k - 1]; int xb = s_boxes[j][r] ; x[4*k - 4] = (byte)(( xb >> 3 ) & 1) ; x[4*k - 3] = (byte)(( xb >> 2 ) & 1) ; x[4*k - 2] = (byte)(( xb >> 1 ) & 1) ; x[4*k - 1] = (byte)( xb & 1 ); } transpose( x, ptr, 32 ) ; } private static void definekey( byte[] k ) { System.arraycopy( k, 0, key, 0, key.length ) ; transpose( key, KeyTr1, 56 ) ; } private static void encrypt( byte[] blck, int edflag ) { byte[] p = blck ; transpose( p, InitialTr, 64 ) ; for ( int i = 15 ; i >= 0 ; i-- ) { int j = edflag > 0 ? i : 15 - i ; byte[] b = new byte[64] ; System.arraycopy( p, 0, b, 0, b.length ) ; byte[] x = new byte[64] ; for ( int k = 31 ; k >= 0 ; k-- ) { p[k] = b[k+32] ; } f( j, key, p, x ) ; for ( int k = 31 ; k >= 0 ; k-- ) { p[k+32] = (byte)(b[k] ^ x[k]) ; } } transpose( p, swap, 64 ) ; transpose( p, FinalTr, 64 ) ; blck = p ; } /** *Returns a String containing the encrypted passwd * *@paramstrpwA String containing the un-encrypted password *@paramstrsaltA 2 character String, containing the salt to *encrypt the password with. *@returnsString containing encrypted password. */ public static String crypt( String strpw, String strsalt ) { char[] pw = strpw.toCharArray() ; char[] salt = strsalt.toCharArray() ; byte[] pwb = new byte[66] ; char[] result = new char[13] ; byte[] new_etr = new byte[etr.length] ; int n = 0 ; int m = 0 ; while ( m < pw.length && n < 64 ) { for ( int j = 6 ; j >= 0 ; j-- ) { pwb[n++] = (byte)(( pw[m] >> j ) & 1 ) ; } m++ ; // Increment pw pwb[n++] = 0 ; } while ( n < 64 ) { pwb[n++] = 0 ; } definekey( pwb ) ; for ( n = 0 ; n < 66 ; n++ ) { pwb[n] = 0 ; } System.arraycopy( etr, 0, new_etr, 0 , new_etr.length ) ; EP = new_etr ; for ( int i = 0 ; i < 2 ; i++ ) { char c = salt[i] ; result[i] = c ; if ( c > 'Z' ) { c -= 6 + 7 + '.' ;// c was a lowercase letter } else if ( c > '9' ) { c -= 7 + '.' ;// c was a uppercase letter } else { c -= '.' ;// c was a digit, '.' or '/' }// now, 0 <= c <= 63 for ( int j = 0 ; j < 6 ; j++ ) { if ((( c >> j ) & 1) == 1 ) { byte t= (byte)(6*i + j) ; byte temp= new_etr[t] ; new_etr[t]= new_etr[t+24] ; new_etr[t+24]= temp ; } } } if ( result[1] == 0 ) { result[1] = result[0] ; } for ( int i = 0 ; i < 25 ; i++ ) { encrypt( pwb, 0 ) ; } EP = etr ; m = 2 ; n = 0 ; while ( n < 66 ) { int c = 0 ; for ( int j = 6 ; j > 0 ; j-- ) { c <<= 1 ; c |= pwb[n++] ; } c += '.' ;// becomes >= '.' if ( c > '9' ) { c += 7 ;// not in [./0-9], becomes upper } if ( c > 'Z' ) { c += 6 ;// not in [A-Z], becomes lower } result[m++] = (char) c ; } return ( new String( result ) ); } }