0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

License System Day 6: ECDSA P-256署名の仕組み

Last updated at Posted at 2025-12-05

🎄 科学と神々株式会社 アドベントカレンダー 2025

License System Day 6: ECDSA P-256署名の仕組み


📖 今日のテーマ

昨日は対称鍵と非対称鍵の基礎を学びました。今日は、このシステムで使用するECDSA P-256という楕円曲線暗号について深掘りします。

「なぜRSAではなくECDSAを選ぶのか?」その答えがここにあります。


🔐 ECDSA とは?

正式名称

ECDSA = Elliptic Curve Digital Signature Algorithm
(楕円曲線デジタル署名アルゴリズム)

3つの要素

1. Elliptic Curve(楕円曲線)
   数学的な曲線を使った暗号化

2. Digital Signature(デジタル署名)
   データの真正性を証明する

3. Algorithm(アルゴリズム)
   署名生成と検証の手順

📐 楕円曲線とは何か?

数学的な定義

y² = x³ + ax + b

例: P-256 カーブ
y² = x³ - 3x + b

ビジュアルイメージ

      y
      ↑
      │     ╱╲
      │    ╱  ╲
      │   ╱    ╲
    ──┼──╱──────╲────→ x
      │╱          ╲
      │            ╲
      │             ╲

なぜ楕円曲線を使うのか?

理由1: 鍵サイズが小さい
  RSA 2048bit = ECDSA 224bit(同等の安全性)
  RSA 3072bit = ECDSA 256bit
  RSA 15360bit = ECDSA 521bit

理由2: 高速
  署名生成・検証が RSA より速い

理由3: メモリ効率
  組み込み機器やモバイルに最適

🎯 P-256 カーブとは?

正式名称

NIST P-256 (prime256v1, secp256r1)

パラメータ

名前: P-256
鍵サイズ: 256 bit
セキュリティレベル: 128 bit(AES-128 相当)
標準化: NIST, SECG

曲線方程式:
y² = x³ - 3x + b (mod p)

p = 2²⁵⁶ - 2²²⁴ + 2¹⁹² + 2⁹⁶ - 1

なぜ P-256 を選ぶのか?

✅ 広くサポートされている
   - Node.js
   - OpenSSL
   - Web Crypto API
   - ほぼすべてのプラットフォーム

✅ 高速
   - モバイルデバイスでも快適

✅ 十分な安全性
   - 128bit セキュリティレベル
   - 2030年代まで安全とされる

✅ 鍵サイズが小さい
   - 32バイト(256bit)
   - ネットワーク転送に最適

🔑 鍵ペアの生成

Node.js での実装

const crypto = require('crypto');

// ECDSA P-256 鍵ペアの生成
const { publicKey, privateKey } = crypto.generateKeyPairSync('ec', {
  namedCurve: 'prime256v1', // P-256
  publicKeyEncoding: {
    type: 'spki',
    format: 'pem'
  },
  privateKeyEncoding: {
    type: 'pkcs8',
    format: 'pem'
  }
});

console.log('公開鍵:\n', publicKey);
console.log('秘密鍵:\n', privateKey);

出力例

公開鍵:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3p8xHZx9...
-----END PUBLIC KEY-----

秘密鍵:
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawI...
-----END PRIVATE KEY-----

✍️ デジタル署名の仕組み

署名生成(サーバー側)

function signData(data, privateKey) {
  const sign = crypto.createSign('SHA256');
  sign.update(JSON.stringify(data));
  sign.end();

  const signature = sign.sign(privateKey, 'base64');
  return signature;
}

// 使用例
const responseData = {
  status: 'activated',
  license_id: '12345',
  plan: 'premium'
};

const signature = signData(responseData, privateKey);
console.log('署名:', signature);
// → MEUCIQDz7vkKYYj...

署名検証(クライアント側)

function verifySignature(data, signature, publicKey) {
  const verify = crypto.createVerify('SHA256');
  verify.update(JSON.stringify(data));
  verify.end();

  const isValid = verify.verify(publicKey, signature, 'base64');
  return isValid;
}

// 使用例
const isValid = verifySignature(responseData, signature, publicKey);

if (isValid) {
  console.log('✅ 署名が正しい!データは改ざんされていません');
} else {
  console.log('❌ 署名が不正!データが改ざんされています');
}

🔍 署名の中身を見てみよう

DER エンコーディング

ECDSA 署名のフォーマット(ASN.1 DER):

SEQUENCE {
  r: INTEGER (256 bit)
  s: INTEGER (256 bit)
}

例:
30 45          SEQUENCE, 69 bytes
   02 21       INTEGER, 33 bytes (r)
      00 d3f7be42a...
   02 20       INTEGER, 32 bytes (s)
      7a8e2c15b9...

合計: 約70バイト(可変長)

Base64 エンコード

バイナリ → Base64 で文字列化

例:
MEUCIQDz7vkKYYjPxQw3vR2S8...

利点:
  - JSONで送信可能
  - URLセーフ
  - 人間が読める(一応)

⚡ RSA vs ECDSA 徹底比較

パフォーマンス

署名生成(1000回):
  RSA 2048:  1.2秒
  ECDSA P-256: 0.3秒  ← 4倍速い!

署名検証(1000回):
  RSA 2048:  0.05秒
  ECDSA P-256: 0.6秒  ← RSAの方が速い

実際のユースケース:
  サーバー: 署名生成が頻繁 → ECDSA が有利
  クライアント: 検証のみ → どちらでもOK

鍵サイズ

同等の安全性:
  RSA 2048 bit  ≈  ECDSA 224 bit
  RSA 3072 bit  ≈  ECDSA 256 bit
  RSA 15360 bit ≈  ECDSA 521 bit

実際のファイルサイズ:
  RSA 公開鍵:  ~450 bytes
  ECDSA 公開鍵: ~120 bytes  ← 1/4サイズ!

署名サイズ

RSA 2048:  256 bytes
ECDSA P-256: 64-72 bytes  ← 1/4サイズ!

API レスポンス例:
  データ: 1 KB
  RSA署名: 256 bytes (25%増加)
  ECDSA署名: 70 bytes (7%増加)  ← 効率的!

🛡️ セキュリティレベル

ビット強度

ECDSA P-256:
  鍵サイズ: 256 bit
  セキュリティレベル: 128 bit

これは何を意味するか?

128 bit = 2^128 通りの組み合わせ
= 340,282,366,920,938,463,463,374,607,431,768,211,456 通り

現在のスーパーコンピューターでも
数十億年かかる計算量

攻撃耐性

✅ 総当たり攻撃: 不可能(2^128 通り)
✅ 量子コンピューター: 2030年代まで安全
✅ 数学的攻撃: 現時点で有効な攻撃なし

注意:
  量子コンピューターの発展により
  将来的には P-384, P-521 への移行が推奨される

💡 実装時のベストプラクティス

1. ハッシュ関数の選択

// ❌ 弱いハッシュ
crypto.createSign('SHA1');  // 脆弱!

// ✅ 推奨
crypto.createSign('SHA256'); // 安全
crypto.createSign('SHA384'); // より安全
crypto.createSign('SHA512'); // 最も安全

2. 鍵の安全な保管

// ❌ 危険
const privateKey = 'ハードコード';

// ✅ 推奨
const privateKey = fs.readFileSync(
  process.env.PRIVATE_KEY_PATH,
  'utf8'
);

// さらに良い
const privateKey = await secretManager.getSecret('private-key');

3. エラーハンドリング

function verifySignature(data, signature, publicKey) {
  try {
    const verify = crypto.createVerify('SHA256');
    verify.update(JSON.stringify(data));
    verify.end();

    return verify.verify(publicKey, signature, 'base64');
  } catch (error) {
    console.error('署名検証エラー:', error.message);
    return false; // 失敗として扱う
  }
}

🌟 まとめ

今日学んだこと:

  1. ECDSA の基本

    • 楕円曲線を使った署名アルゴリズム
    • 高速・コンパクト・安全
  2. P-256 カーブ

    • 256bit 鍵サイズ
    • 128bit セキュリティレベル
    • 広くサポートされている
  3. RSA との比較

    • 署名生成: ECDSA が4倍速い
    • 鍵サイズ: ECDSA が1/4
    • 署名サイズ: ECDSA が1/4
  4. 実装のポイント

    • SHA256 以上のハッシュ
    • 鍵の安全な保管
    • 適切なエラーハンドリング

🎓 理解度チェック

  1. ECDSA の利点は?
  2. P-256 のセキュリティレベルは?
  3. なぜ RSA ではなく ECDSA を選ぶ?
  4. 署名検証の流れは?

💡 次回予告

Day 7: JWT(JSON Web Token)入門

  • JWT の構造
  • Header, Payload, Signature
  • なぜ JWT を使うのか
  • 実際の実装例

お楽しみに!


前回: Day 5: 暗号化の基礎 - 対称鍵と非対称鍵
次回: Day 7: JWT(JSON Web Token)入門

Happy Learning! 🎉

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?