Scrypt算法

看了一圈觉得还是WikiPedia的比较通俗靠谱:

Overview

The large memory requirements of scrypt come from a large vector of pseudorandom bit strings that are generated as part of the algorithm. Once the vector is generated, the elements of it are accessed in a pseudo-random order and combined to produce the derived key. A straightforward implementation would need to keep the entire vector in RAM so that it can be accessed as needed.

Because the elements of the vector are generated algorithmically, each element could be generated on the fly as needed, only storing one element in memory at a time and therefore cutting the memory requirements significantly. However, the generation of each element is intended to be computationally expensive, and the elements are expected to be accessed many times throughout the execution of the function. Thus there is a significant trade-off in speed in order to get rid of the large memory requirements.

This sort of time–memory trade-off often exists in computer algorithms: speed can be increased at the cost of using more memory, or memory requirements decreased at the cost of performing more operations and taking longer. The idea behind scrypt is to deliberately make this trade-off costly in either direction. Thus an attacker could use an implementation that doesn’t require many resources (and can therefore be massively parallelized with limited expense) but runs very slowly, or use an implementation that runs more quickly but has very large memory requirements and is therefore more expensive to parallelize.

Algorithm

Scrypt算法_第1张图片
The algorithm includes the following parameters:

  1. Passphrase - The string of characters to be hashed.
  2. Salt - A string of characters that modifies the hash to protect against Rainbow table attacks
  3. N - CPU/memory cost parameter.
  4. p - Parallelization parameter; a positive integer satisfying p ≤ (232− 1) * hLen / MFLen.
  5. dkLen - Intended output length in octets of the derived key; a positive integer satisfying dkLen ≤ (232− 1) * hLen.
  6. r - The blocksize parameter, which fine-tunes sequential memory read size and performance. 8 is commonly used.
  7. hLen - The length in octets of the hash function (32 for SHA256).
  8. MFlen - The length in octets of the output of the mixing function (SMix below). Defined as r * 128 in RFC7914.
Function scrypt
   Inputs:
      Passphrase:                Bytes    string of characters to be hashed
      Salt:                      Bytes    random salt
      CostFactor (N):            Integer  CPU/memory cost parameter
      BlockSizeFactor (r):       Integer  blocksize parameter (8 is commonly used)
      ParallelizationFactor (p): Integer  Parallelization parameter. (1..232-1 * hLen/MFlen)
      DesiredKeyLen:             Integer  Desired key length in bytes
   Output:
      DerivedKey:                Bytes    array of bytes, DesiredKeyLen long

   Step 1. Generate expensive salt
   blockSize ← 128*BlockSizeFactor  //Length (in bytes) of the SMix mixing function output (e.g. 128*8 = 1024 bytes)

   Use PBKDF2 to generate initial 128*BlockSizeFactor*p bytes of data (e.g. 128*8*3 = 3072 bytes)
   Treat the result as an array of p elements, each entry being blocksize bytes (e.g. 3 elements, each 1024 bytes)
   [B0...Bp−1] ← PBKDF2HMAC-SHA256(Passphrase, Salt, 1, blockSize*ParallelizationFactor)

   Mix each block in B 2CostFactor times using ROMix function (each block can be mixed in parallel)
   for i ← 0 to p-1 do
      Bi ← ROMix(Bi, 2CostFactor)

   All the elements of B is our new "expensive" salt
   expensiveSalt ← B0∥B1∥B2∥ ... ∥Bp-1  //where ∥ is concatenation

   Step 2. Use PBKDF2 to generate the desired number of bytes, but using the expensive salt we just generated
   return PBKDF2HMAC-SHA256(Passphrase, expensiveSalt, 1, DesiredKeyLen);
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
      //Convert first 8-bytes of the last 64-byte block of X to a UInt64, assuming little endian (Intel) format
      j ← Integerify(X) mod N 
      X ← BlockMix(X xor Vj)

   return X
Where Integerify is a bijective function from {0, 1}k to {0,...,2k− 1}.
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 chucks
    [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
Where Salsa20/8 is the 8-round version of Salsa20.

More

  1. Litecoin - a lite version of Bitcoin. Launched!:莱特币创始人发表在bitcointalk.org上的帖子,因为莱特币没有白皮书,则莱特币创始人李启威(英文名字为Charlie lee)发表在bitcointalk.org上的帖子姑且算是个白皮书。
  2. Tenebrix, a CPU-friendly, GPU-hostile cryptocurrency:介绍Tenebrix的帖子。
  3. http://www.tarsnap.com/scrypt.html:介绍Scrypt算法的主页。
  4. https://datatracker.ietf.org/doc/rfc7914/?include_text=1:Scrypt算法的标准文档。
  5. crypto/scrypt/scrypt.go:Scrypt算法的Go语言实现代码。

你可能感兴趣的:(密码学,2018,blockchain,共识算法)