ブラウザ暗号の実践:Web Crypto API と国密 SM2/SM3/SM4

前端安全(更新: 2026年5月18日)

なぜブラウザで暗号処理するのか

従来のフローではデータをサーバーに送って暗号化するため、プライバシーリスクがあります。

従来:平文 → ネットワーク → サーバーで暗号化 → 暗号文を返却
リスク:平文の傍受、サーバー側のログ

ブラウザ:平文 → ローカルで暗号化 → 暗号文
利点:平文が端末外に出ない

ToolsKu の 30 以上の暗号ツールはすべてブラウザ内で完結し、アップロードはゼロです。


Web Crypto API:ブラウザ標準の暗号

主な機能

Web Crypto API は W3C 標準で、モダンブラウザはすべて対応しています。

// 機能検出
if (window.crypto?.subtle) {
  // Web Crypto API 利用可能
}
カテゴリ アルゴリズム 鍵長
対称 AES-GCM, AES-CBC, AES-CTR 128/192/256
非対称 RSA-OAEP, RSA-PSS, ECDSA 2048/4096
鍵導出 PBKDF2, HKDF, ECDH -
ハッシュ SHA-1, SHA-256, SHA-384, SHA-512 -
HMAC HMAC(上記ハッシュと組み合わせ) -

AES-256-GCM の実装例

async function aesGcmEncrypt(plaintext: string, password: string) {
  const enc = new TextEncoder();

  // 1. パスワードから鍵を導出(PBKDF2)
  const salt = crypto.getRandomValues(new Uint8Array(16));
  const keyMaterial = await crypto.subtle.importKey(
    'raw', enc.encode(password), 'PBKDF2', false, ['deriveKey']
  );
  const key = await crypto.subtle.deriveKey(
    { name: 'PBKDF2', salt, iterations: 600000, hash: 'SHA-256' },
    keyMaterial,
    { name: 'AES-GCM', length: 256 },
    false,
    ['encrypt']
  );

  // 2. ランダム IV
  const iv = crypto.getRandomValues(new Uint8Array(12));

  // 3. 暗号化
  const ciphertext = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    key,
    enc.encode(plaintext)
  );

  // 4. 連結:salt + iv + ciphertext
  return concatBuffers(salt, iv, ciphertext);
}

セキュリティ上の選択

項目 選択 理由
対称モード AES-GCM(CBC ではない) 認証付き暗号で改ざん検知
鍵導出 PBKDF2 + SHA-256 標準で広くサポート
反復回数 600,000 OWASP 2023 の推奨下限
IV 長 12 バイト(96 ビット) GCM の推奨
Salt 16 バイト乱数 レインボーテーブル対策

国密アルゴリズム:JS 実装の課題

アルゴリズム体系

アルゴリズム 種別 国際標準との対応 ToolsKu
SM2 公開鍵暗号・署名 ECDSA (P-256) sm-crypto
SM3 ハッシュ SHA-256 sm-crypto
SM4 対称暗号 AES-128 sm-crypto

sm-crypto の利用

import { sm2, sm3, sm4 } from 'sm-crypto';

// SM2 鍵ペア生成
const keyPair = sm2.generateKeyPairHex();
// publicKey: keyPair.publicKey (130 hex chars, uncompressed)
// privateKey: keyPair.privateKey (64 hex chars)

// SM2 暗号化(C1C3C4 モード、国密標準)
const cipherMode = 1; // 1 = C1C3C4, 0 = C1C2C3
const ciphertext = sm2.doEncrypt(msg, keyPair.publicKey, cipherMode);

// SM2 復号
const plaintext = sm2.doDecrypt(ciphertext, keyPair.privateKey, cipherMode);

// SM3 ハッシュ
const hash = sm3('message');

// SM4 暗号化(ECB モード)
const key = '0123456789abcdeffedcba9876543210'; // 128-bit hex
const encrypted = sm4.encrypt(msg, key);

性能比較

操作 Web Crypto (AES-256-GCM) sm-crypto (SM4) 倍率
1MB 暗号化 2ms 45ms 22x
1MB 復号 2ms 42ms 21x
鍵生成 0.5ms 3ms 6x

Web Crypto は 20 倍以上高速です。ブラウザネイティブ(C/Rust や HW 加速)に対し、sm-crypto は純 JS の大整数演算のためです。

最適化の方針

  1. Web Worker:SM2/SM4 を Worker に逃がして UI をブロックしない
  2. Wasm 加速:sm-crypto のホットパスを Wasm に(コミュニティ実験あり)
  3. チャンク分割:大ファイルはブロック単位で暗号化し進捗表示

暗号ツールのアーキテクチャ

ToolsKu のレイヤ構成

UI 層(React コンポーネント)
     ↓
暗号サービス層(統一 API)
     ↓
┌──────────────┬──────────────┐
│ Web Crypto   │ sm-crypto    │
│(標準)      │(国密)      │
│ ネイティブ   │ 純 JS        │
└──────────────┴──────────────┘

統一インターフェース

interface CryptoService {
  encrypt(data: Uint8Array, key: CryptoKeyInput): Promise<Uint8Array>;
  decrypt(data: Uint8Array, key: CryptoKeyInput): Promise<Uint8Array>;
  generateKey(): Promise<CryptoKeyOutput>;
}

標準・国密とも同一インターフェースを実装し、UI は実装を意識しません。

ファイル暗号のメモリ管理

async function encryptFile(file: File, password: string) {
  // 1. ファイルをメモリに読み込み
  const buffer = await file.arrayBuffer();

  // 2. 大ファイルはチャンク処理(一括暗号化の OOM 回避)
  const CHUNK_SIZE = 64 * 1024 * 1024; // 64MB
  if (buffer.byteLength > CHUNK_SIZE) {
    return encryptFileInChunks(buffer, password, CHUNK_SIZE);
  }

  // 3. 暗号化
  const result = await aesGcmEncrypt(new Uint8Array(buffer), password);

  // 4. 機密データのクリア
  buffer = null; // GC に任せる

  return result;
}

よくある誤解

誤解 1:Base64 = 暗号化

Base64("password123") = "5a+G56CBMTIz"  ← すぐ復元できる
AES-256("password123") = "U2FsdGVkX1..."  ← 鍵なしでは復元不可

Base64 はエンコードであり暗号ではありません。誰でもデコードできます。

誤解 2:MD5/SHA-1 は「暗号化」

ハッシュは一方向で「復号」できません。完全性検証用であり、機密性のためではありません。

  • MD5:破られている—セキュリティ用途に使わない
  • SHA-1:衝突攻撃—非推奨
  • SHA-256/SM3:現時点では安全とみなされる

誤解 3:ECB モードは安全

ECB:同じ平文ブロック → 同じ暗号文(パターンが漏れる)
CBC/GCM:同じ平文ブロック → 異なる暗号文(安全)

ToolsKu の AES ツールは GCM のみ—不安全な ECB は提供しません。


まとめ

ブラウザ暗号はすでに実用段階です。

  • Web Crypto API:標準アルゴリズム(AES/RSA/SHA)をネイティブに近い速度で
  • sm-crypto:国密を純 JS で、コンプライアンス要件に対応
  • ゼロアップロード:鍵もデータも端末外に出ない

ToolsKu では AES暗号RSA暗号SM2暗号SM3ハッシュSM4暗号 など 30 以上のツールを、すべてブラウザ内で処理しています。

ブラウザローカルツールを無料で試す →

#加密#WebCrypto#国密#SM2#AES#安全