コンテンツにスキップ

scrypt

出典: フリー百科事典『ウィキペディア(Wikipedia)』
scrypt
一般
設計者 コリン・パーシバル英語版
初版発行日 2009
暗号詳細
ダイジェスト長 可変
ブロック長 可変
ラウンド数 可変

暗号理論において、scrypt[注釈 1]は、2009年3月コリン・パーシバル英語版によって作成されたパスワードベースの鍵導出関数である[注釈 2][2][3]。このアルゴリズムは特に大規模なカスタムハードウェア攻撃英語版の実行時に大量のメモリが必要になるようにし、そのコストが高くなるように設計されている。2016年にscryptアルゴリズムはIETFによってRFC 7914として公開された[4]。scryptの簡素化されたバージョンは多くの暗号通貨プルーフ・オブ・ワークスキームとして使用されている。最初はArtForzと名乗る匿名のプログラマーによってTenebrixに実装され、その後すぐにFairbrixとライトコインにも実装された[5]

導入

[編集]

パスワードベースの鍵導出関数は一般的に多くの計算資源が必要になるように設計されているので、計算に比較的長い時間がかかる[注釈 3]。正しいユーザーは認証などの操作ごとにこれを1回だけ実行するので、必要な時間は僅かである。しかし、総当たり攻撃では操作を何十億回も実行する必要がある可能性が高く、その時点で必要な時間が無視できないほどになり、理想的には途方もない時間が必要となる。

RSAセキュリティによるPBKDF2などの以前のパスワードベースの鍵導出関数は、要求される計算資源が比較的低く、実行に綿密なハードウェアや大量のメモリを必要としない。そのため、ASICFPGAなどのハードウェアに簡単かつ安価に実装することができる。これによって、十分な計算資源を持つ攻撃者は、数百から数千のハードウェアにアルゴリズムの実装を構築し、それぞれが鍵空間の異なるサブセットを検索することで、大規模な並列攻撃を始めることができる。これは総当たり攻撃を完了するのに必要な時間を利用可能な実装で割ることにより、必要な時間を妥当なものに引き下げる可能性が非常に高い。

scrypt関数はアルゴリズムの計算資源要求を引き上げることによって、このような試みを阻止するように設計されている。具体的には、このアルゴリズムは他のパスワードベースの鍵導出関数と比較して大量のメモリを使用するように設計されており[6]、ハードウェア実装のサイズとコストが遥かに高くなるので、攻撃者が実行可能な並列処理の量が制限される。

概要

[編集]

scryptが多くのメモリを必要とすることはアルゴリズムの一部として生成される擬似ランダムビット文字列の大きなベクターに由来する。ベクターが一度生成されると、派生鍵を生成するためにその要素に対して擬似ランダムな順序でアクセスと結合が行われる。単純な実装では、必要に応じてアクセスできるように、ベクター全体をRAMに保持する必要がある。

ベクターの要素はアルゴリズムで生成されるので、必要に応じて各要素をオンザフライで生成でき、一度に1つの要素だけをメモリに格納できるので、メモリ使用量が大幅に削減される。しかし、各要素の生成には多くの計算資源を必要とすることを意図しており、要素は関数の実行中に何度もアクセスされることが予想される。したがって、メモリの使用量を減らすには速度に大きなトレードオフがある。

この種の時間とメモリのトレードオフは、多くのコンピューターアルゴリズムに存在する。速度はより多くのメモリを使用することで上げることができ、メモリ使用量はより多くの操作を実行して長い時間を必要とすることで減らすことができる。scryptの背後にある考え方は、このトレードオフを意図的にどちらも高価なものにすることである。したがって、攻撃者は限られた費用で大規模な並列化が可能な多くの計算資源を必要としない実装を使用する可能性があるが、これの実行速度は非常に遅くなる。または、高速に実行できる実装を使用する場合は、大量のメモリが必要となることから並列化のコストが高価になる。

アルゴリズム

[編集]
Function scrypt
   Inputs: このアルゴリズムには次のパラメーターが含まれている:
      Passphrase:                Bytes    ハッシュ化する文字列
      Salt:                      Bytes    レインボーテーブル攻撃から保護するためにハッシュを変更するランダムな文字列
      CostFactor (N):            Integer  CPU/メモリコストパラメーター - 2の累乗でなければならない(1024など)
      BlockSizeFactor (r):       Integer  ブロックサイズパラメーター、シーケンシャルメモリ読み取りサイズと性能を微調整する(8が一般的)
      ParallelizationFactor (p): Integer  並列化パラメーター。(1 .. 232-1 * hLen/MFlen)
      DesiredKeyLen (dkLen):     Integer  必要な鍵の長さ(バイト単位、派生鍵のオクテット単位の意図した出力長、dkLen ≤ (232− 1) * hLenを満たす正の整数。)
      hLen:                      Integer  ハッシュ関数のオクテット単位の長さ(SHA256の場合は32)。
      MFlen:                     Integer  混合関数(以下のSMix)のオクテット単位の出力長。RFC7914でr * 128と定義されている。
   Output:
      DerivedKey:                Bytes    バイト配列、長さはDesiredKeyLen

   ステップ1. 高価なソルトを生成する
   blockSize ← 128*BlockSizeFactor  // バイト単位のSMix混合関数の出力長(例えば128*8 = 1024バイト)

   PBKDF2を使用して最初の128*BlockSizeFactor*pバイトのデータを生成する(例えば128*8*3 = 3072バイト)
   結果をp個の要素を持つ配列として扱う。各エントリーはblocksizeバイトである(例えば3要素で各エントリーは1024バイト)
   [B0...Bp−1] ← PBKDF2HMAC-SHA256(Passphrase, Salt, 1, blockSize*ParallelizationFactor)

   ROMix関数を使用して各ブロックをB Costfactor回混合する(各ブロックは並列で混合できる)
   for i ← 0 to p-1 do
      Bi ← ROMix(Bi, CostFactor)

   Bの全要素が新しい「高価な」ソルトである
   expensiveSalt ← B0∥B1∥B2∥ ... ∥Bp-1  // ∥は連結を意味する
 
   ステップ2. PBKDF2を使用して目的のバイト数を生成するが、生成した高価なソルトを使用する
   return PBKDF2HMAC-SHA256(Passphrase, expensiveSalt, 1, DesiredKeyLen);

PBKDF2(P, S, c, dkLen)表記はRFC 2898で定義されており、cは反復回数である。

この表記はc = 1でPBKDF2の使用法を指定するためにRFC 7914で使用されている。

Function ROMix(Block, Iterations)

   XIterationsコピーを作成する
   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

RFC 7914ではIntegerify(X)をXの最後の64バイトをリトルエンディアン整数A1として解釈した結果として定義している。

Iterationsは2のN乗と等しいので、Xの最後の64バイトのうち最初のCeiling(N / 8)バイトだけがリトルエンディアン整数A2として解釈され、Integerify(X) mod Iterations = A1 mod Iterations = A2 mod Iterationsを計算するために実際に必要となる。

Function BlockMix(B):

    ブロックBはrの128バイトのチャンクである(これは2rの64バイトのチャンクに相当します)
    r ← Length(B) / 128;

    Bを2rの64バイトチャンクの配列として扱う
    [B0...B2r-1] ← B

    X ← B2r−1
    for i ← 0 to 2r−1 do
        X ← Salsa20/8(X xor Bi)  // 64バイトから64バイトのSalsa20/8ハッシュ
        Yi ← X

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

Salsa20/8Salsa20の8ラウンドバージョンである。

暗号通貨での使用

[編集]

Scryptはプルーフ・オブ・ワークアルゴリズムとして多くの暗号通貨で使用されている。最初は2011年9月にTenebrixに実装され、scryptアルゴリズムを採用したライトコインドージコインの基礎となった[7][8]。scryptを使用する暗号通貨の採掘は、Graphics Processing Unit(GPU)がCPUと比べて処理能力が大幅に高い傾向があることから、GPUで実行されることが多い[9]。これは2013年11月12月にこれらの暗号通貨の価格が上昇した際に、ハイエンドGPUが不足したことにつながった[10]

2014年5月時点で特別なASIC採掘ハードウェアがscryptベースの暗号通貨で利用することができる[要出典]

ユーティリティ

[編集]

scryptユーティリティは2009年5月にコリン・パーシバルによってscrypt鍵導出関数のデモンストレーションとして作成された[2][3]。これは殆どのLinuxディストリビューションとBSDディストリビューションで利用することができる。

関連項目

[編集]

脚注

[編集]

注釈

[編集]
  1. ^ "ess crypt"と発音する[1]
  2. ^ 元々はオンラインバックアップサービスのTarsnap英語版向けに作成された。
  3. ^ 数百ミリ秒程度。

出典

[編集]
  1. ^ Colin Percival”. Twitter. 17 February 2019時点のオリジナルよりアーカイブ2022年11月11日閲覧。
  2. ^ a b The scrypt key derivation function”. Tarsnap. 21 January 2014閲覧。
  3. ^ a b SCRYPT(1) General Commands Manual”. Debian Manpages. 2 March 2022閲覧。
  4. ^ The scrypt Password-Based Key Derivation Function”. RFC Editor. 13 December 2021閲覧。
  5. ^ Alec Liu. “Beyond Bitcoin: A Guide to the Most Promising Cryptocurrencies”. 2022年11月11日閲覧。
  6. ^ Percival, Colin. “Stronger Key Derivation Via Sequential Memory-Hard Functions”. 2022年11月11日閲覧。
  7. ^ Andreas M. Antonopoulos (3 December 2014). Mastering Bitcoin: Unlocking Digital Cryptocurrencies. O'Reilly Media. pp. 221, 223. ISBN 9781491902646. https://books.google.com/books?id=IXmrBQAAQBAJ&pg=PA221 
  8. ^ History of cryptocurrency”. 11 June 2016時点のオリジナルよりアーカイブ。27 June 2014閲覧。
  9. ^ Roman Guelfi-Gibbs. Litecoin Scrypt Mining Configurations for Radeon 7950. Amazon Digital Services. https://www.amazon.com/Litecoin-Scrypt-Mining-Configurations-Radeon-ebook/dp/B00E2RT1I4 
  10. ^ Joel Hruska (10 December 2013). “Massive surge in Litecoin mining leads to graphics card shortage”. ExtremeTech. 2022年11月11日閲覧。

外部リンク

[編集]