Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;

import org.hibernate.HibernateException;

import static java.util.Comparator.comparing;

/**
Expand Down Expand Up @@ -125,27 +121,121 @@ public String generateHashedConstraintName(

/**
* Hash a constraint name using MD5. Convert the MD5 digest to base 35
* (full alphanumeric), guaranteeing
* that the length of the name will always be smaller than the 30
* character identifier restriction enforced by a few dialects.
* (full alphanumeric), guaranteeing that the length of the name will
* always be smaller than the 30 character identifier restriction
* enforced by some dialects.
*
* @param name The name to be hashed.
*
* @return String The hashed name.
*/
public String hashedName(String name) {
final byte[] bytes;
try {
final MessageDigest md5 = MessageDigest.getInstance( "MD5" );
md5.reset();
md5.update( charset != null ? name.getBytes( charset ) : name.getBytes() );
final BigInteger bigInt = new BigInteger( 1, md5.digest() );
// By converting to base 35 (full alphanumeric), we guarantee
// that the length of the name will always be smaller than the 30
// character identifier restriction enforced by a few dialects.
return bigInt.toString( 35 );
bytes = charset == null
? name.getBytes()
: name.getBytes( charset );
}
catch (UnsupportedEncodingException uee) {
throw new IllegalArgumentException(uee);
}
final byte[] digest = hash( pad( bytes ) );
return new BigInteger( 1, digest ).toString( 35 );
}

// Constants for MD5
private static final int[] S = {
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
};

private static final int[] K = new int[64];
static {
for ( int i = 0; i < 64; i++ ) {
K[i] = (int)(long) ( (1L << 32) * Math.abs( Math.sin( i + 1 ) ) );
}
}

public static byte[] hash(byte[] message) {
int a0 = 0x67452301;
int b0 = 0xefcdab89;
int c0 = 0x98badcfe;
int d0 = 0x10325476;

for ( int i = 0; i < message.length / 64; i++ ) {
final int[] M = new int[16];
for (int j = 0; j < 16; j++) {
M[j] = ((message[i * 64 + j * 4] & 0xFF))
| ((message[i * 64 + j * 4 + 1] & 0xFF) << 8)
| ((message[i * 64 + j * 4 + 2] & 0xFF) << 16)
| ((message[i * 64 + j * 4 + 3] & 0xFF) << 24);
}

int A = a0, B = b0, C = c0, D = d0;

for (int j = 0; j < 64; j++) {
final int F, g;
if (j < 16) {
F = (B & C) | (~B & D);
g = j;
}
else if (j < 32) {
F = (D & B) | (~D & C);
g = (5 * j + 1) % 16;
}
else if (j < 48) {
F = B ^ C ^ D;
g = (3 * j + 5) % 16;
}
else {
F = C ^ (B | ~D);
g = (7 * j) % 16;
}

final int temp = D;
D = C;
C = B;
B = B + Integer.rotateLeft( A + F + K[j] + M[g], S[j] );
A = temp;
}

a0 += A;
b0 += B;
c0 += C;
d0 += D;
}
catch ( NoSuchAlgorithmException | UnsupportedEncodingException e ) {
throw new HibernateException( "Unable to generate a hashed name", e );

// Convert final state to byte array (little-endian)
final byte[] digest = new byte[16];
encodeInt( digest, 0, a0 );
encodeInt( digest, 4, b0 );
encodeInt( digest, 8, c0 );
encodeInt( digest, 12, d0 );
return digest;
}

private static void encodeInt(byte[] output, int offset, int value) {
output[offset] = (byte) (value & 0xFF);
output[offset + 1] = (byte) ((value >>> 8) & 0xFF);
output[offset + 2] = (byte) ((value >>> 16) & 0xFF);
output[offset + 3] = (byte) ((value >>> 24) & 0xFF);
}

private static byte[] pad(byte[] input) {
final int originalLength = input.length;
final int numPaddingBytes = ( 56 - (originalLength + 1) % 64 + 64 ) % 64;

final byte[] padded = new byte[originalLength + 1 + numPaddingBytes + 8];
System.arraycopy( input, 0, padded, 0, originalLength );
padded[originalLength] = (byte) 0x80;

long bitLength = (long) originalLength * 8;
for ( int i = 0; i < 8; i++ ) {
padded[padded.length - 8 + i] = (byte) ( ( bitLength >>> (8 * i) ) & 0xFF );
}

return padded;
}
}
Loading