數據摘要算法總結

概述
數據摘要算法具備不可逆性, 其主要功能有數據簽名, 數據完整性校驗等. 下面介紹常見的數據摘要算法:java

CRCpython

CRC(Cyclic Redundancy Check,循環冗餘校驗)算法出現時間較長,應用也十分普遍,尤爲是通信領域,如今應用最多的就是 CRC32 算法,它產生一個4字節(32位)的校驗值,通常是以8位十六進制數,如FA 12 CD 45等。CRC算法的優勢在於簡便、速度快,嚴格的來講,CRC更應該被稱爲數據校驗算法,但其功能與數據摘要算法相似,所以也做爲測試的可選算法。算法

MD5安全

Message-Digest Algorithm 5,消息摘要算法版本5。由Ron Rivest(RSA公司)在1992年提出,目前被普遍應用於數據完整性校驗、數據(消息)摘要、數據加密等。MD二、MD四、MD5 都產生16字節(128位)的校驗值,通常用32位十六進制數表示。MD2的算法較慢但相對安全,MD4速度很快,但安全性降低,MD5比MD4更安全、速度更快。工具

SHA測試

SHA(Secure Hash Algorithm)是由美國專門制定密碼算法的標準機構——美國國家標準技術研究院(NIST)制定的,SHA系列算法的摘要長度分別爲:SHA爲20字節(160位)、SHA256爲32字節(256位)、 SHA384爲48字節(384位)、SHA512爲64字節(512位),因爲它產生的數據摘要的長度更長,所以更難以發生碰撞,所以也更爲安全,它是將來數據摘要算法的發展方向。因爲SHA系列算法的數據摘要長度較長,所以其運算速度與MD5相比,也相對較慢。
目前SHA1的應用較爲普遍,主要應用於CA和數字證書中,另外在目前互聯網中流行的BT軟件中,也是使用SHA1來進行文件校驗的。ui

Crc32this

CRC32 Cyclical Redundancy Check 循環冗餘檢查, 是一種數據傳輸檢錯功能。經常使用在在數據存儲和數據通信領域, CRC32 Cyclical Redundancy Check 循環冗餘檢查, 是一種數據傳輸檢錯功能。經常使用在 在數據存儲和數據通信領域。加密

常見應用code

著名的通信協議X.25的FCS(幀檢錯序列)採用的是CRC-CCITT
ARJ、LHA等壓縮工具軟件採用的是CRC32
磁盤驅動器的讀寫採用了CRC16
通用的圖像存儲格式GIF、TIFF等也都用CRC做爲檢錯手段
本質

是模-2除法的餘數,採用的除數不一樣,CRC的類型也就不同。一般,CRC的除數用生成多項式來表示。最經常使用的CRC碼的生成多項式如表1所示。
CRC-32: x^32 + x^26 + x^23 + x^22 + x^16 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

Adler32

Adler-32是Mark Adler發明的校驗和算法,和32位CRC校驗算法同樣,都是保護數據防止意外更改的算法,可是這個算法較容易被僞造,因此是不安全的保護措施。可是比CRC好點的是,它計算的很快。這個算法那是從Fletcher校驗和算法中修改過來的,原始的算法形式略快,可是可依賴性並不高。

Adler-32的一種滾動哈希版本被用在了rsync工具 Adler-32經過求解兩個16位的數值A、B實現,並將結果連結成一個32位整數。A就是字符串中每一個字節的和,而B是A在相加時每一步的階段值之和。在Adler-32開始運行時,A初始化爲1,B初始化爲0,最後的校驗和要模上65521(繼216以後的最小素數)。

A = 1 + D1 + D2 + ... + Dn (mod 65521)
B = (1 + D1) + (1 + D1 + D2) + ... + (1 + D1 + D2 + ... + Dn) (mod 65521)
   = n×D1 + (n-1)×D2 + (n-2)×D3 + ... + Dn + n (mod 65521)
Adler-32(D) = B × 65536 + A

其中D爲字符串的字節,n是D的字節長度。

綜合應用

對用戶手機設備惟一碼加密:
Python版:

#!/usr/bin/env python
import zlib,base64
def diu2pid(diu, cpcode):
    row = '%s.%s' % (base64.b64encode(diu), cpcode.upper())
    a = zlib.crc32(row)
    b = zlib.adler32(row, 0) & 0xffffffff
    return a << 32 | b & 0x7fffffffffffffff
    
if __name__ == '__main__':
    diu = '866100020117496'
    cpcode = 'XXX'
    print diu2pid(diu, cpcode)

Java版:

public BigInteger toPid() {
  String base64Uuid = new String(Base64.encodeBase64(uuid.getBytes()));
  String key = String.format("%s.%s", base64Uuid, this.cpcode.toUpperCase());
  
  CRC32 crcChecksum = new CRC32();
  crcChecksum.update(key.getBytes());

  BigInteger crcValue = new BigInteger(String.format("%d", crcChecksum.getValue()));
  Adler32 adlerChecksum = createAdler32Checksum(0);
  adlerChecksum.update(key.getBytes());

  BigInteger adlerValue = new BigInteger(String.format("%d", adlerChecksum.getValue()));
  BigInteger pid = crcValue.shiftLeft(32).or(adlerValue).and(new BigInteger("7FFFFFFFFFFFFFFF", 16));
  return pid;
}
相關文章
相關標籤/搜索