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?

PDF用電子署名の証明書を手作りで作成してみました

Last updated at Posted at 2025-06-06

環境情報

  • 使用OS:Windows
  • システム環境:PowerShell, node.js, python

OpenSSLインストール

ダウンロード

ダウンロードサイト
https://slproweb.com/products/Win32OpenSSL.html

私は下記のファイルをダウンロードしました。

  • Win64 OpenSSL v3.5.0

  • 余談:最近WindowsはOpenSSLが標準搭載だと思っていましたが、そうではなさそうでした

環境変数設定

Windowsシステム環境変数(PATH)にC:\Program Files\OpenSSL-Win64\binを追加

動作確認

openssl version

OpenSSL 3.5.0 8 Apr 2025 (Library: OpenSSL 3.5.0 8 Apr 2025)

電子署名の証明書を作成

秘密鍵と証明書(有効期限365日)を作成

  • /CN=Your NameYour Nameは署名者名を入力します
  • days 365は有効期間ですので、日数はお好きに変更します
openssl req -x509 -newkey rsa:2048 -keyout private.key -out certificate.crt -days 365 -nodes -subj "/CN=Your Name"

p12ファイルにまとめる

  • p12ファイル:秘密鍵と証明書(公開鍵証明書)をセットでまとめて、パスワードで保護したファイル
  • こちらで設定したパスワードはPDFに電子署名をするときに必要です
openssl pkcs12 -export -out certificate.p12 -inkey private.key -in certificate.crt
Enter Export Password:

Verifying - Enter Export Password:

PDF作成APP(Node.js)

PDFに署名をする

  • pdfBufferはPDFデータです
  • passphrase: '****'****にはp12ファイル作成時に設定したパスワードを入力します
import fs from "fs";
import { plainAddPlaceholder } from 'node-signpdf';
import signPdfInstance from 'node-signpdf';
//・・・中略・・・

// 電子署名用証明書ファイルのパス
const p12Path = path.join(process.cwd(), 'certificate.p12');
const p12Buffer = fs.readFileSync(p12Path);
// Buffer型に変換
const pdfBufferNode = Buffer.from(pdfBuffer);
// プレースホルダー追加
const pdfWithPlaceholder = plainAddPlaceholder({ pdfBuffer: pdfBufferNode, reason: '電子署名' });
// 署名付与(パスワードなしでp12を作成した場合は空文字を指定)
const signedPdf = signPdfInstance.sign(pdfWithPlaceholder, p12Buffer, { passphrase: '****' });

//・・・中略・・・

PDFの署名を検証(Python)

  • CAで作ってないためCAは確認しない
    • CAとは:認証局 (Certificate Authorities)
  • PDFファイルのSHA256 fingerprintSerial numberを確認する
    • 技術的には、元の証明書なしでSHA256 fingerprintSerial numberを偽造するのは不可能に近いらしいです
    • 重大な確認が必要な際は、万が一のため、PDFが本物なのかを電話などで確認した方がいいです

証明書の署名情報を確認

  • Passwordはcertificate.p12作成時のパスワード
openssl pkcs12 -in certificate.p12 -nokeys -clcerts -out mycert.pem

Enter Import Password:

openssl x509 -in mycert.pem -noout -subject -issuer -serial -fingerprint -sha256

subject=CN=Park Test
issuer=CN=Park Test
serial=6D1B3ACBC48A1DCD20494D565AD63687C9E2D93D
sha256 Fingerprint=07:9B:94:AB:0B:0B:96:C6:80:C2:E2:EE:93:00:9C:8E:DF:6B:70:E4:EE:FC:8B:84:7E:0F:67:C2:53:CF:2E:DD

PDFの署名を確認

from pyhanko.pdf_utils.reader import PdfFileReader
from pyhanko.sign.validation import validate_pdf_signature
import contextlib
import io

with open("test2.pdf", "rb") as f:
    r = PdfFileReader(f)
    sig = r.embedded_signatures[0]
    # バリデーション時のstderr出力を抑制
    with contextlib.redirect_stderr(io.StringIO()):
        status = validate_pdf_signature(sig, key_usage_settings=None)
    cert = sig.signer_cert
    sha256 = cert.sha256_fingerprint  # Already a hex string
    sha1 = cert.sha1_fingerprint      # Already a hex string
    print("SHA256 fingerprint:", sha256)
    print("SHA1 fingerprint:", sha1)
    print("Subject:", cert.subject.human_friendly)
    # Adobeと同じ形式(0xなし大文字16進数)でシリアル番号を表示
    try:
        serial_bytes = cert.serial_number_bytes
        serial_hex = serial_bytes.hex().upper()
        print("Serial number:", serial_hex)
    except AttributeError:
        print("Serial number:", format(cert.serial_number, 'X'))
root@ccd3416ad175:/workspaces/python-tools# python sign-test.py
SHA256 fingerprint: 07 9B 94 AB 0B 0B 96 C6 80 C2 E2 EE 93 00 9C 8E DF 6B 70 E4 EE FC 8B 84 7E 0F 67 C2 53 CF 2E DD
SHA1 fingerprint: 7C 24 8F AA 04 07 16 C4 E0 BA 19 16 BE 08 14 07 A8 5D 45 96
Subject: Common Name: Park Test
Serial number: 6D1B3ACBC48A1DCD20494D565AD63687C9E2D93D

※注意

  • 証明書のserialやfingerprintは公開して問題ありません
  • 秘密鍵の内容は絶対に公開しないよう注意してください
  • certificate.p12private.keyは公開してはいけません
  • 自分で作成した証明書ではなく、認証局(CA)発行のAATL対応する証明書を利用すれば、AdobeなどでPDFの署名を検証した際、信頼された署名と表示されます
    • AATL:Adobe Approved Trust List
    • ※たとえCAが発行した証明書でも、AATLに対応していない場合は、Adobeで署名を確認しても「信頼できる」とは表示されません

おわりに

ChatGPTとGeminiを活用して調査しました。

0
0
2

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?