package org.postgresql.util;

/**
 * MD5-based utility function to obfuscate passwords before network transmission
 *
 * @author Jeremy Wohl
 *
 */

import java.security.*;

public class MD5Digest
{
    private MD5Digest() {}


    /**
     * Encodes user/password/salt information in the following way:
     *   MD5(MD5(password + user) + salt)
     *
     * @param user      The connecting user.
     * @param password  The connecting user's password.
     * @param salt      A four-character string sent by the server.
     *
     * @return  A 35-byte array, comprising the string "md5", followed by an MD5 digest.
     */
    public static byte[] encode(String user, String password, String salt)
    {
	MessageDigest  md;
	byte[]         temp_digest, pass_digest;
	byte[]         hex_digest = new byte[35];
	    

	try {
	    md = MessageDigest.getInstance("MD5");

	    md.update(password.getBytes());
	    md.update(user.getBytes());
	    temp_digest = md.digest();

	    bytesToHex(temp_digest, hex_digest, 0);
	    md.update(hex_digest, 0, 32);
	    md.update(salt.getBytes());
	    pass_digest = md.digest();

	    bytesToHex(pass_digest, hex_digest, 3);
	    hex_digest[0] = (byte) 'm'; hex_digest[1] = (byte) 'd'; hex_digest[2] = (byte) '5';
	} catch (Exception e) {
	    ; // "MessageDigest failure; " + e
	}

	return hex_digest;
    }


    /**
     * Turn 16-byte stream into a human-readable 32-byte hex string
     */
    private static void bytesToHex(byte[] bytes, byte[] hex, int offset)
    {
	final char lookup[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'a', 'b', 'c', 'd', 'e', 'f' };
	
	int i, c, j, pos = offset;
	
	for (i = 0; i < 16; i++) {
	    c = bytes[i] & 0xFF; j = c >> 4;
	    hex[pos++] = (byte) lookup[j];
	    j = (c & 0xF);
	    hex[pos++] = (byte) lookup[j];
	}
    }
}
