Digest::SHA - Perl 擴充套件,用於 SHA-1/224/256/384/512
在程式中
# Functional interface
use Digest::SHA qw(sha1 sha1_hex sha1_base64 ...);
$digest = sha1($data);
$digest = sha1_hex($data);
$digest = sha1_base64($data);
$digest = sha256($data);
$digest = sha384_hex($data);
$digest = sha512_base64($data);
# Object-oriented
use Digest::SHA;
$sha = Digest::SHA->new($alg);
$sha->add($data); # feed data into stream
$sha->addfile(*F);
$sha->addfile($filename);
$sha->add_bits($bits);
$sha->add_bits($data, $nbits);
$sha_copy = $sha->clone; # make copy of digest object
$state = $sha->getstate; # save current state to string
$sha->putstate($state); # restore previous $state
$digest = $sha->digest; # compute digest
$digest = $sha->hexdigest;
$digest = $sha->b64digest;
從命令列
$ shasum files
$ shasum --help
# Functional interface only
use Digest::SHA qw(hmac_sha1 hmac_sha1_hex ...);
$digest = hmac_sha1($data, $key);
$digest = hmac_sha224_hex($data, $key);
$digest = hmac_sha256_base64($data, $key);
Digest::SHA 是 NIST 安全雜湊標準的完整實作。它為 Perl 程式設計師提供一種便利的方式來計算 SHA-1、SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224 和 SHA-512/256 訊息摘要。此模組可以處理所有類型的輸入,包括部分位元組資料。
Digest::SHA 使用 C 語言撰寫,以提升速度。如果您的平台沒有 C 編譯器,您可以安裝功能相當(但速度慢很多)的 Digest::SHA::PurePerl 模組。
程式設計介面很容易使用:它與 CPAN 的 Digest 模組中找到的介面相同。因此,如果您的應用程式目前使用 Digest::MD5,而您偏好 SHA 的安全性更強,那麼將它們轉換是一件很簡單的事。
此介面提供兩種計算摘要的方式:一次性或分階段。為說明,以下簡短程式使用每種方法來計算「hello world」的 SHA-256 摘要
use Digest::SHA qw(sha256_hex);
$data = "hello world";
@frags = split(//, $data);
# all-at-once (Functional style)
$digest1 = sha256_hex($data);
# in-stages (OOP style)
$state = Digest::SHA->new(256);
for (@frags) { $state->add($_) }
$digest2 = $state->hexdigest;
print $digest1 eq $digest2 ?
"whew!\n" : "oops!\n";
要計算 n 位元訊息的摘要,其中 n 不是 8 的倍數,請使用 add_bits() 方法。例如,考慮由位元串「110」重複 148 次,後接「11」組成的 446 位元訊息。以下是顯示其 SHA-1 摘要的方法
use Digest::SHA;
$bits = "110" x 148 . "11";
$sha = Digest::SHA->new(1)->add_bits($bits);
print $sha->hexdigest, "\n";
請注意,對於較大的位元串,使用雙引數版本 add_bits($data, $nbits) 較為有效率,其中 $data 採用 Perl 字串慣用的封裝二進位格式。
此模組也讓您將中間 SHA 狀態儲存到字串中。getstate() 方法會產生可攜式、人類可讀取的文字,描述運算的目前狀態。您可以在稍後使用 putstate() 還原該狀態,以從計算中斷處繼續。
要查看狀態描述的樣子,只需執行下列動作
use Digest::SHA;
print Digest::SHA->new->add("Shaw" x 1962)->getstate;
作為額外的便利,Digest::SHA 模組提供常式來使用 HMAC-SHA-1/224/256/384/512 演算法計算鍵控雜湊。這些服務僅以函式形式存在,並模仿 sha()、sha_hex() 和 sha_base64() 函式的樣式和行為。
# Test vector from draft-ietf-ipsec-ciph-sha-256-01.txt
use Digest::SHA qw(hmac_sha256_hex);
print hmac_sha256_hex("Hi There", chr(0x0b) x 32), "\n";
Perl 從版本 5.6 開始支援 Unicode 字串。此類字串可能包含寬字元,亦即序數值大於 255 的字元。這可能會對 SHA 等摘要演算法造成問題,因為這些演算法指定在位元組序列上執行。
Digest::SHA 處理 Unicode 字串的規則很容易說明,但可能令人困惑:字串被解釋為位元組值序列,其中每個位元組值等於其對應 Unicode 字元的序數值(即碼點)。這樣一來,Unicode 字串「abc」的摘要值與一般字串「abc」完全相同。
由於寬字元不符合位元組,因此 Digest::SHA 常式在遇到寬字元時會中斷。而如果 Unicode 字串不包含寬字元,則模組會欣然接受。以下程式說明這兩種情況
$str1 = pack('U*', (0..255));
print sha1_hex($str1); # ok
$str2 = pack('U*', (0..256));
print sha1_hex($str2); # croaks
請注意,摘要常式會將 UTF-8 輸入靜默轉換為其在原生編碼中的等效位元組序列(請參閱 utf8::downgrade)。此副作用僅影響 Perl 內部儲存資料的方式,但不會影響資料的實際值。
NIST 承認 Prof. Xiaoyun Wang 的工作構成對 SHA-1 的實際碰撞攻擊。因此,NIST 鼓勵快速採用 SHA-2 雜湊函數(例如 SHA-256),以應用於需要強碰撞阻力的應用程式,例如數位簽章。
ref. http://csrc.nist.gov/groups/ST/hash/statement.html
根據慣例,CPAN Digest 模組不會填充其 Base64 輸出。當將此類摘要提供給預期正確填充 Base64 編碼的其他軟體時,可能會發生問題。
目前,任何必要的填充都必須由使用者執行。幸運的是,這是一個簡單的操作:如果 Base64 編碼摘要的長度不是 4 的倍數,只需在摘要的結尾追加 "=" 字元,直到長度為 4 的倍數。
while (length($b64_digest) % 4) {
$b64_digest .= '=';
}
舉例來說,sha256_base64("abc") 計算結果為
ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0
長度為 43。因此,正確填充的版本為
ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
預設為無。
如果您的 C 編譯器支援 64 位元類型(例如 C99 的long long 或 Microsoft C/C++ 使用的__int64),所有這些函數都可供使用。否則,您將無法執行 SHA-384 和 SHA-512 轉換,這兩個轉換都需要 64 位元運算。
函數樣式
將參數邏輯地串接成單一字串,並傳回其編碼為二進位字串的 SHA-1/224/256/384/512 摘要。
以邏輯方式將參數連接成單一字串,並傳回其 SHA-1/224/256/384/512 摘要,編碼為十六進位字串。
以邏輯方式將參數連接成單一字串,並傳回其 SHA-1/224/256/384/512 摘要,編碼為 Base64 字串。
請務必注意,結果字串不包含 Base64 編碼中常見的填充字元。此遺漏是故意的,目的是為了與 CPAN Digest 模組家族保持相容性。有關詳細資訊,請參閱 "PADDING OF BASE64 DIGESTS"。
OOP 樣式
傳回新的 Digest::SHA 物件。$alg 的允許值為 1、224、256、384、512、512224 或 512256。也可以使用演算法的常見字串表示法(例如 "sha256"、"SHA-384")。如果沒有參數,預設會使用 SHA-1。
以執行個體方法的方式呼叫 new 會將物件重設為與 $alg 相關的初始狀態。如果沒有參數,物件會繼續使用在建立時選取的相同演算法。
此方法的效果與 new($alg) 完全相同。事實上,reset 只是 new 的別名。
傳回此物件的摘要位元數。SHA-1、SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224 和 SHA-512/256 的值分別為 160、224、256、384、512、224 和 256。
傳回此物件的摘要演算法。SHA-1、SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224 和 SHA-512/256 的值分別為 1、224、256、384、512、512224 和 512256。
傳回物件的重複複本。
將參數邏輯性地加入單一字串,並使用它來更新目前的摘要狀態。換句話說,下列陳述具有相同效果
$sha->add("a"); $sha->add("b"); $sha->add("c");
$sha->add("a")->add("b")->add("c");
$sha->add("a", "b", "c");
$sha->add("abc");
傳回值是更新後的物件本身。
透過附加位元到目前的摘要狀態來更新它。傳回值是更新後的物件本身。
第一個形式會導致 $data 的最高有效位元 $nbits 附加到串流。$data 參數採用 Perl 字串使用的慣例二進位格式。
第二個形式採用 ASCII 字串「0」和「1」字元作為其參數。它等於
$sha->add_bits(pack("B*", $bits), length($bits));
因此,下列兩個陳述執行相同動作
$sha->add_bits("111100001010");
$sha->add_bits("\xF0\xA0", 12);
請注意,SHA-1 和 SHA-2 對其內部狀態使用最高有效位元順序。這表示
$sha3->add_bits("110");
等於
$sha3->add_bits("1")->add_bits("1")->add_bits("0");
從 FILE 讀取直到 EOF,並將該資料附加到目前的狀態。傳回值是更新後的物件本身。
讀取 $filename 的內容,並將該資料附加到目前的狀態。傳回值是更新後的物件本身。
預設情況下,$filename 會被單純開啟並讀取;不會使用任何特殊模式或 I/O 規則。若要變更這個設定,請將選用的 $mode 參數設定為下列值之一
"b" read file in binary mode
"U" use universal newlines
"0" use BITS mode
「U」模式仿效 Python 的「通用換行符號」概念,在處理之前,會將 DOS 和 Mac OS 的換行符號內部轉換為 UNIX 換行符號。這樣可以確保在同時處理多個檔案系統時,摘要值的一致性。「U」模式只會影響文字檔,也就是通過 Perl 的 -T 測試的檔案;二進位檔案會在完全不轉換的情況下進行處理。
BITS 模式(「0」)會將 $filename 的內容解譯為一個邏輯位元串流,其中每個 ASCII 的「0」或「1」字元分別代表 0 或 1 位元。所有其他字元都會被忽略。這提供了一個便利的方式來計算部分位元組資料的摘要值,方法是使用檔案,而不是必須撰寫使用 add_bits 方法的獨立程式。
傳回一個字串,其中包含目前 SHA 狀態的可攜式、人類可讀的表示形式。
傳回一個 Digest::SHA 物件,代表 $str 中包含的 SHA 狀態。$str 的格式與方法 getstate 所產生的輸出格式相符。如果以類別方法呼叫,會建立一個新的物件;如果以實例方法呼叫,會將物件重設為 $str 中包含的狀態。
將 getstate 的輸出寫入 $filename。如果參數遺失或等於空字串,狀態資訊將寫入 STDOUT。
傳回一個 Digest::SHA 物件,其結果是針對 $filename 的內容呼叫 putstate 所產生的。如果參數遺失或等於空字串,狀態資訊將從 STDIN 讀取。
傳回編碼為二進位字串的摘要。
請注意,digest 方法是只讀一次的作業。執行過後,Digest::SHA 物件會自動重設,以準備計算另一個摘要值。如果需要保留原始摘要狀態,請呼叫 $sha->clone->digest。
傳回編碼為十六進位字串的摘要。
與 digest 相同,這個方法是只讀一次的作業。如果需要保留原始摘要狀態,請呼叫 $sha->clone->hexdigest。
傳回編碼為 Base64 字串的摘要。
與 digest 相同,這個方法是只讀一次的作業。如果需要保留原始摘要狀態,請呼叫 $sha->clone->b64digest。
請務必注意,結果字串不包含 Base64 編碼中常見的填充字元。此遺漏是故意的,目的是為了與 CPAN Digest 模組家族保持相容性。有關詳細資訊,請參閱 "PADDING OF BASE64 DIGESTS"。
HMAC-SHA-1/224/256/384/512
傳回 $data/$key 的 HMAC-SHA-1/224/256/384/512 摘要,結果編碼成二進制字串。允許多個 $data 參數,但 $key 必須是清單中的最後一個參數。
傳回 $data/$key 的 HMAC-SHA-1/224/256/384/512 摘要,結果編碼成十六進位字串。允許多個 $data 參數,但 $key 必須是清單中的最後一個參數。
傳回 $data/$key 的 HMAC-SHA-1/224/256/384/512 摘要,結果編碼成 Base64 字串。允許多個 $data 參數,但 $key 必須是清單中的最後一個參數。
請務必注意,結果字串不包含 Base64 編碼中常見的填充字元。此遺漏是故意的,目的是為了與 CPAN Digest 模組家族保持相容性。有關詳細資訊,請參閱 "PADDING OF BASE64 DIGESTS"。
安全雜湊標準 (草案 FIPS PUB 180-4) 可在以下位置找到
http://csrc.nist.gov/publications/drafts/fips180-4/Draft-FIPS180-4_Feb2011.pdf
金鑰雜湊訊息驗證碼 (HMAC)
http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
Mark Shelor <mshelor@cpan.org>
作者特別感謝
Gisle Aas
H. Merijn Brand
Sean Burke
Chris Carey
Alexandr Ciornii
Chris David
Jim Doble
Thomas Drugeon
Julius Duque
Jeffrey Friedl
Robert Gilmour
Brian Gladman
Jarkko Hietaniemi
Adam Kennedy
Mark Lawrence
Andy Lester
Alex Muntada
Steve Peters
Chris Skiscim
Martin Thurn
Gunnar Wolf
Adam Woodbury
「透過訓練有素的技術,從如此洶湧的波濤和濃密的黑暗中拯救生命,並將其停泊在如此完美的平靜和如此明亮的光芒中」- 盧克萊修
版權所有 (C) 2003-2022 Mark Shelor
此函式庫是自由軟體;您可以在與 Perl 相同的條款下重新散布或修改它。