LASSIC Media らしくメディア

2026.10.09 らしくコラム

デジタル署名の仕組み、なりすましと改ざんを防ぐ流れを図で解説

監修・編集責任者:牛尾 昭昌(株式会社LASSIC 執行役員)

手書きのサインが何種類も並ぶタブレットの画面と、同じサインを書き並べた紙が黒い机の上に置かれている様子の写真。

この記事の結論

  • デジタル署名は、秘密鍵でしか作れない値をデータに添え、公開鍵で作った人と改ざんの有無を確かめる仕組みです。
  • 「秘密鍵で暗号化」という説明は不正確で、署名は内容を隠さず、使う鍵の組の持ち主と目的が暗号化と異なります。
  • 新しく作るならEd25519かRSA-PSSを選び、鍵は署名専用に分け、ハッシュ値だけで改ざん対策にしないことが要点です。

※ 本記事は2026年10月時点の公式情報(省庁・公的機関、および製品やサービスを提供する事業者が公開している資料)に基づきます。

デジタル署名は、データに添えておくことで、誰が作ったものか、途中で書き換えられていないかを受け手が確かめられるようにする仕組みです。ソフトウェアの配布、APIのトークン、電子契約、サーバー証明書などで使われています。

一方で「秘密鍵で暗号化するのが署名」という説明が広く出回っており、暗号化との違いや、どこまでを保証するのかは混同されがちです。本記事では、署名の生成と検証の流れ、暗号化との違い、否認防止の意味、アルゴリズムの選び方、つまずきやすい点を、NISTの規格とRFC、Pythonでの実行結果をもとに整理します。

デジタル署名とは

デジタル署名は、公開鍵暗号の鍵の組(秘密鍵と公開鍵)を使います。署名する側は秘密鍵を使ってデータから署名値を計算し、データに添えます。受け手は、署名した人の公開鍵で、その署名値がデータと合っているかを確かめます。NISTのデジタル署名標準FIPS 186-5は用語の定義で、デジタル署名を、正しく実装すれば発信元の確認、データの完全性、署名者の否認防止を確かめる手段になる、暗号学的な変換の結果としています。*1

公開鍵は誰に知られても構いませんが、秘密鍵は署名する本人だけが持ちます。同じ規格も、署名を作れるのは秘密鍵を持つ利用者だけで、検証は公開鍵を使えば誰でもできるとしています。公開鍵暗号そのものの考え方は「共通鍵暗号と公開鍵暗号の違い」、ハッシュ関数の性質は「ハッシュ関数とは」で扱っているので、本記事では署名の使い方に絞ります。

署名の生成と検証の流れ

署名する側は、多くの方式で、まずデータをハッシュ関数で短い値(メッセージダイジェスト)にまとめ、その値と秘密鍵から署名値を計算します。FIPS 186-5も、署名の生成ではデータを要約するためにハッシュ関数がよく使われると説明しています。ただしEdDSAでは、データを先にハッシュせずに署名のアルゴリズムへ入れます。

デジタル署名の流れを示した図。署名する側は、本人だけが持つ秘密鍵でデータから署名値を作り、データと署名値を送る。データの中身は隠れない。検証する側は、誰に配ってもよい署名者の公開鍵で検証し、一致すれば受け入れ、不一致なら処理を止める。下段では、公開鍵暗号による暗号化が受け手の公開鍵で暗号化して受け手の秘密鍵で復号し、受け手以外に読ませないことを目的とするのに対し、デジタル署名は送り手の秘密鍵で署名値を作って送り手の公開鍵で確かめ、作った人と改ざんの有無を示すことを目的とする、と対比している。

受け手は、データと署名値、署名した人の公開鍵の3つを使って検証します。FIPS 186-5は、検証する側が、署名者とされる人の公開鍵と、署名の生成と同じハッシュ関数を使うとしています。*1 データが1ビットでも変わっていれば、また別の秘密鍵で作った署名値であれば、検証は失敗します。

検証で確かめられるのは、その公開鍵に対応する秘密鍵で署名されたことと、署名した後にデータが変わっていないことの2点です。その公開鍵が本当に相手のものかどうかは、署名だけでは分かりません。公開鍵の持ち主を認証局が保証する仕組みは「証明書チェーンの仕組み」で扱っています。

暗号化との違い

署名は「秘密鍵で暗号化し、公開鍵で復号すること」と説明されることがあります。暗号化では受け手の公開鍵で暗号化して受け手の秘密鍵で復号するので、署名では鍵の使い方が逆になる、という説明です。半分は正しく、半分は誤解を生む説明です。

正しいのは、使う鍵の組の持ち主と目的です。暗号化は受け手の鍵の組を使い、受け手だけが読めるようにします。署名は送り手の鍵の組を使い、送り手しか作れない値を、誰でも確かめられるようにします。

誤解を生むのは「暗号化」という言い方です。RSAについて、PKCS #1 v2.2(RFC 8017)は、署名の基本演算RSASP1と検証のRSAVP1は、復号のRSADPと暗号化のRSAEPと入出力の名前が違うだけで、目的が違うため区別していると述べています。*2 数式が同じなのはRSAの事情で、RSASSA-PSSでは、データのハッシュ値を決まった形式に符号化してから演算します。ECDSAやEdDSAには、暗号化という操作そのものがありません。署名は「秘密鍵で暗号化すること」ではなく、「秘密鍵でしか作れない値を作り、公開鍵で確かめること」と言い直すのが正確です。

暗号化・デジタル署名・HMACの違い(この記事の整理)
仕組み 使う鍵 値を作れる人 確かめられる人 主な目的
公開鍵暗号による暗号化 受け手の公開鍵と秘密鍵 公開鍵を持つ誰でも(暗号化) 受け手だけ(復号) 内容を受け手以外に読ませない
デジタル署名 送り手の秘密鍵と公開鍵 秘密鍵を持つ送り手だけ 公開鍵を持つ誰でも 作った人と改ざんの有無を示す
HMAC 双方が持つ同じ秘密の鍵 鍵を持つ双方 鍵を持つ双方 鍵を共有する相手との間で改ざんを見つける

HMACも改ざんを見つけられますが、送り手と受け手が同じ秘密の鍵を持ちます。鍵を持つ双方が同じ値を作れるので、第三者に対して、どちらが作ったかを示すことはできません。HMACの詳しい仕組みは別の記事で扱います。

否認防止の意味と限界

FIPS 186-5は、署名を受け取った人が、その署名が確かに署名者によって作られたことを第三者に示す証拠として使えること、そのため署名者が後から署名を否定しにくくなることを、否認防止と呼んでいます。*1 鍵を共有するHMACでは得られない、公開鍵による署名ならではの性質です。

ただし、技術だけで否認防止が成り立つわけではありません。SP 800-57 Part 1は、否認防止を本当に判断するのは多くの点を考える法的な判断で、暗号の仕組みはその要素の1つにすぎず、デジタル署名は判断を支えるものにとどまるとしています。*4 秘密鍵が漏れていた、誰でも鍵を使える場所に置いていた、といった事情があれば、署名があっても本人が作ったとは言い切れません。

日本の電子署名法でいう「電子署名」も、特定の技術の名前ではありません。総務省・法務省・経済産業省のQ&Aは、同法第2条第1項の電子署名を、電磁的記録に記録できる情報について行われる措置で、その情報を措置を行った者が作ったことを示すためのものと、改変が行われていないかを確かめられるもの、の両方に当たるものと説明しています。*5 デジタル署名はその代表的な手段ですが、法律上の効力は使い方や本人確認の方法で変わるため、契約などへの適用は法務部門や専門家に確かめます。電子署名の基盤を自社で運用する例は「Documensoで電子署名をセルフホスト構築・外注」で扱っています。

具体例:PythonでEd25519

Pythonのcryptographyライブラリで、Ed25519の署名と検証を試します。ライブラリの公式ドキュメントは、古いシステムとの相互運用の事情が無ければ、この署名アルゴリズムを強く検討するよう勧めています。*6 金額を1文字だけ書き換えたデータでも検証します。

from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.exceptions import InvalidSignature

private_key = Ed25519PrivateKey.generate()   # 署名する側だけが持つ
public_key = private_key.public_key()        # 検証する側に配る

message = b"order=1001;amount=50000"
signature = private_key.sign(message)
print("signature bytes:", len(signature))
print("same signature :", private_key.sign(message) == signature)

public_key.verify(signature, message)        # 一致すれば何も返さない
print("original : OK")

tampered = b"order=1001;amount=90000"        # 5を9に、1文字だけ変える
try:
    public_key.verify(signature, tampered)
except InvalidSignature as e:
    print("tampered :", type(e).__name__)

Python 3.12とcryptography 50.0.2で実行すると、署名値は64バイトで、同じデータに2回署名した値は一致しました(same signature : True)。元のデータの検証は通り、5を9に変えたデータではInvalidSignatureの例外が出ました。ドキュメントは、verifyは検証できないときにInvalidSignatureを送出し、通ったときは何も返さないと定めています。RFC 8032は、Ed25519の鍵を32オクテット、署名を64オクテットとし、EdDSAの署名は決定的で、質の悪い乱数で署名することから来る攻撃を防げると述べています。*3

RSAで署名するなら、パディングにPSSを使います。次の例では3072ビットの鍵を作り、同じデータに2回署名しました。

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa, padding

key = rsa.generate_private_key(public_exponent=65537, key_size=3072)
pss = padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
                  salt_length=padding.PSS.DIGEST_LENGTH)

message = b"order=1001;amount=50000"
sig1 = key.sign(message, pss, hashes.SHA256())
sig2 = key.sign(message, pss, hashes.SHA256())
key.public_key().verify(sig1, message, pss, hashes.SHA256())
key.public_key().verify(sig2, message, pss, hashes.SHA256())
print("signature bytes:", len(sig1))
print("same signature :", sig1 == sig2)

実行すると署名値は384バイトで、2回の署名値は一致しませんでしたが(same signature : False)、どちらも検証は通りました。PSSでは署名のたびに乱数のソルトを作って混ぜるためです。ライブラリのドキュメントは、PSSをRSAの署名に推奨するパディングとし、ソルトの長さはPSS.DIGEST_LENGTHかPSS.MAX_LENGTHにするよう勧めています。*7 署名値が毎回変わる方式もあるので、テストでは値の一致ではなく、検証が通るかどうかを見ます。

アルゴリズムの選び方

FIPS 186-5が承認している署名アルゴリズムは、RSA、ECDSA、EdDSAの3つの系統です。以前の版にあったDSAは署名の生成には承認されなくなり、すでに作られた署名の検証にだけ使えます。*1

FIPS 186-5が承認する署名アルゴリズムと主な条件
アルゴリズム 規格上の主な条件 選ぶ場面の例
RSA(RSASSA-PSS) 法の長さは2048ビット以上。新しく作るならPSS、PKCS1-v1_5は互換のため 既存の証明書や古い連携先との互換が要る
ECDSA 署名のたびに秘密の乱数kを新しく作る。決定的ECDSA(RFC 6979)も承認 連携先や証明書がECDSAを前提にしている
EdDSA(Ed25519・Ed448) Ed25519はSHA-512を使い、約128ビットの強度。署名に乱数を使わない 新しく作るAPIや社内システムの署名

RFC 8017は、RSASSA-PKCS1-v1_5への攻撃は知られていないとしつつ、堅牢さを高めるため、新しいアプリケーションではRSASSA-PSSを必須とし、v1.5は既存のアプリケーションとの互換のためだけに残していると述べています。*2

ECDSAでは、署名のたびに秘密の乱数を新しく作り、漏らさないことが求められます。RFC 8032は、質の悪い乱数で署名すると、アルゴリズムによっては秘密鍵が漏れるところまで影響が及ぶと注意しています。*3 乱数の扱いまで任せられる実績のあるライブラリを使うか、乱数を使わないEdDSAを選ぶのが無難です。連携先が対応する方式で決まる場面も多いので、先に確かめます。

つまずきやすい点

1つ目は、ハッシュ値だけで改ざん対策をしたつもりになることです。ファイルとSHA-256の値を同じ場所に置いていれば、そこを書き換えられる人は、ファイルを差し替えて値も計算し直せます。ハッシュ関数は鍵を使わないので、誰でも同じ値を作れるからです。作った人まで確かめるには、配布元の秘密鍵で署名し、受け手は別の経路で手に入れた公開鍵で検証します。アプリの署名の運用は「アプリのコード署名・証明書管理を外注」で扱っています。

2つ目は、鍵の用途の使い回しです。SP 800-57 Part 1は、1つの鍵は原則として1つの用途にだけ使うとし、理由として、2つの処理に同じ鍵を使うと一方か両方の強さが損なわれるおそれがあること、鍵が漏れたときの被害を限れることを挙げています。*4 FIPS 186-5も、RSAの署名用の鍵の組を、鍵確立など他の目的に使ってはならないとしています。*1 署名用と暗号化用、本番と検証環境で、鍵を分けておきます。

3つ目は、検証の結果の扱いです。cryptographyのverifyは失敗を例外で知らせるので、例外を捕まえて何もしなければ、改ざんされたデータをそのまま通してしまいます。例外を捕まえたら処理を止め、記録を残します。テストでは、正しいデータで通ることと、1文字変えたデータで失敗することの両方を確かめます。

4つ目は、鍵の期限と更新です。SP 800-57 Part 1は、署名用の秘密鍵の使用期間として最長でおよそ1〜3年を勧め、期間が終われば破棄するとしています。一方、検証用の公開鍵は、過去の署名を検証する必要がある間は残しておきます。*4 証明書の更新と失効の運用は「証明書管理(PKI)システム」で扱っています。

外部に委託するときに確認しておきたい点

署名の仕組みを委託先に作ってもらうときは、まず、何を誰が署名し、誰がどの公開鍵で検証するのかを図にしてもらいます。公開鍵の配り方と、それが本物だと確かめる方法が抜けていれば、署名は役に立ちません。

次に、秘密鍵の置き場所と、使える人を確かめます。ソースコードや設定ファイルに秘密鍵を置かず、クラウドの鍵管理サービスやHSM(ハードウェアセキュリティモジュール)に入れて、署名の操作だけを許す作りになっているか、用途ごとに鍵が分かれているかを見ます。

最後に、アルゴリズムと鍵長を選んだ理由、鍵の更新と失効の手順、検証の失敗をどこに記録して誰が気づくのかを、設計書と運用手順書に書いてもらいます。検証の失敗は攻撃の兆しのこともあるので、監視の対象に入れておきます。

まとめ:デジタル署名で確かめておきたい3つの点

第一に、デジタル署名は秘密鍵で署名値を作り、公開鍵で作った人と改ざんの有無を確かめる仕組みで、内容を隠す暗号化とは目的が違うこと。第二に、否認防止は署名だけでは決まらず、秘密鍵の管理と公開鍵の配り方まで含めて初めて意味を持つこと。第三に、新しく作るならEd25519かRSA-PSSを選び、署名用の鍵を他の用途に使い回さず、検証に失敗したら処理を止めて記録することです。

LASSICに相談するメリット

LASSICは、元請(プライムベンダー)としてシステムの開発と保守・運用を受託しています。署名の実装では、Pythonのcryptography、OpenSSL、AWS KMSやAzure Key Vaultなどの鍵管理サービスを、要件に合わせて使い分けます。設計の段階では、署名する対象と検証する人、Ed25519・ECDSA・RSA-PSSのどれを使うか、公開鍵の配り方と鍵の用途の分け方を発注者と整理します。検証と運用では、pytestで改ざんしたデータの検証が失敗することを確かめ、Terraformなどのコードで鍵の権限を管理し、CI/CDのパイプラインで署名と検証を自動で回します。本番では検証の失敗を監視し、鍵の更新の時期を管理します。

よくある質問

デジタル署名と電子署名は、同じものですか

電子署名は電子文書に対する署名の広い呼び方で、電子署名法では、作った人を示すことと、改変がないかを確かめられることの両方に当たる措置を指します。デジタル署名は、公開鍵暗号を使ってそれを実現する技術の名前で、電子署名の代表的な方式です。

署名すれば、データを秘密にできますか

できません。署名はデータを読めないようにはしないので、データはそのまま相手や第三者に見えます。中身を隠す必要があれば、署名とは別に暗号化します。

秘密鍵が漏れたら、どうなりますか

漏れた鍵を使えば、誰でも本人になりすまして正しい署名を作れます。証明書を使っている場合は失効させ、新しい鍵の組に切り替えます。漏れた時点より後の署名は信用できないので、影響の範囲を記録から洗い出します。

デジタル署名の設計と鍵管理のご相談

元請(プライムベンダー)として、署名と鍵管理の設計から、システムの保守・運用までご提案します。

Remoguとリラシクなら、署名や認証の仕組みの開発に加わるITエンジニアも探せます。

Remoguは、リモート前提で全国から即戦力のITプロ人材を調達するサービスです。リラシクは、扱う求人がすべてリモートワークのITエンジニア専門転職エージェントです。どちらもLASSICが運営しています。

無料相談はこちら

出典

  1. *1 参考:NIST「FIPS 186-5: Digital Signature Standard (DSS)」(2023年2月)(https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf)。出典:Abstract(否認防止)、3. Definitions(Digital signature)、3. General Discussion(署名の生成と検証、ハッシュ関数、EdDSAはデータをハッシュしない)、5.1(RSAの法は2048ビット以上、署名用の鍵の組を他の目的に使わない)、6.3(ECDSAの秘密の乱数k)、7.1(Ed25519はSHA-512、約128ビット)、Appendix E(DSAは署名の生成に承認されない)を参照(2026年10月確認)
  2. *2 参考:K. Moriarty ほか「RFC 8017: PKCS #1: RSA Cryptography Specifications Version 2.2」(https://www.rfc-editor.org/rfc/rfc8017)。出典:5.2 Signature and Verification Primitives(RSASP1・RSAVP1とRSADP・RSAEPの関係)、8. Signature Scheme with Appendix(新しいアプリケーションではRSASSA-PSSを必須)、9.1.1 Encoding Operation(ソルトの生成)を参照(2026年10月確認)
  3. *3 参考:S. Josefsson, I. Liusvaara「RFC 8032: Edwards-Curve Digital Signature Algorithm (EdDSA)」(https://www.rfc-editor.org/rfc/rfc8032)。出典:7. Test Vectors(Ed25519の鍵は32オクテット、署名は64オクテット)、8.2 Randomness Considerations(EdDSAの署名は決定的、質の悪い乱数による署名の危険)を参照(2026年10月確認)
  4. *4 参考:NIST「SP 800-57 Part 1 Rev. 5: Recommendation for Key Management: Part 1 – General」(2020年5月)(https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf)。出典:3.5 Non-repudiation(法的な判断)、5.1.1 Cryptographic Keys(共通鍵の認証用の鍵)、5.2 Key Usage(1つの鍵は1つの用途)、5.3.6 Cryptoperiod Recommendations(署名用の秘密鍵は最長でおよそ1〜3年)を参照(2026年10月確認)
  5. *5 参考:総務省・法務省・経済産業省「利用者の指示に基づきサービス提供事業者自身の署名鍵により暗号化等を行う電子契約サービスに関するQ&A」(令和2年7月17日)(https://www.moj.go.jp/content/001323974.pdf)。出典:問1(電子署名法第2条第1項における「電子署名」の説明)を参照(2026年10月確認)
  6. *6 参考:The Python Cryptographic Authority「Ed25519 signing」cryptography 50.0.2 ドキュメント(https://cryptography.io/en/stable/hazmat/primitives/asymmetric/ed25519/)。出典:冒頭の説明(相互運用の事情が無ければ強く検討を勧める)と verify(失敗時は InvalidSignature を送出し、成功時は None を返す)を参照(2026年10月確認)
  7. *7 参考:The Python Cryptographic Authority「RSA」cryptography 50.0.2 ドキュメント(https://cryptography.io/en/stable/hazmat/primitives/asymmetric/rsa/)。出典:padding.PSS の説明(RSAの署名に推奨するパディング、ソルトの長さは PSS.DIGEST_LENGTH か PSS.MAX_LENGTH を推奨)を参照(2026年10月確認)




View