计算理论中,没有Hash函数的说法,只有单向函数的说法。所谓的单向函数,是一个复杂的定义,大家可以去看计算理论或者密码学方面的数据。用“人类”的语言描述单向函数就是:如果某个函数在给定输入的时候,很容易计算出其结果来;而当给定结果的时候,很难计算出输入来,这就是单项函数。各种加密函数都可以被认为是单向函数的逼近。Hash函数(或者成为散列函数)也可以看成是单向函数的一个逼近。即它接近于满足单向函数的定义。
Hash函数还有另外的含义。实际中的Hash函数是指把一个大范围映射到一个小范围。把大范围映射到一个小范围的目的往往是为了节省空间,使得数据容易保存。除此以外,Hash函数往往应用于查找上。所以,在考虑使用Hash函数之前,需要明白它的几个限制:
1. Hash的主要原理就是把大范围映射到小范围;所以,你输入的实际值的个数必须和小范围相当或者比它更小。不然冲突就会很多。
2. 由于Hash逼近单向函数;所以,你可以用它来对数据进行加密。
3. 不同的应用对Hash函数有着不同的要求;比如,用于加密的Hash函数主要考虑它和单项函数的差距,而用于查找的Hash函数主要考虑它映射到小范围的冲突率。
应用于加密的Hash函数已经探讨过太多了,在作者的博客里面有更详细的介绍。所以,本文只探讨用于查找的Hash函数。
Hash函数应用的主要对象是数组(比如,字符串),而其目标一般是一个int类型。以下我们都按照这种方式来说明。
一般的说,Hash函数可以简单的划分为如下几类:
1. 加法Hash;
2. 位运算Hash;
3. 乘法Hash;
4. 除法Hash;
5. 查表Hash;
6. 混合Hash;
下面详细的介绍以上各种方式在实际中的运用。
一 加法Hash
所谓的加法Hash就是把输入元素一个一个的加起来构成最后的结果。标准的加法Hash的构造如下:
static int additiveHash(String key, int prime) { int hash, i; for (hash = key.length(), i = 0; i < key.length(); i++) hash += key.charAt(i); return (hash % prime); }
这里的prime是任意的质数,看得出,结果的值域为[0,prime-1]。
二 位运算Hash
这类型Hash函数通过利用各种位运算(常见的是移位和异或)来充分的混合输入元素。比如,标准的旋转Hash的构造如下:
static int rotatingHash(String key, int prime) { int hash, i; for (hash=key.length(), i=0; i<key.length(); ++i) hash = (hash<<4)^(hash>>28)^key.charAt(i); return (hash % prime); }
先移位,然后再进行各种位运算是这种类型Hash函数的主要特点。比如,以上的那段计算hash的代码还可以有如下几种变形:
1. hash = (hash<<5)^(hash>>27)^key.charAt(i); 2. hash += key.charAt(i); hash += (hash << 10); hash ^= (hash >> 6); 3. if((i&1) == 0) { hash ^= (hash<<7) ^ key.charAt(i) ^ (hash>>3); } else { hash ^= ~((hash<<11) ^ key.charAt(i) ^ (hash >>5)); } 4. hash += (hash<<5) + key.charAt(i); 5. hash = key.charAt(i) + (hash<<6) + (hash>>16) – hash; 6. hash ^= ((hash<<5) + key.charAt(i) + (hash>>2));
三 乘法Hash
这种类型的Hash函数利用了乘法的不相关性(乘法的这种性质,最有名的莫过于平方取头尾的随机数生成算法,虽然这种算法效果并不好)。比如,
static int bernstein(String key) { int hash = 0; int i; for (i=0; i<key.length(); ++i) hash = 33*hash + key.charAt(i); return hash; }
jdk5.0里面的String类的hashCode()方法也使用乘法Hash。不过,它使用的乘数是31。推荐的乘数还有:131, 1313, 13131, 131313等等。
使用这种方式的著名Hash函数还有:
// 32位FNV算法 int M_SHIFT = 0; public int FNVHash(byte[] data) { int hash = (int)2166136261L; for(byte b : data) hash = (hash * 16777619) ^ b; if (M_SHIFT == 0) return hash; return (hash ^ (hash >> M_SHIFT)) & M_MASK; }
以及改进的FNV算法:
public static int FNVHash1(String data) { final int p = 16777619; int hash = (int)2166136261L; for(int i=0;i<data.length();i++) hash = (hash ^ data.charAt(i)) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return hash; }
除了乘以一个固定的数,常见的还有乘以一个不断改变的数,比如:
static int RSHash(String str) { int b = 378551; int a = 63689; int hash = 0; for(int i = 0; i < str.length(); i++) { hash = hash * a + str.charAt(i); a = a * b; } return (hash & 0x7FFFFFFF); }
虽然Adler32算法的应用没有CRC32广泛,不过,它可能是乘法Hash里面最有名的一个了。关于它的介绍,大家可以去看RFC 1950规范。
四 除法Hash
除法和乘法一样,同样具有表面上看起来的不相关性。不过,因为除法太慢,这种方式几乎找不到真正的应用。需要注意的是,我们在前面看到的hash的结果除以一个prime的目的只是为了保证结果的范围。如果你不需要它限制一个范围的话,可以使用如下的代码替代”hash%prime”: hash = hash ^ (hash>>10) ^ (hash>>20)。
五 查表Hash
查表Hash最有名的例子莫过于CRC系列算法。虽然CRC系列算法本身并不是查表,但是,查表是它的一种最快的实现方式。下面是CRC32的实现:
static int crctab[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; int crc32(String key, int hash) { int i; for (hash=key.length(), i=0; i<key.length(); ++i) hash = (hash >> 8) ^ crctab[(hash & 0xff) ^ k.charAt(i)]; return hash; }
查表Hash中有名的例子有:Universal Hashing和Zobrist Hashing。他们的表格都是随机生成的。
六 混合Hash
混合Hash算法利用了以上各种方式。各种常见的Hash算法,比如MD5、Tiger都属于这个范围。它们一般很少在面向查找的Hash函数里面使用。
七 对Hash算法的评价
http://www.burtleburtle.net/bob/hash/doobs.html 这个页面提供了对几种流行Hash算法的评价。我们对Hash函数的建议如下:
1. 字符串的Hash。最简单可以使用基本的乘法Hash,当乘数为33时,对于英文单词有很好的散列效果(小于6个的小写形式可以保证没有冲突)。复杂一点可以使用FNV算法(及其改进形式),它对于比较长的字符串,在速度和效果上都不错。
2. 长数组的Hash。可以使用http://burtleburtle.net/bob/c/lookup3.c这种算法,它一次运算多个字节,速度还算不错。
八 后记
本文简略的介绍了一番实际应用中的用于查找的Hash算法。Hash算法除了应用于这个方面以外,另外一个著名的应用是巨型字符串匹配(这时的Hash算法叫做:rolling hash,因为它必须可以滚动的计算)。设计一个真正好的Hash算法并不是一件容易的事情。做为应用来说,选择一个适合的算法是最重要的。
常用hash算法类:
package lotusroots.algorithms.math; import java.security.MessageDigest; /** * Hash算法大全<br> * 推荐使用FNV1算法 * * @algorithm None * @author Goodzzp 2006-11-20 * @lastEdit Goodzzp 2006-11-20 * @editDetail Create */ public class HashAlgorithms { /** * 加法hash * * @param key * 字符串 * @param prime * 一个质数 * @return hash结果 */ public static int additiveHash(String key, int prime) { int hash, i; for (hash = key.length(), i = 0; i < key.length(); i++) hash += key.charAt(i); return (hash % prime); } /** * 旋转hash * * @param key * 输入字符串 * @param prime * 质数 * @return hash值 */ public static int rotatingHash(String key, int prime) { int hash, i; for (hash = key.length(), i = 0; i < key.length(); ++i) hash = (hash << 4) ^ (hash >> 28) ^ key.charAt(i); return (hash % prime); // return (hash ^ (hash>>10) ^ (hash>>20)); } // 替代: // 使用:hash = (hash ^ (hash>>10) ^ (hash>>20)) & mask; // 替代:hash %= prime; /** * MASK值,随便找一个值,最好是质数 */ static int M_MASK = 0x8765fed1; /** * 一次一个hash * * @param key * 输入字符串 * @return 输出hash值 */ public static int oneByOneHash(String key) { int hash, i; for (hash = 0, i = 0; i < key.length(); ++i) { hash += key.charAt(i); hash += (hash << 10); hash ^= (hash >> 6); } hash += (hash << 3); hash ^= (hash >> 11); hash += (hash << 15); // return (hash & M_MASK); return hash; } /** * Bernstein's hash * * @param key * 输入字节数组 * @param level * 初始hash常量 * @return 结果hash */ public static int bernstein(String key) { int hash = 0; int i; for (i = 0; i < key.length(); ++i) hash = 33 * hash + key.charAt(i); return hash; } // // // Pearson's Hash // char pearson(char[]key, ub4 len, char tab[256]) // { // char hash; // ub4 i; // for (hash=len, i=0; i<len; ++i) // hash=tab[hash^key[i]]; // return (hash); // } // // CRC Hashing,计算crc,具体代码见其他 // ub4 crc(char *key, ub4 len, ub4 mask, ub4 tab[256]) // { // ub4 hash, i; // for (hash=len, i=0; i<len; ++i) // hash = (hash >> 8) ^ tab[(hash & 0xff) ^ key[i]]; // return (hash & mask); // } /** * Universal Hashing */ public static int universal(char[] key, int mask, int[] tab) { int hash = key.length, i, len = key.length; for (i = 0; i < (len << 3); i += 8) { char k = key[i >> 3]; if ((k & 0x01) == 0) hash ^= tab[i + 0]; if ((k & 0x02) == 0) hash ^= tab[i + 1]; if ((k & 0x04) == 0) hash ^= tab[i + 2]; if ((k & 0x08) == 0) hash ^= tab[i + 3]; if ((k & 0x10) == 0) hash ^= tab[i + 4]; if ((k & 0x20) == 0) hash ^= tab[i + 5]; if ((k & 0x40) == 0) hash ^= tab[i + 6]; if ((k & 0x80) == 0) hash ^= tab[i + 7]; } return (hash & mask); } /** * Zobrist Hashing */ public static int zobrist(char[] key, int mask, int[][] tab) { int hash, i; for (hash = key.length, i = 0; i < key.length; ++i) hash ^= tab[i][key[i]]; return (hash & mask); } // LOOKUP3 // 见Bob Jenkins(3).c文件 // 32位FNV算法 static int M_SHIFT = 0; /** * 32位的FNV算法 * * @param data * 数组 * @return int值 */ public static int FNVHash(byte[] data) { int hash = (int) 2166136261L; for (byte b : data) hash = (hash * 16777619) ^ b; if (M_SHIFT == 0) return hash; return (hash ^ (hash >> M_SHIFT)) & M_MASK; } /** * 改进的32位FNV算法1 * * @param data * 数组 * @return int值 */ public static int FNVHash1(byte[] data) { final int p = 16777619; int hash = (int) 2166136261L; for (byte b : data) hash = (hash ^ b) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return hash; } /** * 改进的32位FNV算法1 * * @param data * 字符串 * @return int值 */ public static int FNVHash1(String data) { final int p = 16777619; int hash = (int) 2166136261L; for (int i = 0; i < data.length(); i++) hash = (hash ^ data.charAt(i)) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return hash; } /** * Thomas Wang的算法,整数hash */ public static int intHash(int key) { key += ~(key << 15); key ^= (key >>> 10); key += (key << 3); key ^= (key >>> 6); key += ~(key << 11); key ^= (key >>> 16); return key; } /** * RS算法hash */ public static int RSHash(String str) { int b = 378551; int a = 63689; int hash = 0; for (int i = 0; i < str.length(); i++) { hash = hash * a + str.charAt(i); a = a * b; } return (hash & 0x7FFFFFFF); } /* End Of RS Hash Function */ /** * JS算法 */ public static int JSHash(String str) { int hash = 1315423911; for (int i = 0; i < str.length(); i++) { hash ^= ((hash << 5) + str.charAt(i) + (hash >> 2)); } return (hash & 0x7FFFFFFF); } /* End Of JS Hash Function */ /** * PJW算法 */ public static int PJWHash(String str) { int BitsInUnsignedInt = 32; int ThreeQuarters = (BitsInUnsignedInt * 3) / 4; int OneEighth = BitsInUnsignedInt / 8; int HighBits = 0xFFFFFFFF << (BitsInUnsignedInt - OneEighth); int hash = 0; int test = 0; for (int i = 0; i < str.length(); i++) { hash = (hash << OneEighth) + str.charAt(i); if ((test = hash & HighBits) != 0) { hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits)); } } return (hash & 0x7FFFFFFF); } /* End Of P. J. Weinberger Hash Function */ /** * ELF算法 */ public static int ELFHash(String str) { int hash = 0; int x = 0; for (int i = 0; i < str.length(); i++) { hash = (hash << 4) + str.charAt(i); if ((x = (int) (hash & 0xF0000000L)) != 0) { hash ^= (x >> 24); hash &= ~x; } } return (hash & 0x7FFFFFFF); } /* End Of ELF Hash Function */ /** * BKDR算法 */ public static int BKDRHash(String str) { int seed = 131; // 31 131 1313 13131 131313 etc.. int hash = 0; for (int i = 0; i < str.length(); i++) { hash = (hash * seed) + str.charAt(i); } return (hash & 0x7FFFFFFF); } /* End Of BKDR Hash Function */ /** * SDBM算法 */ public static int SDBMHash(String str) { int hash = 0; for (int i = 0; i < str.length(); i++) { hash = str.charAt(i) + (hash << 6) + (hash << 16) - hash; } return (hash & 0x7FFFFFFF); } /* End Of SDBM Hash Function */ /** * DJB算法 */ public static int DJBHash(String str) { int hash = 5381; for (int i = 0; i < str.length(); i++) { hash = ((hash << 5) + hash) + str.charAt(i); } return (hash & 0x7FFFFFFF); } /* End Of DJB Hash Function */ /** * DEK算法 */ public static int DEKHash(String str) { int hash = str.length(); for (int i = 0; i < str.length(); i++) { hash = ((hash << 5) ^ (hash >> 27)) ^ str.charAt(i); } return (hash & 0x7FFFFFFF); } /* End Of DEK Hash Function */ /** * AP算法 */ public static int APHash(String str) { int hash = 0; for (int i = 0; i < str.length(); i++) { hash ^= ((i & 1) == 0) ? ((hash << 7) ^ str.charAt(i) ^ (hash >> 3)) : (~((hash << 11) ^ str.charAt(i) ^ (hash >> 5))); } // return (hash & 0x7FFFFFFF); return hash; } /* End Of AP Hash Function */ /** * JAVA自己带的算法 */ public static int java(String str) { int h = 0; int off = 0; int len = str.length(); for (int i = 0; i < len; i++) { h = 31 * h + str.charAt(off++); } return h; } /** * 混合hash算法,输出64位的值 */ public static long mixHash(String str) { long hash = str.hashCode(); hash <<= 32; hash |= FNVHash1(str); return hash; } /** * 计算sha1 * * @param text * 文本 * @return 字节数组 * @throws Exception */ public static byte[] sha1(String text) throws Exception { MessageDigest md; md = MessageDigest.getInstance("SHA-1"); byte[] sha1hash = new byte[40]; byte[] input = text.getBytes("utf-8"); md.update(input, 0, input.length); sha1hash = md.digest(); return sha1hash; } // 4位值对应16进制字符 static char[] m_byteToHexChar = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** * 计算sha1 * * @param text * 文本 * @return 16进制表示的hash值 * @throws Exception */ public static String sha1_text(String text) throws Exception { byte[] hash = sha1(text); StringBuilder ret = new StringBuilder(hash.length * 2); for (byte b : hash) { int d = (b & 0xff); ret.append(m_byteToHexChar[(d & 0xf)]); d >>= 4; ret.append(m_byteToHexChar[(d & 0xf)]); } return ret.toString(); } }
相关推荐
混合函数允许用户通过Java实现自定义函数,例如: 1. **`JAVA_METHOD`**:通过类名和方法名调用Java方法。 2. **`REFLECT`**:反射调用Java方法。 3. **`HASH`**:计算哈希值。 4. **`UDTF`**(User Defined Table ...
在IT领域,哈希函数是一种将任意长度的数据转化为固定长度输出的函数,广泛应用于数据校验、密码存储等方面。在Java编程中,MD5(Message-Digest Algorithm 5)是一种常用的哈希算法,能将任意长度的信息映射为128位...
描述"Maybe it's useful for u"提示我们,这些内容可能是对任何正在学习或使用Java哈希函数的人有所帮助的资源,无论是初学者还是有经验的开发者。 从压缩包的文件名"www.pudn.com.txt"来看,这可能是一个链接或者...
这里我们将深入探讨 Java 中实现数据完整性验证的方法,主要关注MD5(Message-Digest Algorithm 5)哈希算法的应用。 首先,我们要了解什么是数据完整性。数据完整性是指数据在创建、存储和传输过程中保持不变的...
在IT领域,哈希(Hash)函数是一种将任意长度的数据转换为固定长度输出的函数,通常用于数据的校验、加密以及数据索引等场景。Java作为一种广泛使用的编程语言,提供了丰富的API来支持哈希计算。这个“获取哈希及...
标题中的"hmac.zip_hmac_java hmac_zip"表明这个压缩包主要包含了关于HMAC(Hash-based Message Authentication Code)在Java环境下的实现,特别是与ZIP文件相关的应用。HMAC是一种基于哈希函数的安全机制,用于验证...
标题中的“HMAC.rar_Quick_java hmac”表明这是一个关于Java实现快速哈希消息认证码(Hash-based Message Authentication Code,简称HMAC)的压缩文件。HMAC是一种基于密钥的哈希函数,用于验证数据的完整性和来源。...
在Java的HashMap中,哈希函数是由内部的`hash()`方法提供的,它通过计算键对象的哈希值并进行位操作来确定元素的位置。如果两个不同的键产生了相同的哈希值,那么就会发生冲突。 处理冲突有多种策略,如开放寻址法...
标题中的"SHA in java"指的是Secure Hash Algorithm (SHA)家族,这是一个用于产生数字摘要的密码散列函数。SHA-1是其中的一员,它能够将任意长度的信息转化为一个固定长度的摘要,通常用于验证数据的完整性。在Java...
在这个场景中,描述提到“获取文件的‘MD5’值”,这涉及到文件的哈希计算,尤其是MD5(Message-Digest Algorithm 5)这种广泛应用的哈希算法。 MD5是一种广泛使用的加密散列函数,产生一个128位(16字节)的散列值...
综上所述,本文档主要关注的是Java编程语言中MD5加密算法的应用,特别是通过实现KeyBean类来执行RFC 1321中的消息摘要算法。通过理解MD5算法的基本原理及其在Java中的实现方式,开发者可以更好地利用这种技术来确保...
4. 关于Java语言特性的描述中,错误的是:Java语言中的方法属于类的成员、Java面向对象语言不允许单独的过程与函数存在、Java语言中的方法必定隶属于某一类(对象),调用方法与过程或函数相同。Java允许单独的方法...
描述中提到的“详细注释”可能包含了关于每行代码的功能解释,帮助初学者理解MD5算法的工作原理和Java实现的细节。测试数据则用于验证程序的正确性,确保对不同输入的MD5哈希计算结果与预期相符。 MD5的主要应用...
虽然描述部分为空白,但从标题和标签来看,这份材料大概率是围绕Java环境下如何实现和操作不同的数据结构展开讨论。接下来,我们将基于这一假设深入探讨与Java数据结构相关的知识点。 ### Java数据结构概述 在...
此外,Java还支持哈希函数,如MD5(Message-Digest Algorithm 5)和SHA(Secure Hash Algorithm)系列,它们可以将任意长度的消息转化为固定长度的摘要,但不适用于加密,因为它们不具备可逆性。在Java中,`java....
描述中的"md5加密算法java编写"意味着这个压缩包提供了使用Java语言实现的MD5加密功能。在Java中,MD5的实现主要依赖于`java.security.MessageDigest`类。下面我们将详细讨论如何在Java中使用MD5进行加密。 首先,...
12.10. 与GROUP BY子句同时使用的函数和修改程序 12.10.1. GROUP BY(聚合)函数 12.10.2. GROUP BY修改程序 12.10.3. 具有隐含字段的GROUP BY 13. SQL语句语法 13.1. 数据定义语句 13.1.1. ALTER DATABASE语法 ...
12.10. 与GROUP BY子句同时使用的函数和修改程序 12.10.1. GROUP BY(聚合)函数 12.10.2. GROUP BY修改程序 12.10.3. 具有隐含字段的GROUP BY 13. SQL语句语法 13.1. 数据定义语句 13.1.1. ALTER DATABASE语法 ...