common_helper/src/main/java/com/xiongyingqi/util/MD5Crypt.java
static public final String crypt(String password, String salt, String magic) {

        byte finalState[];
        long l;

        /**
         * Two MD5 hashes are used
         */
        MessageDigest ctx, ctx1;

        try {
            ctx = MessageDigest.getInstance("md5");
            ctx1 = MessageDigest.getInstance("md5");
        } catch (NoSuchAlgorithmException ex) {
            System.err.println(ex);
            return null;
        }

		/* Refine the Salt first */
        /* If it starts with the magic string, then skip that */

        if (salt.startsWith(magic)) {
            salt = salt.substring(magic.length());
        }

		/* It stops at the first '$', max 8 chars */

        if (salt.indexOf('$') != -1) {
            salt = salt.substring(0, salt.indexOf('$'));
        }

        if (salt.length() > 8) {
            salt = salt.substring(0, 8);
        }

        /**
         * Transformation set #1: The password first, since that is what is most
         * unknown Magic string Raw salt
         */
        ctx.update(password.getBytes());
        ctx.update(magic.getBytes());
        ctx.update(salt.getBytes());

		/* Then just as many characters of the MD5(pw,salt,pw) */

        ctx1.update(password.getBytes());
        ctx1.update(salt.getBytes());
        ctx1.update(password.getBytes());
        finalState = ctx1.digest(); // ctx1.Final();

        for (int pl = password.length(); pl > 0; pl -= 16) {
            ctx.update(finalState, 0, pl > 16 ? 16 : pl);
        }

        /**
         * the original code claimed that finalState was being cleared to keep
         * dangerous bits out of memory, but doing this is also required in
         * order to get the right output.
         */

        clearbits(finalState);

		/* Then something really weird... */

        for (int i = password.length(); i != 0; i >>>= 1) {
            if ((i & 1) != 0) {
                ctx.update(finalState, 0, 1);
            } else {
                ctx.update(password.getBytes(), 0, 1);
            }
        }

        finalState = ctx.digest();

        /**
         * and now, just to make sure things don't run too fast On a 60 Mhz
         * Pentium this takes 34 msec, so you would need 30 seconds to build a
         * 1000 entry dictionary... (The above timings from the C version)
         */

        for (int i = 0; i < 1000; i++) {
            try {
                ctx1 = MessageDigest.getInstance("md5");
            } catch (NoSuchAlgorithmException e0) {
                return null;
            }

            if ((i & 1) != 0) {
                ctx1.update(password.getBytes());
            } else {
                ctx1.update(finalState, 0, 16);
            }

            if ((i % 3) != 0) {
                ctx1.update(salt.getBytes());
            }

            if ((i % 7) != 0) {
                ctx1.update(password.getBytes());
            }

            if ((i & 1) != 0) {
                ctx1.update(finalState, 0, 16);
            } else {
                ctx1.update(password.getBytes());
            }

            finalState = ctx1.digest(); // Final();
        }

		/* Now make the output string */

        StringBuffer result = new StringBuffer();

        result.append(magic);
        result.append(salt);
        result.append("$");

        /**
         * Build a 22 byte output string from the set: A-Za-z0-9./
         */
        l = (bytes2u(finalState[0]) << 16) | (bytes2u(finalState[6]) << 8)
                | bytes2u(finalState[12]);
        result.append(to64(l, 4));

        l = (bytes2u(finalState[1]) << 16) | (bytes2u(finalState[7]) << 8)
                | bytes2u(finalState[13]);
        result.append(to64(l, 4));

        l = (bytes2u(finalState[2]) << 16) | (bytes2u(finalState[8]) << 8)
                | bytes2u(finalState[14]);
        result.append(to64(l, 4));

        l = (bytes2u(finalState[3]) << 16) | (bytes2u(finalState[9]) << 8)
                | bytes2u(finalState[15]);
        result.append(to64(l, 4));

        l = (bytes2u(finalState[4]) << 16) | (bytes2u(finalState[10]) << 8)
                | bytes2u(finalState[5]);
        result.append(to64(l, 4));

        l = bytes2u(finalState[11]);
        result.append(to64(l, 2));

		/* Don't leave anything around in vm they could use. */
        clearbits(finalState);

        return result.toString();
    }
static public final String crypt(String password, String salt, String magic) {

        byte finalState[];
        long l;

        /**
         * Two MD5 hashes are used
         */
        MessageDigest ctx, ctx1;

        try {
            ctx = MessageDigest.getInstance("md5");
            ctx1 = MessageDigest.getInstance("md5");
        } catch (NoSuchAlgorithmException ex) {
            System.err.println(ex);
            return null;
        }

		/* Refine the Salt first */
        /* If it starts with the magic string, then skip that */

        if (salt.startsWith(magic)) {
            salt = salt.substring(magic.length());
        }

		/* It stops at the first '$', max 8 chars */

        if (salt.indexOf('$') != -1) {
            salt = salt.substring(0, salt.indexOf('$'));
        }

        if (salt.length() > 8) {
            salt = salt.substring(0, 8);
        }

        /**
         * Transformation set #1: The password first, since that is what is most
         * unknown Magic string Raw salt
         */
        ctx.update(password.getBytes());
        ctx.update(magic.getBytes());
        ctx.update(salt.getBytes());

		/* Then just as many characters of the MD5(pw,salt,pw) */

        ctx1.update(password.getBytes());
        ctx1.update(salt.getBytes());
        ctx1.update(password.getBytes());
        finalState = ctx1.digest(); // ctx1.Final();

        for (int pl = password.length(); pl > 0; pl -= 16) {
            ctx.update(finalState, 0, pl > 16 ? 16 : pl);
        }

        /**
         * the original code claimed that finalState was being cleared to keep
         * dangerous bits out of memory, but doing this is also required in
         * order to get the right output.
         */

        clearbits(finalState);

		/* Then something really weird... */

        for (int i = password.length(); i != 0; i >>>= 1) {
            if ((i & 1) != 0) {
                ctx.update(finalState, 0, 1);
            } else {
                ctx.update(password.getBytes(), 0, 1);
            }
        }

        finalState = ctx.digest();

        /**
         * and now, just to make sure things don't run too fast On a 60 Mhz
         * Pentium this takes 34 msec, so you would need 30 seconds to build a
         * 1000 entry dictionary... (The above timings from the C version)
         */

        for (int i = 0; i < 1000; i++) {
            try {
                ctx1 = MessageDigest.getInstance("md5");
            } catch (NoSuchAlgorithmException e0) {
                return null;
            }

            if ((i & 1) != 0) {
                ctx1.update(password.getBytes());
            } else {
                ctx1.update(finalState, 0, 16);
            }

            if ((i % 3) != 0) {
                ctx1.update(salt.getBytes());
            }

            if ((i % 7) != 0) {
                ctx1.update(password.getBytes());
            }

            if ((i & 1) != 0) {
                ctx1.update(finalState, 0, 16);
            } else {
                ctx1.update(password.getBytes());
            }

            finalState = ctx1.digest(); // Final();
        }

		/* Now make the output string */

        StringBuffer result = new StringBuffer();

        result.append(magic);
        result.append(salt);
        result.append("$");

        /**
         * Build a 22 byte output string from the set: A-Za-z0-9./
         */
        l = (bytes2u(finalState[0]) << 16) | (bytes2u(finalState[6]) << 8)
                | bytes2u(finalState[12]);
        result.append(to64(l, 4));

        l = (bytes2u(finalState[1]) << 16) | (bytes2u(finalState[7]) << 8)
                | bytes2u(finalState[13]);
        result.append(to64(l, 4));

        l = (bytes2u(finalState[2]) << 16) | (bytes2u(finalState[8]) << 8)
                | bytes2u(finalState[14]);
        result.append(to64(l, 4));

        l = (bytes2u(finalState[3]) << 16) | (bytes2u(finalState[9]) << 8)
                | bytes2u(finalState[15]);
        result.append(to64(l, 4));

        l = (bytes2u(finalState[4]) << 16) | (bytes2u(finalState[10]) << 8)
                | bytes2u(finalState[5]);
        result.append(to64(l, 4));

        l = bytes2u(finalState[11]);
        result.append(to64(l, 2));

		/* Don't leave anything around in vm they could use. */
        clearbits(finalState);

        return result.toString();
    }
static public final String crypt ( String password , String salt , String magic ) { byte finalState [ ] ; long l ; /**
         * Two MD5 hashes are used
         */ MessageDigest ctx , ctx1 ; try { ctx = MessageDigest . getInstance ( "md5" ) ; ctx1 = MessageDigest . getInstance ( "md5" ) ; } catch ( NoSuchAlgorithmException ex ) { System . err . println ( ex ) ; return null ; } /* Refine the Salt first */ /* If it starts with the magic string, then skip that */ if ( salt . startsWith ( magic ) ) { salt = salt . substring ( magic . length ( ) ) ; } /* It stops at the first '$', max 8 chars */ if ( salt . indexOf ( ' ' ) != - 1 ) { salt = salt . substring ( 0 , salt . indexOf ( ' ' ) ) ; } if ( salt . length ( ) > 8 ) { salt = salt . substring ( 0 , 8 ) ; } /**
         * Transformation set #1: The password first, since that is what is most
         * unknown Magic string Raw salt
         */ ctx . update ( password . getBytes ( ) ) ; ctx . update ( magic . getBytes ( ) ) ; ctx . update ( salt . getBytes ( ) ) ; /* Then just as many characters of the MD5(pw,salt,pw) */ ctx1 . update ( password . getBytes ( ) ) ; ctx1 . update ( salt . getBytes ( ) ) ; ctx1 . update ( password . getBytes ( ) ) ; finalState = ctx1 . digest ( ) ; // ctx1.Final(); for ( int pl = password . length ( ) ; pl > 0 ; pl -= 16 ) { ctx . update ( finalState , 0 , pl > 16 ? 16 : pl ) ; } /**
         * the original code claimed that finalState was being cleared to keep
         * dangerous bits out of memory, but doing this is also required in
         * order to get the right output.
         */ clearbits ( finalState ) ; /* Then something really weird... */ for ( int i = password . length ( ) ; i != 0 ; i >>>= 1 ) { if ( ( i & 1 ) != 0 ) { ctx . update ( finalState , 0 , 1 ) ; } else { ctx . update ( password . getBytes ( ) , 0 , 1 ) ; } } finalState = ctx . digest ( ) ; /**
         * and now, just to make sure things don't run too fast On a 60 Mhz
         * Pentium this takes 34 msec, so you would need 30 seconds to build a
         * 1000 entry dictionary... (The above timings from the C version)
         */ for ( int i = 0 ; i < 1000 ; i ++ ) { try { ctx1 = MessageDigest . getInstance ( "md5" ) ; } catch ( NoSuchAlgorithmException e0 ) { return null ; } if ( ( i & 1 ) != 0 ) { ctx1 . update ( password . getBytes ( ) ) ; } else { ctx1 . update ( finalState , 0 , 16 ) ; } if ( ( i % 3 ) != 0 ) { ctx1 . update ( salt . getBytes ( ) ) ; } if ( ( i % 7 ) != 0 ) { ctx1 . update ( password . getBytes ( ) ) ; } if ( ( i & 1 ) != 0 ) { ctx1 . update ( finalState , 0 , 16 ) ; } else { ctx1 . update ( password . getBytes ( ) ) ; } finalState = ctx1 . digest ( ) ; // Final(); } /* Now make the output string */ StringBuffer result = new StringBuffer ( ) ; result . append ( magic ) ; result . append ( salt ) ; result . append ( "$" ) ; /**
         * Build a 22 byte output string from the set: A-Za-z0-9./
         */ l = ( bytes2u ( finalState [ 0 ] ) << 16 ) | ( bytes2u ( finalState [ 6 ] ) << 8 ) | bytes2u ( finalState [ 12 ] ) ; result . append ( to64 ( l , 4 ) ) ; l = ( bytes2u ( finalState [ 1 ] ) << 16 ) | ( bytes2u ( finalState [ 7 ] ) << 8 ) | bytes2u ( finalState [ 13 ] ) ; result . append ( to64 ( l , 4 ) ) ; l = ( bytes2u ( finalState [ 2 ] ) << 16 ) | ( bytes2u ( finalState [ 8 ] ) << 8 ) | bytes2u ( finalState [ 14 ] ) ; result . append ( to64 ( l , 4 ) ) ; l = ( bytes2u ( finalState [ 3 ] ) << 16 ) | ( bytes2u ( finalState [ 9 ] ) << 8 ) | bytes2u ( finalState [ 15 ] ) ; result . append ( to64 ( l , 4 ) ) ; l = ( bytes2u ( finalState [ 4 ] ) << 16 ) | ( bytes2u ( finalState [ 10 ] ) << 8 ) | bytes2u ( finalState [ 5 ] ) ; result . append ( to64 ( l , 4 ) ) ; l = bytes2u ( finalState [ 11 ] ) ; result . append ( to64 ( l , 2 ) ) ; /* Don't leave anything around in vm they could use. */ clearbits ( finalState ) ; return result . toString ( ) ; }
Linux/BSD MD5Crypt function

@param magic    $1$ for Linux/BSB, $apr1$ for Apache crypt
@param salt     8 byte permutation string
@param password user password
@return The encrypted password as an MD5 hash
Linux / BSD MD5Crypt function