密碼學系列之:加密貨幣中的scrypt演算法

flydean 發表於 2021-10-14
演算法 加密

簡介

為了抵禦密碼破解,科學家們想出了很多種方法,比如對密碼進行混淆加鹽操作,對密碼進行模式變換和組合。但是這些演算法逐漸被一些特製的ASIC處理器打敗,這些ASIC處理器不做別的,就是專門來破解你的密碼或者進行hash運算。

最有名的當然是比特幣了,它使用的是為人詬病的POW演算法,誰的算力高,誰就可以挖礦,這樣就導致了大量無意義的礦機的產生,這些礦機什麼都不能幹,就算是用來算hash值。結果浪費了大量的電力。

普通人更是別想加入這個只有巨頭才能擁有的賽道,如果你想用一個普通的PC機來挖礦,那麼我估計你挖到礦的機率可能跟被隕石砸中差不多。

為了抵禦這種CPU為主的密碼加密方式,科學家們發明了很多其他的演算法,比如需要佔用大量記憶體的演算法,因為記憶體不像CPU可以瘋狂提速,所以限制了很多暴力破解的場景,今天要將的scrypt演算法就是其中一種,該演算法被應用到很多新的加密貨幣挖礦體系中,用以表示他們挖礦程式的公平性。

scrypt演算法

scrypt是一種密碼衍生演算法,它是由Colin Percival建立的。使用scrypt演算法來生成衍生key,需要用到大量的記憶體。scrypt演算法在2016年作為RFC 7914標準釋出。

密碼衍生演算法主要作用就是根據初始化的主密碼來生成系列的衍生密碼。這種演算法主要是為了抵禦暴力破解的攻擊。通過增加密碼生成的複雜度,同時也增加了暴力破解的難度。

但是和上面提到的原因一樣,之前的password-based KDF,比如PBKDF2雖然提高了密碼生成的遍歷次數,但是它使用了很少的記憶體空間。所以很容易被簡單的ASIC機器破解。scrypt演算法就是為了解決這樣的問題出現的。

scrypt演算法詳解

scrypt演算法會生成非常大的偽隨機數序列,這個隨機數序列會被用在後續的key生成過程中,所以一般來說需要一個RAM來進行儲存。這就是scrypt演算法需要大記憶體的原因。

接下我們詳細分析一下scrypt演算法,標準的Scrypt演算法需要輸入8個引數,如下所示:

  • Passphrase: 要被hash的輸入密碼
  • Salt: 對密碼保護的鹽,防止彩虹表攻擊
  • CostFactor (N): CPU/memory cost 引數,必須是2的指數(比如: 1024)
  • BlockSizeFactor (r): blocksize 引數
  • ParallelizationFactor (p): 並行引數
  • DesiredKeyLen (dkLen): 輸出的衍生的key的長度
  • hLen: hash函式的輸出長度
  • MFlen: Mix函式的輸出長度

這個函式的輸出就是DerivedKey。

首先我們需要生成一個expensiveSalt。首先得到blockSize:

blockSize = 128*BlockSizeFactor 

然後使用PBKDF2生成p個blockSize,將這p個block組合成一個陣列:

[B0...Bp−1] = PBKDF2HMAC-SHA256(Passphrase, Salt, 1, blockSize*ParallelizationFactor)

使用ROMix對得到的block進行混合:

   for i ← 0 to p-1 do
      Bi ← ROMix(Bi, CostFactor)

將B組合成新的expensiveSalt:

expensiveSalt ← B0∥B1∥B2∥ ... ∥Bp-1

接下來使用PBKDF2和新的salt生成最終的衍生key:

return PBKDF2HMAC-SHA256(Passphrase, expensiveSalt, 1, DesiredKeyLen);

下面是ROMix函式的虛擬碼:

Function ROMix(Block, Iterations)

   Create Iterations copies of X
   X ← Block
   for i ← 0 to Iterations−1 do
      Vi ← X
      X ← BlockMix(X)

   for i ← 0 to Iterations−1 do
      j ← Integerify(X) mod Iterations 
      X ← BlockMix(X xor Vj)

   return X

其中BlockMix的虛擬碼如下:

Function BlockMix(B):

    The block B is r 128-byte chunks (which is equivalent of 2r 64-byte chunks)
    r ← Length(B) / 128;

    Treat B as an array of 2r 64-byte chunks
    [B0...B2r-1] ← B

    X ← B2r−1
    for i ← 0 to 2r−1 do
        X ← Salsa20/8(X xor Bi)  // Salsa20/8 hashes from 64-bytes to 64-bytes
        Yi ← X

    return ← Y0∥Y2∥...∥Y2r−2 ∥ Y1∥Y3∥...∥Y2r−1

scrypt的使用

Scrypt被用在很多新的POW的虛擬貨幣中,比如Tenebrix、 Litecoin 和 Dogecoin。感興趣的朋友可以關注一下。

本文已收錄於 http://www.flydean.com/42-scrypt/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!