åå¸ç®æ³ï¼Hashï¼åç§°æè¦ç®æ³ï¼Digestï¼ï¼å®çä½ç¨æ¯ï¼å¯¹ä»»æä¸ç»è¾å ¥æ°æ®è¿è¡è®¡ç®ï¼å¾å°ä¸ä¸ªåºå®é¿åº¦çè¾åºæè¦ã
常ç¨çåå¸ç®æ³æï¼

æ ¹æ®ç¢°ææ¦çï¼åå¸ç®æ³çè¾åºé¿åº¦è¶é¿ï¼å°±è¶é¾äº§ç碰æï¼ä¹å°±è¶å®å ¨ã
æ£åç®æ³æ¯è¾
| åç§° | å®å ¨æ§ | é度 |
|---|---|---|
| MD5 | ä¸ | å¿« |
| SHA | é« | æ ¢ |
| åç§° | ä¼ç¹ | ç¼ºç¹ | ç ´è§£æ¹å¼ | 使ç¨åºæ¯ |
|---|---|---|---|---|
| MD5 | ç®åã伪é é¾ | æ½å¨çå²çª | æ´åç ´è§£ | 1ï¼ç»å½å¯ç ä¿æ¤ï¼2ï¼æä»¶é²æ¢ç¯¡æ¹ï¼3ï¼HTTPä¼ è¾å 容å å¯é²ç¯¡æ¹ï¼4ï¼æ°åç¾åï¼ |
åå¸ç®æ³æéè¦çç¹ç¹å°±æ¯ï¼
- åºå®è¾å ¥ä¸å®å¾å°åºå®è¾åº
- ä¸åè¾å ¥å¾å°ç¸åè¾åºçæ¦çæä½ãä¸åçè¾å ¥å¤§æ¦çå¾å°ä¸åçè¾åºã
- ååæ§ï¼å°±æ¯æ ¹æ®ç®æ³ï¼ç论ä¸ä¸è½ä»è®¡ç®ä¹åçæ£åå¼éæ¨åºåå§ææã
- æ 论è¾å ¥æ°æ®çé¿åº¦æ¯å¤å°ï¼å¾å°çè¾åºå¼æ¯åºå®çãMD5ï¼æ£åå¼è¿è¡åå è¿å¶ç¼ç ä¹åé¿åº¦ä¸º32ï¼SHA256 å为 64ï¼
å忣å彿°ï¼ä¸ç®¡ææå¤é¿ï¼æ£ååç坿å®é¿ãæ£ååç坿ä¸å¯éã
Hashæ»å»ï¼å½©è¹è¡¨æ»å»
彩è¹è¡¨æ»å»ï¼Rainbow Table Attackï¼æ¯ä¸ç§å¯ç ç ´è§£ææ¯ï¼ç¨äºç ´è§£å¯ç åå¸çå®å ¨æ§ã 宿¯ä¸ç§é¢å 计ç®å¯ç åå¸åå ¶å¯¹åºææçå·¨å¤§æ°æ®è¡¨çæ¹æ³ãè½ç¶å½©è¹è¡¨æ»å»ä¸æ¯ç´æ¥æ´åç ´è§£å¯ç ï¼ä½å®å¯ä»¥æ´å¿«å°ç ´è§£å å¯å¯ç ï¼å°¤å ¶æ¯å½ä½¿ç¨å¼±å¯ç æ¶ã
以é²å¾¡è çè§è§ï¼éè¿æç§æªæ½æ¥æµå¾¡å½©è¹è¡¨ç ´è§£æè 使æ»å»è çç ´è§£é¾åº¦åææ¬å¤§å¤§å¢å ã
å çï¼ å çæ¯å¨ç¨æ·å¯ç çåºç¡ä¸æ·»å ä¸ä¸ªéæºçæçå符串ï¼ç¶ååè¿è¡åå¸è¿ç®ã è¿ä¸ªéæºå符串被称为çï¼å®ä½¿å¾ç¸åçå¯ç å¨å çåå¾å°çåå¸å¼ä¹æ¯ä¸åçã 彩è¹è¡¨æ»å»ç主è¦ä¼å¿å¨äºäºå 计ç®å¤§éå¯ç çåå¸å¼ï¼å¹¶å°å ¶åå¨å¨è¡¨ä¸ã éè¿å çï¼å³ä½¿å¯ç ç¸åï¼ç±äºæ¯ä¸ªç¨æ·é½æå¯ä¸ççï¼æç»çåå¸å¼ä¹ä¼ææä¸åï¼ä½¿å¾äºå 计ç®çè¡¨æ æ³ç´æ¥ç¨äºæ»å»ã
è¿ä»£åå¸ï¼ è¿ä»£å叿¯å¯¹å¯ç è¿è¡å¤æ¬¡è¿ä»£çåå¸è¿ç®ï¼å¢å ç ´è§£å¯ç æéçæ¶é´ã é常ï¼åå¸å¼ä¼åå¤ä½ä¸ºè¾å ¥è¿è¡æ´å¤æ¬¡çåå¸è¿ç®ï¼ä»è产çæç»çåå¸å¼ã 彩è¹è¡¨æ»å»çéåº¦ä¸»è¦æ¥èªäºäºå 计ç®å¤§éçåå¸å¼ï¼èè¿ä»£åå¸ä½¿å¾æ¯ä¸ªå°è¯çå¯ç éè¦æ´å¤çè®¡ç®æ¶é´ã éå½éæ©è¿ä»£æ¬¡æ°å¯ä»¥å¨ä¿è¯ç¨æ·ç»å½æ¶çåçååºæ¶é´çåæ¶ï¼ææå°å¢å æ»å»è è¿è¡å½©è¹è¡¨æ»å»æ¶æéçè®¡ç®æ¶é´ã
MD5
MD5æ¶æ¯æè¦ç®æ³ï¼å±Hashç®æ³ä¸ç±»ã
MD5ç®æ³æ¯ä¸ç§å¹¿æ³ä½¿ç¨çåå¸å½æ°ï¼ç¨äºçæ128ä½ï¼32个åå è¿å¶æ°åï¼çæ¶æ¯æè¦ã 宿¥åä»»æé¿åº¦çè¾å ¥ï¼å¹¶è¾åºåºå®é¿åº¦çåå¸å¼ï¼ä¸ä¸ª128ä½çæ¶æ¯æè¦ï¼32ä½çæ°ååæ¯æ··åç ï¼ï¼é常ç¨äºéªè¯æ°æ®å®æ´æ§ãæ°åç¾åãå¯ç åå¨çé¢åã MD5ç®æ³ä»¥å ¶ç®æ´é«æç设计åå¿«é计ç®é度èé»åï¼ ä½è¿å¹´æ¥ç±äºå ¶åå¨ä¸äºå®å ¨æ§å¼±ç¹ï¼éæ¸è¢«æ´å®å ¨çåå¸ç®æ³æå代ã
MD5主è¦ç¹ç¹
ä¸ä¸ªMD5ç论ä¸çç¡®æ¯å¯è½å¯¹åºæ æ°å¤ä¸ªåæçï¼å 为MD5æ¯æéå¤ä¸ªçèåæå¯ä»¥æ¯æ æ°å¤ä¸ªã æ¯å¦ä¸»æµä½¿ç¨çMD5å°ä»»æé¿åº¦çâåè串æ å°ä¸ºä¸ä¸ª128bitçå¤§æ´æ°ã ä¹å°±æ¯ä¸å ±æ2^128^ç§å¯è½ ï¼å¤§æ¦æ¯3.4*10^38^ï¼è¿ä¸ªæ°åæ¯æéå¤ä¸ªçï¼ è使¯ä¸çä¸å¯ä»¥è¢«ç¨æ¥å å¯çåæåä¼ææ æ°çå¯è½æ§ã
MD5çæ§è´¨
- 1ãå缩æ§ï¼ä»»æé¿åº¦çæ°æ®ï¼ç®åºçMD5å¼é¿åº¦é½æ¯åºå®ç(ç¸å½äºè¶ æå缩)ã
- 2ã容æè®¡ç®ï¼ä»åæ°æ®è®¡ç®åºMD5å¼å¾å®¹æã
- 3ãæä¿®æ¹æ§ï¼å¯¹åæ°æ®è¿è¡ä»»ä½æ¹å¨ï¼åªæåªä¿®æ¹1个åèï¼æå¾å°çMD5å¼é½æå¾å¤§åºå«ã
- 4ãå¼±æç¢°æï¼å·²ç¥åæ°æ®åå ¶MD5å¼ï¼æ³æ¾å°ä¸ä¸ªå ·æç¸åMD5å¼çæ°æ®ï¼å³ä¼ªé æ°æ®ï¼æ¯é常å°é¾çã
- 5ã强æç¢°æï¼æ³æ¾å°ä¸¤ä¸ªä¸åçæ°æ®ï¼ä½¿å®ä»¬å ·æç¸åçMD5å¼ï¼æ¯é常å°é¾çã
MD5ç®æ³çåºç¨
æ°æ®å®æ´æ§éªè¯
MD5ç®æ³å¸¸ç¨äºæ°æ®å®æ´æ§éªè¯ï¼å³ç¡®ä¿æ°æ®å¨ä¼ è¾æåå¨è¿ç¨ä¸æ²¡æè¢«ç¯¡æ¹ãåéæ¹ä¼è®¡ç®æ°æ®çMD5åå¸å¼å¹¶å°å ¶éå 卿°æ®ä¸ä¸èµ·ä¼ è¾ï¼æ¥æ¶æ¹æ¶å°æ°æ®åéæ°è®¡ç®MD5åå¸å¼ï¼å¹¶ä¸æ¥æ¶å°çMD5åå¸å¼è¿è¡æ¯è¾ï¼å¦æä¸è´åè¯´ææ°æ®å®æ´æ§è¯å¥½ã
æ°åç¾å
MD5ç®æ³ä¹å¯ä»¥ç¨äºæ°åç¾åï¼æ°åç¾åæ¯ä¸ç§ç¨äºéªè¯æ°æ®æ¥æºå宿´æ§çææ¯ãåéæ¹ä½¿ç¨ç§é¥å¯¹æ°æ®çMD5åå¸å¼è¿è¡å å¯ï¼çææ°åç¾åå¹¶å°å ¶éå 卿°æ®ä¸åéãæ¥æ¶æ¹ä½¿ç¨åéæ¹çå ¬é¥è§£å¯æ°åç¾åï¼åè®¡ç®æ°æ®çMD5åå¸å¼å¹¶ä¸è§£å¯åçæ°åç¾åè¿è¡æ¯è¾ï¼ä»¥éªè¯æ°æ®ç宿´æ§åç宿§ã
å¯ç åå¨
å¨å¯ç å卿¹é¢ï¼MD5ç®æ³å¯ä»¥ç¨äºå å¯å¯ç å¹¶åå¨å¨æ°æ®åºä¸ãå½ç¨æ·ç»å½æ¶ï¼ç³»ç»ä¼å¯¹ç¨æ·è¾å ¥çå¯ç è¿è¡MD5åå¸è¿ç®ï¼ç¶å䏿°æ®åºä¸åå¨çMD5åå¸å¼è¿è¡æ¯è¾ï¼ä»¥éªè¯å¯ç çæ£ç¡®æ§ãç¶èï¼ç±äºMD5ç®æ³åå¨ç¢°ææ»å»çå®å ¨æ¼æ´ï¼ç°å¨æ´æ¨èä½¿ç¨æ´å®å ¨çåå¸ç®æ³å¦SHA-256æ¥åå¨å¯ç ã
æä»¶æ ¡éª
MD5ç®æ³è¿å¸¸ç¨äºæä»¶æ ¡éªï¼ä¾å¦ä¸è½½æä»¶åå¯ä»¥è®¡ç®æä»¶çMD5åå¸å¼ï¼ä¸æä¾çMD5å¼è¿è¡æ¯è¾ï¼ä»¥ç¡®ä¿æä»¶å¨ä¼ è¾è¿ç¨ä¸æ²¡æè¢«ç¯¡æ¹ææåãå¦æä¸¤ä¸ªMD5å¼ä¸è´ï¼åæä»¶å®æ´ï¼å¦åå¯è½åå¨é®é¢ã
é®é¢è§£ç
MD5ç®æ³æåªäºåºç¨åºæ¯ï¼
MD5ç®æ³å¸¸ç¨äºéªè¯æ°æ®å®æ´æ§ï¼æä»¶æ ¡éªï¼å¯ç åå¨çåºæ¯ã
MD5ç®æ³åå¨åªäºå®å ¨æ§é®é¢ï¼
MD5ç®æ³åå¨ç¢°ææ»å»æ¼æ´ï¼ä¸åå®å ¨å¯é ï¼å®¹æè¢«ç ´è§£ã
MD5ç®æ³ä¸SHAç®æ³æä½åºå«ï¼
MD5ç®æ³åSHAç®æ³é½æ¯åå¸ç®æ³ï¼ä½SHAç®æ³æ¯MD5æ´å®å ¨ï¼å¦SHA-256ãSHA-512çã
MD5ç®æ³æ¯å¦å¯éï¼
MD5ç®æ³æ¯åååå¸ç®æ³ï¼ä¸å¯éï¼æ æ³ä»æè¦å¼è¿ååºåå§æ°æ®ã
MD5ç®æ³å¨å¯ç å¦ä¸çä½ç¨æ¯ä»ä¹ï¼
MD5ç®æ³å¨å¯ç å¦ä¸ç¨äºçææè¦å¼ï¼éªè¯æ°æ®å®æ´æ§ï¼å¯ç åå¨çæ¹é¢ã
ä»£ç æ ·ä¾
Java
private static void md5()
throws NoSuchAlgorithmException, UnsupportedEncodingException {
String[] input = {"Hello", "World"};
// å建ä¸ä¸ªMessageDigestå®ä¾
MessageDigest md = MessageDigest.getInstance("MD5");
// åå¤è°ç¨updateè¾å
¥æ°æ®
for (String s : input) {
md.update(s.getBytes("UTF-8"));
}
// å½è¾å
¥ç»æåï¼è°ç¨digest()æ¹æ³è·å¾byte[]æ°ç»è¡¨ç¤ºçæè¦
byte[] result = md.digest();
// æåï¼æå®è½¬æ¢ä¸ºåå
è¿å¶çå符串ã
// 16 bytes: 68e109f0f40ca72a15e05cc22786f8e6
String rs = HexFormat.of().formatHex(result);
System.out.println(rs);
Preconditions.checkArgument(
StringUtils.equals(rs, "68e109f0f40ca72a15e05cc22786f8e6"), "ä¸ç¬¦åææ");
}
JavaScript(CryptoJS)
const hasher = CryptoJS.algo.MD5.create(); // [!code error]
hasher.reset();
hasher.update('abc');
hasher.update('def');
const hash = hasher.finalize();
return hash + '';
Python
import hashlib
def md5_test1():
md5 = hashlib.new('md5', 'I love python!'.encode('utf-8'))
print(md5.hexdigest())
def md5_test2():
md5 = hashlib.md5()
md5.update('I love '.encode('utf-8'))
md5.update('python!'.encode('utf-8'))
print(md5.hexdigest())
if __name__ == '__main__':
md5_test1() # 21169ee3acd4a24e1fcb4322cfd9a2b8
md5_test2() # 21169ee3acd4a24e1fcb4322cfd9a2b8
MD5 鲿¢å½©è¹è¡¨æ»å»
使ç¨åå¸å£ä»¤æ¶ï¼è¿è¦æ³¨æé²æ¢å½©è¹è¡¨æ»å»ã
å¦æåªæ¿å°MD5ï¼ä»MD5忍ææå£ä»¤ï¼åªè½ä½¿ç¨æ´åç©·ä¸¾çæ¹æ³ã ç¶èæ´åç©·ä¸¾ä¼æ¶è大éçç®ååæ¶é´ã使¯ï¼å¦ææä¸ä¸ªé¢å 计ç®å¥½ç常ç¨å£ä»¤åå®ä»¬çMD5çå¯¹ç §è¡¨(å¯¹ç §è¡¨)ï¼å°±å¯ä»¥æ ¹æ®MD5ç´æ¥åæ¥ã
ä¸è¿°ä»£ç æ ·ä¾ï¼ ç»è¿å çæä½çæ¹è¯ï¼ä½¿é»å®¢ç彩è¹è¡¨å¤±æï¼å³ä½¿ç¨æ·ä½¿ç¨å¸¸ç¨å£ä»¤ï¼ä¹æ æ³ä»MD5忍åå§å£ä»¤ã
/**
* å ççç®çå¨äºä½¿é»å®¢ç彩è¹è¡¨å¤±æï¼å³ä½¿ç¨æ·ä½¿ç¨å¸¸ç¨å£ä»¤ï¼ä¹æ æ³ä»MD5忍åå§å£ä»¤ã
*/
private static void md5WithSalt(String salt)
throws NoSuchAlgorithmException, UnsupportedEncodingException {
String[] input = {salt, "Hello", "World"};
// å建ä¸ä¸ªMessageDigestå®ä¾
MessageDigest md = MessageDigest.getInstance("MD5");
// åå¤è°ç¨updateè¾å
¥æ°æ®
for (String s : input) {
md.update(s.getBytes("UTF-8"));
}
// å½è¾å
¥ç»æåï¼è°ç¨digest()æ¹æ³è·å¾byte[]æ°ç»è¡¨ç¤ºçæè¦
byte[] result = md.digest();
// æåï¼æå®è½¬æ¢ä¸ºåå
è¿å¶çå符串ã
// 16 bytes: 68e109f0f40ca72a15e05cc22786f8e6
String rs = HexFormat.of().formatHex(result);
System.out.println(rs);
Preconditions.checkArgument(
StringUtils.equals(rs, "20fd53312bf2f702d26087a204e6e0b5"), "ä¸ç¬¦åææ");
}
SHA
å®å ¨æ£åç®æ³ï¼è±è¯ï¼Secure Hash Algorithmï¼ç¼©å为SHAï¼æ¯ä¸ä¸ªå¯ç æ£å彿°å®¶æï¼ æ¯FIPSæè®¤è¯çå®å ¨æ£åç®æ³ã è½è®¡ç®åºä¸ä¸ªæ°åæ¶æ¯æå¯¹åºå°çï¼é¿åº¦åºå®çå符串ï¼åç§°æ¶æ¯æè¦ï¼çç®æ³ã
ä¸è¥è¾å ¥çæ¶æ¯ä¸åï¼å®ä»¬å¯¹åºå°ä¸ååç¬¦ä¸²çæºçå¾é«ã
ç®åSHAæäºä¸ªç®æ³ï¼å嫿¯SHA-1ãSHA-224ãSHA-256ãSHA-384ï¼åSHA-512ï¼ ç±ç¾å½å®å ¨å±ï¼NSAï¼æè®¾è®¡ï¼å¹¶ç±ç¾å½å½å®¶æ å䏿æ¯ç ç©¶é¢ï¼NISTï¼åå¸ï¼ä¹æ¯ç¾å½çæ¿åºæ åï¼ååè ææ¶å¹¶ç§°ä¸ºSHA-2ã
SHA-1乿¯ä¸ç§åå¸ç®æ³ï¼å®çè¾åºæ¯160 bitsï¼å³20åèã
SHAå®¶æ
SHAå®¶æåä¸ªåæ°å¯¹æ¯å¦ä¸ï¼

ä»£ç æ ·ä¾
SHA-1
20 bytes
private static void sha1() throws Exception {
String[] input = {"Hello", "World"};
// å建ä¸ä¸ªMessageDigestå®ä¾:
MessageDigest md = MessageDigest.getInstance("SHA-1");
// åå¤è°ç¨updateè¾å
¥æ°æ®
for (String s : input) {
md.update(s.getBytes("UTF-8"));
}
byte[] result = md.digest();
// 20 bytes
Preconditions.checkArgument(result.length == 20, "ä¸ç¬¦åææ");
String rs = HexFormat.of().formatHex(result);
System.out.println(rs);
Preconditions.checkArgument(
StringUtils.equals(rs, "db8ac1c259eb89d4a131b253bacfca5f319d54f2"), "ä¸ç¬¦åææ");
}
SHA-224
224 / 8 = 28 bytes
private static void sha224() throws Exception {
// 注åBouncyCastle.
Security.addProvider(new BouncyCastleProvider());
String[] input = {"Hello", "World"};
// å建ä¸ä¸ªMessageDigestå®ä¾
MessageDigest md = MessageDigest.getInstance("SHA-224");
// åå¤è°ç¨updateè¾å
¥æ°æ®
for (String s : input) {
md.update(s.getBytes("UTF-8"));
}
byte[] result = md.digest();
// 224 / 8 = 28 bytes
Preconditions.checkArgument(result.length == 28, "ä¸ç¬¦åææ");
String rs = HexFormat.of().formatHex(result);
System.out.println(rs);
Preconditions.checkArgument(
StringUtils.equals(rs, "b07a0b24d54879214f2361e0a1ac320442fa4e53a0f607d126fbfb8a"), "ä¸ç¬¦åææ");
}
SHA-256
256/8 = 32 bytes
private static void sha256() throws Exception {
String[] input = {"Hello", "World"};
// å建ä¸ä¸ªMessageDigestå®ä¾:
MessageDigest md = MessageDigest.getInstance("SHA-256");
// åå¤è°ç¨updateè¾å
¥æ°æ®
for (String s : input) {
md.update(s.getBytes("UTF-8"));
}
byte[] result = md.digest();
// 32 bytes
Preconditions.checkArgument(result.length == 32, "ä¸ç¬¦åææ");
String rs = HexFormat.of().formatHex(result);
System.out.println(rs);
Preconditions.checkArgument(
StringUtils.equals(rs, "872e4e50ce9990d8b041330c47c9ddd11bec6b503ae9386a99da8584e9bb12c4"), "ä¸ç¬¦åææ");
}
SHA-384
384/8 = 48 bytes
private static void sha384() throws Exception {
String[] input = {"Hello", "World"};
// å建ä¸ä¸ªMessageDigestå®ä¾:
MessageDigest md = MessageDigest.getInstance("SHA-384");
// åå¤è°ç¨updateè¾å
¥æ°æ®
for (String s : input) {
md.update(s.getBytes("UTF-8"));
}
byte[] result = md.digest();
// 48 bytes
Preconditions.checkArgument(result.length == 48, "ä¸ç¬¦åææ");
String rs = HexFormat.of().formatHex(result);
System.out.println(rs);
Preconditions.checkArgument(
StringUtils.equals(rs, "293cd96eb25228a6fb09bfa86b9148ab69940e68903cbc0527a4fb150eec1ebe0f1ffce0bc5e3df312377e0a68f1950a"), "ä¸ç¬¦åææ");
}
SHA-512
512/8 = 64 bytes
private static void sha512() throws Exception {
String[] input = {"Hello", "World"};
// å建ä¸ä¸ªMessageDigestå®ä¾:
MessageDigest md = MessageDigest.getInstance("SHA-512");
// åå¤è°ç¨updateè¾å
¥æ°æ®
for (String s : input) {
md.update(s.getBytes("UTF-8"));
}
byte[] result = md.digest();
// 64 bytes
Preconditions.checkArgument(result.length == 64, "ä¸ç¬¦åææ");
String rs = HexFormat.of().formatHex(result);
System.out.println(rs);
Preconditions.checkArgument(
StringUtils.equals(rs, "8ae6ae71a75d3fb2e0225deeb004faf95d816a0a58093eb4cb5a3aa0f197050d7a4dc0a2d5c6fbae5fb5b0d536a0a9e6b686369fa57a027687c3630321547596"), "ä¸ç¬¦åææ");
}
CryptoJS
return CryptoJS.SHA256('a12345678');
return CryptoJS.SHA384('a12345678');
return CryptoJS.SHA512('a12345678');
è¯è®ºåº