Nonce(ノンス) - 暗号化全般

暗号化全般 | IT用語集

Nonceとは

Nonce(ノンス / Number used ONCE)は、暗号通信において「一度だけ使用される数値」です。同じ鍵で複数のメッセージを暗号化する際に、各暗号化操作に固有のNonceを使用することで、セキュリティを確保します。

Nonceの主な役割:

  • 暗号文の一意性:同じ平文を同じ鍵で暗号化しても、異なる暗号文を生成
  • リプレイ攻撃の防止:過去のメッセージの再送信を検出
  • 認証プロトコル:チャレンジ-レスポンス認証での使用

NonceとIVの違い

NonceとIV(初期化ベクトル)は関連する概念ですが、厳密には異なります:

特性 Nonce IV
一意性要件 絶対に再利用してはならない 予測不可能であるべき
生成方法 カウンター or ランダム 通常ランダム
典型的な使用 AES-GCM、ChaCha20 AES-CBC

AIエンジニアとしての実体験

AIモデルのAPI認証システムでNonceを使用したリプレイ攻撃防止を実装しました。APIリクエストにNonceを含め、サーバー側で使用済みNonceを追跡します。

import os
import time
import hashlib
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

class NonceManager:
    """Nonce管理クラス"""
    
    def __init__(self):
        self.used_nonces = set()
        self.counter = 0
    
    def generate_random_nonce(self, size: int = 12) -> bytes:
        """ランダムNonceを生成(AES-GCM推奨サイズ: 12バイト)"""
        return os.urandom(size)
    
    def generate_counter_nonce(self, prefix: bytes = b'') -> bytes:
        """カウンターベースNonceを生成"""
        self.counter += 1
        return prefix + self.counter.to_bytes(8, 'big')
    
    def verify_nonce(self, nonce: bytes) -> bool:
        """Nonceの一意性を検証"""
        nonce_hash = hashlib.sha256(nonce).hexdigest()
        if nonce_hash in self.used_nonces:
            return False  # 再利用を検出
        self.used_nonces.add(nonce_hash)
        return True

# AES-GCMでのNonce使用例
def encrypt_with_aes_gcm(key: bytes, plaintext: bytes, associated_data: bytes = b''):
    nonce = os.urandom(12)  # 96ビットNonce
    aesgcm = AESGCM(key)
    ciphertext = aesgcm.encrypt(nonce, plaintext, associated_data)
    return nonce + ciphertext  # Nonceと暗号文を連結

def decrypt_with_aes_gcm(key: bytes, encrypted_data: bytes, associated_data: bytes = b''):
    nonce = encrypted_data[:12]
    ciphertext = encrypted_data[12:]
    aesgcm = AESGCM(key)
    return aesgcm.decrypt(nonce, ciphertext, associated_data)

自社サーバー運用への応用

TLSでのNonce使用

TLS 1.3では、各レコードの暗号化にNonceが使用されます。シーケンス番号をXORすることで、一意のNonceを生成します。

API認証でのNonce

# APIリクエストにNonceを含める例
import requests
import time
import hmac
import hashlib
import secrets

def make_authenticated_request(url: str, api_key: str, api_secret: str):
    nonce = secrets.token_hex(16)  # 32文字のNonce
    timestamp = str(int(time.time()))
    
    # 署名の生成
    message = f"{nonce}{timestamp}{url}"
    signature = hmac.new(
        api_secret.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()
    
    headers = {
        'X-API-Key': api_key,
        'X-Nonce': nonce,
        'X-Timestamp': timestamp,
        'X-Signature': signature
    }
    
    return requests.get(url, headers=headers)

関連ブログ記事

最新動向(2026年)

XChaCha20-Poly1305の採用

より長いNonce(24バイト)を使用するXChaCha20-Poly1305が普及しています。ランダムNonceの衝突リスクが大幅に低減されます。

SIV(Synthetic IV)モード

Nonce再利用に対する耐性を持つAES-GCM-SIVなどのモードが注目されています。Nonce誤用時の被害を限定できます。

トラブル事例と対策

🚨 重大な脆弱性:Nonce再利用

問題:AES-GCMで同じNonceを再利用すると、認証タグが破られ、平文が漏洩する可能性

対策:ランダムNonce(十分な長さ)またはカウンターベースNonceを使用。Nonce管理を厳密に

⚠️ ランダムNonceの衝突

問題:96ビットNonceで2^32回以上暗号化すると衝突確率が高くなる(誕生日のパラドックス)

対策:鍵のローテーション、より長いNonceを持つアルゴリズム(XChaCha20)の使用

権威あるリソース

関連用語

この用語についてもっと詳しく

Nonceに関するご質問や暗号設計のご相談など、お気軽にお問い合わせください。