JavaScript/Crypto

カテゴリ:Book:JavaScript#Crypto%20

Crypto インタフェースは、暗号論的に強力な疑似乱数ジェネレータを含む、汎用暗号機能へのインタフェースを表します。このジェネレータは真に乱数的な値でシードされます[1]

WebIDL 定義

partial interface mixin WindowOrWorkerGlobalScope {
  [SameObject] readonly attribute Crypto crypto;
};

[Exposed=(Window,Worker)]
interface Crypto {
  [SecureContext] readonly attribute SubtleCrypto subtle;
  ArrayBufferView getRandomValues(ArrayBufferView array);
  [SecureContext] DOMString randomUUID();
};

説明

Crypto インタフェースは、ウェブアプリケーションで暗号操作を行うための主要なエントリーポイントです。window.crypto または self.crypto を通じてアクセスできます。

注意点:

  • 実装は、オペレーティングシステムのエントロピーソース(例:"/dev/urandom")などから高品質のエントロピーを使用して、確立された暗号論的疑似乱数ジェネレータで暗号論的に強力な乱数値を生成する必要があります。
  • この仕様は、暗号論的に強力な乱数値に存在する情報理論的エントロピーの下限を規定していませんが、実装は可能な限り多くのエントロピーを提供するよう最善を尽くすべきです。
  • このインタフェースは、暗号論的に強力な乱数値を取得するための同期メソッドを定義しています。パフォーマンス上の理由とシステムのエントロピーを枯渇させないために、実装は getRandomValues の実装に真の乱数源を使用しないことが推奨されています。代わりに、これらのソースは暗号論的疑似乱数ジェネレータのシードとして使用され、効率的に適切な値を返すことができます。

プロパティとメソッド

静的プロパティ

静的プロパティ
名称解説
arguments 非標準であり、ほとんどの環境で undefined を返します。関数の引数を表す配列風オブジェクトですが、Cryptoオブジェクトでは意味を持ちません。
caller 非標準であり、ほとんどの環境で null を返します。現在の関数を呼び出した関数への参照ですが、Cryptoオブジェクトでは意味を持ちません。
length Cryptoコンストラクタが受け取る引数の数を返します。常に0です。
name Cryptoコンストラクタの名前を返します。常に"Crypto"です。
prototype Cryptoオブジェクトのプロトタイプオブジェクトへの参照です。

静的アクセサ

静的メソッド

インスタンスプロパティ

静的プロパティ
名称解説
Crypto.prototype [ Symbol.toStringTag ] Object.prototype.toString()メソッドで使用される、オブジェクトの既定の文字列表現を指定するシンボルです。Cryptoオブジェクトの場合、"Crypto"という文字列を返します。

インスタンスアクセサ

インスタンスアクセサ
名称解説
get Crypto.prototype.subtle SubtleCrypto インターフェイスを返すアクセサプロパティです。このインターフェイスは、暗号操作のための低レベルのプリミティブを提供します。

subtle 属性は、低レベルの暗号プリミティブとアルゴリズムを提供する SubtleCrypto インタフェースのインスタンスを提供します。

インスタンスメソッド

インスタンスアクセサ
名称解説
constructor() Crypto オブジェクトのインスタンスを生成した関数を返します。
getRandomValues() 暗号論的に強い乱数で指定された配列を入力します。
randomUUID() バージョン 4 の UUID を生成します。

getRandomValues を使用して乱数を生成するプログラム

以下のプログラムは、getRandomValues メソッドを使用して暗号論的に強力な乱数を生成します。

// 8ビット符号なし整数の配列を作成
const array = new Uint8Array(16);

// 配列に暗号論的に強力な乱数を生成
window.crypto.getRandomValues(array);

console.log(array);
// 例: Uint8Array(16) [221, 45, 178, 3, 75, 214, 44, 110, 39, 178, 148, 25, 3, 248, 80, 33]

// 16進数文字列に変換する関数
function bytesToHex(bytes) {
  return Array.from(bytes)
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

console.log(bytesToHex(array));
// 例: "dd2db20344d62c6e27b294190af85021"

このプログラムでは、getRandomValues メソッドを使用して Uint8Array に乱数を生成し、その結果を16進数の文字列に変換しています。

getRandomValues メソッド

getRandomValues メソッドは、暗号論的に強力な乱数値を生成します。以下のように動作します:

  1. array が Int8ArrayUint8ArrayUint8ClampedArrayInt16ArrayUint16ArrayInt32ArrayUint32ArrayBigInt64Array、または BigUint64Array でない場合、TypeMismatchError をスローしてアルゴリズムを終了します。
  2. byteLength を array のバイト長とします。
  3. byteLength が 65536 より大きい場合、QuotaExceededError をスローしてアルゴリズムを終了します。
  4. bytes を長さ byteLength のバイトシーケンスとします。
  5. bytes を暗号論的にセキュアな乱数バイトで埋めます。
  6. bytes を array に書き込みます。
  7. array を返します。

注意: getRandomValues メソッドを使用してキーを生成しないでください。代わりに generateKey メソッドを使用してください。

randomUUID メソッド

randomUUID メソッドは、新しいバージョン4 UUIDを生成し、[RFC4122]のセクション3で説明されているように、その名前空間固有の文字列表現を返します。ランダムUUIDを生成するには:

  1. bytes を長さ 16 のバイトシーケンスとします。
  2. bytes を暗号論的にセキュアな乱数バイトで埋めます。
  3. UUIDバージョンを表す bytes[6] の上位4ビットを 0100 に設定します。
  4. UUIDバリアントを表す bytes[8] の上位2ビットを 10 に設定します。
  5. 以下の文字列連結を返します:
    1. bytes[0]の16進表現, bytes[1]の16進表現, bytes[2]の16進表現, bytes[3]の16進表現,
    2. "-",
    3. bytes[4]の16進表現, bytes[5]の16進表現,
    4. "-",
    5. bytes[6]の16進表現, bytes[7]の16進表現,
    6. "-",
    7. bytes[8]の16進表現, bytes[9]の16進表現,
    8. "-",
    9. bytes[10]の16進表現, bytes[11]の16進表現, bytes[12]の16進表現, bytes[13]の16進表現, bytes[14]の16進表現, bytes[15]の16進表現

ランダムUUIDを生成するアルゴリズムで説明されているステップでは、バイト値の 16進表現 は、ASCII小文字16進数を使用して値を16進数で表現し、2つのASCII小文字16進数に達するまで "0" で左パディングして作成された2文字の文字列です。

randomUUID を使用してUUIDを生成するプログラム

以下のプログラムは、randomUUID メソッドを使用してランダムなUUIDを生成します。

// セキュアコンテキスト(HTTPS)でのみ動作します
function generateUUID() {
  try {
    return window.crypto.randomUUID();
  } catch (e) {
    console.error('randomUUID() はサポートされていないか、セキュアコンテキストでありません:', e);
    return null;
  }
}

const uuid = generateUUID();
console.log(uuid);
// 例: "f7355dc9-cb0c-45c5-9f42-d21f0e1b7131"

// 複数のUUIDを生成
const uuids = Array.from({ length: 5 }, () => generateUUID());
console.log(uuids);
// 例: ["a8a17a1d-4943-4021-9a56-5c2c10d9b507", "c83e1fcf-01ca-47ac-b547-d143d4e14940", ...]

このプログラムでは、randomUUID メソッドを使用して複数のUUIDを生成しています。このメソッドはセキュアコンテキスト(HTTPS)でのみ使用可能です。

getRandomValues を使用してランダムな整数を生成するプログラム

以下のプログラムは、getRandomValues メソッドを使用して特定の範囲内のランダムな整数を生成する関数を実装しています。

// min以上max未満のランダムな整数を生成する関数
function getRandomInt(min, max) {
  const range = max - min;
  
  // 必要なバイト数を計算
  const bytesNeeded = Math.ceil(Math.log2(range) / 8);
  const maxNum = Math.pow(256, bytesNeeded);
  
  // バイト配列を作成
  const byteArray = new Uint8Array(bytesNeeded);
  let randomNum;
  
  // 範囲内の値が得られるまで繰り返す
  do {
    window.crypto.getRandomValues(byteArray);
    
    // バイト配列から数値を構築
    randomNum = 0;
    for (let i = 0; i < byteArray.length; i++) {
      randomNum = (randomNum * 256) + byteArray[i];
    }
    
    randomNum = randomNum % range;
  } while (randomNum >= range);
  
  return min + randomNum;
}

// 使用例
console.log(getRandomInt(1, 100)); // 例: 42
console.log(getRandomInt(1000, 2000)); // 例: 1234

// 複数の乱数を生成
const randomNumbers = Array.from({ length: 10 }, () => getRandomInt(1, 100));
console.log(randomNumbers); // 例: [34, 78, 12, 90, 45, 23, 67, 89, 54, 32]

このプログラムでは、getRandomValues メソッドを使用して、指定された範囲内のランダムな整数を暗号論的に安全な方法で生成しています。

注意点

  • セキュアコンテキスト: randomUUID メソッドや subtle 属性へのアクセスには、セキュアコンテキスト(HTTPS)が必要です。
  • サイズ制限: getRandomValues メソッドは65536バイトを超えるサイズの配列に対して QuotaExceededError をスローします。
  • 配列型: getRandomValues メソッドは、特定の型の ArrayBufferView のみをサポートしています。
  • キー生成: getRandomValues メソッドをキー生成に使用せず、代わりに SubtleCrypto.generateKey メソッドを使用することが推奨されています。
  • ブラウザサポート: すべてのブラウザがすべての機能をサポートしているわけではありません。特に randomUUID は比較的新しいメソッドです。

脚註

  1. Crypto インタフェースは、セキュアな乱数生成や暗号操作を行うために使用されます。

外部リンク

カテゴリ:Book:JavaScript#Crypto%20 カテゴリ:JavaScript カテゴリ:Web API
カテゴリ:Book:JavaScript カテゴリ:JavaScript カテゴリ:Pages using the JsonConfig extension カテゴリ:Web API