几种加密解密算法
public final class MD5Crypt {
/**
*
* Command line test rig.
* @throws NoSuchAlgorithmException
*
*/
static public void main(String argv[]) throws NoSuchAlgorithmException
{
System.out.println(crypt("daliantan0v0"));;
// if ((argv.length < 1) || (argv.length > 2))
// {
// System.err.println("Usage: MD5Crypt password salt");
// System.exit(1);
// }
//
// if (argv.length == 2)
// {
// System.err.println(MD5Crypt.crypt(argv[0], argv[1]));
// }
// else
// {
// System.err.println(MD5Crypt.crypt(argv[0]));
// }
//
// System.exit(0);
}
static private final String SALTCHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
static private final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static private final String to64(long v, int size)
{
StringBuffer result = new StringBuffer();
while (--size >= 0)
{
result.append(itoa64.charAt((int) (v & 0x3f)));
v >>>= 6;
}
return result.toString();
}
static private final void clearbits(byte bits[])
{
for (int i = 0; i < bits.length; i++)
{
bits[i] = 0;
}
}
/**
* convert an encoded unsigned byte value into a int
* with the unsigned value.
*/
static private final int bytes2u(byte inp)
{
return (int) inp & 0xff;
}
/**
* <p>This method actually generates a OpenBSD/FreeBSD/Linux PAM compatible
* md5-encoded password hash from a plaintext password and a
* salt.</p>
*
* <p>The resulting string will be in the form '$1$<salt>$<hashed mess></p>
*
* @param password Plaintext password
*
* @return An OpenBSD/FreeBSD/Linux-compatible md5-hashed password field.
* @throws NoSuchAlgorithmException
*/
static public final String crypt(String password) throws NoSuchAlgorithmException
{
StringBuffer salt = new StringBuffer();
java.util.Random randgen = new java.util.Random();
/* -- */
while (salt.length() < 8)
{
int index = (int) (randgen.nextFloat() * SALTCHARS.length());
salt.append(SALTCHARS.substring(index, index+1));
}
return MD5Crypt.crypt(password, salt.toString());
}
/**
* <p>This method actually generates a OpenBSD/FreeBSD/Linux PAM compatible
* md5-encoded password hash from a plaintext password and a
* salt.</p>
*
* <p>The resulting string will be in the form '$1$<salt>$<hashed mess></p>
*
* @param password Plaintext password
* @param salt A short string to use to randomize md5. May start with $1$, which
* will be ignored. It is explicitly permitted to pass a pre-existing
* MD5Crypt'ed password entry as the salt. crypt() will strip the salt
* chars out properly.
*
* @return An OpenBSD/FreeBSD/Linux-compatible md5-hashed password field.
* @throws NoSuchAlgorithmException
*/
static public final String crypt(String password, String salt) throws NoSuchAlgorithmException
{
/* This string is magic for this algorithm. Having it this way,
* we can get get better later on */
String magic = "$1$";
byte finalState[];
MessageDigest ctx, ctx1;
long l;
/* -- */
/* 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);
}
ctx = MessageDigest.getInstance("MD5");
ctx.update(password.getBytes()); // The password first, since that is what is most unknown
ctx.update(magic.getBytes()); // Then our magic string
ctx.update(salt.getBytes()); // Then the raw salt
/* Then just as many characters of the MD5(pw,salt,pw) */
ctx1 = MessageDigest.getInstance("MD5");
ctx1.update(password.getBytes());
ctx1.update(salt.getBytes());
ctx1.update(password.getBytes());
finalState = ctx1.digest();
for (int pl = password.length(); pl > 0; pl -= 16)
{
for( int i=0; i< (pl > 16 ? 16 : pl); i++ )
ctx.update(finalState[i] );
}
/* 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]);
}
else
{
ctx.update(password.getBytes()[0]);
}
}
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++)
{
ctx1 = MessageDigest.getInstance("MD5");
if ((i & 1) != 0)
{
ctx1.update(password.getBytes());
}
else
{
for( int c=0; c<16; c++ )
ctx1.update(finalState[c]);
}
if ((i % 3) != 0)
{
ctx1.update(salt.getBytes());
}
if ((i % 7) != 0)
{
ctx1.update(password.getBytes());
}
if ((i & 1) != 0)
{
for( int c=0; c<16; c++ )
ctx1.update(finalState[c]);
}
else
{
ctx1.update(password.getBytes());
}
finalState = ctx1.digest();
}
/* Now make the output string */
StringBuffer result = new StringBuffer();
result.append(magic);
result.append(salt);
result.append("$");
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();
}
}