電子帳簿保存法のタイムスタンプを業務システムに組み込むとき、条文が求めているのは「付ける」機能だけではありません。施行規則は、保存期間を通じて変更がないと確認できることと、課税期間中の任意の期間を指定して一括で検証できることの2つを、タイムスタンプそのものの要件として定めています。この記事では、その条文を実装要件に読み替えたうえで、opensslによるRFC 3161の要求と検証のコマンド、トークンを保管するテーブル設計、一括検証バッチ、訂正削除履歴でタイムスタンプを使わずに済ませる条件までを、国税庁の一問一答(令和8年7月版)に沿って示します。スキャナ保存の要件と電子契約のタイムスタンプの扱いも、実装の観点から整理する内容です。
まとめ:電帳法のタイムスタンプは保存区分で要否が分かれ実装は付与と一括検証の2機能
タイムスタンプが要件に出てくるのは、スキャナ保存と電子取引データ保存の2区分です。電子取引では訂正削除履歴の残るシステムや事務処理規程でも足りるため、付与は選択肢の1つにすぎません。スキャナ保存を自社開発のシステムで行う場合は、認定タイムスタンプの付与が事実上の前提になります。
実装するなら、作るものは2つです。1つは保存処理とは切り離した付与ジョブで、原本のSHA-256を認定事業者へ送り、返ってきたトークンを原本と紐づけて保管します。もう1つは課税期間を指定して全トークンを再検証するバッチです。付与だけ作って検証の手段を持たないシステムは、条文の要件を満たしません。
施行規則の条文から読むタイムスタンプ機能の実装要件と付与の単位・期限
タイムスタンプの意味や電子署名との違いといった総論はタイムスタンプとは?仕組み・電子署名との違いと電子帳簿保存法での要否で扱っています。ここでは、システムの仕様書に落とすための条文だけを拾います。
スキャナ保存は一の入力単位ごと・電子取引は授受後に付ける対象の違い
電子帳簿保存法施行規則の第2条第6項第2号ロは、スキャナ保存について、書類の作成または受領の後、速やかに「一の入力単位ごとの電磁的記録の記録事項」にタイムスタンプを付すと定めています。1回のスキャン入力で作られたデータごとにトークンを持たせる設計が、条文に最も素直に沿います。月末に1か月分の画像を1つのファイルへまとめてから1回だけ付与する作りは避けてください。
電子取引は第4条第1項です。第1号が「タイムスタンプが付された後の授受」、第2号が「授受後に付す」方法で、付与の対象は授受した電子データそのものです。同じ文書管理システムでも、取込み経路がスキャンか電子取引かで付与の単位と期限の起点が変わるので、証憑テーブルに保存区分の列を持たせて分岐させます。
保存期間を通じた確認と課税期間の一括検証という2つの機能要件
同じ第2条第6項第2号ロは、使えるタイムスタンプを総務大臣が認定する時刻認証業務のものに限ったうえで、次の2つを満たすものとしています。
- 記録事項が変更されていないことを、保存期間を通じ、その業務を行う者に対して確認する方法その他の方法で確認できること
- 課税期間中の任意の期間を指定し、その期間内に付したタイムスタンプを一括して検証できること
1は「7年後でも検証できるか」、2は「期間指定の一括処理があるか」という機能要件です。国税庁の一問一答【電子取引関係】(令和8年7月)問60も、この2点を規則第2条第6項第2号ロの要件として挙げています。1は条文どおり認定事業者に確認する方法でも満たせるので、自前で作り込むべきなのは2の期間指定バッチのほうです。
付与期限を7営業日と最長2か月+7営業日で計算する期限管理の列設計
「速やかに」は、おおむね7営業日以内と扱われます。授受からタイムスタンプ付与までの事務処理規程を定めている会社は、業務処理サイクル(最長2か月)を経過した後、おおむね7営業日以内でよいとされています(問62)。最長2か月は暦の上の2か月で、4月21日受領なら6月20日がサイクルの終わりです。
システムでは、受領日・適用する期限ルール・算出した期限日の3列を持たせ、付与ジョブが期限日の数日前に未付与を警告する作りにします。営業日の数え方は会社の休日カレンダーに依存するため、祝日テーブルと結合して算出してください。期限の数え方そのものの解説は前出の総論記事に譲ります。
opensslでRFC 3161のタイムスタンプを要求し応答を検証する手順の実演
認定事業者のAPIは契約者向けの仕様で、要求と応答の形式はRFC 3161(Time-Stamp Protocol)が土台です。手元で形式に慣れておくと、事業者の仕様書を読む時間が短くなります。
検証環境の準備と認定外のFreeTSAで手順だけを先に確かめる理由
手元に必要なのは、OpenSSL 3系とcurlの2つだけです。送信先には、無償で公開されているFreeTSAを使います。FreeTSAは送信先 https://freetsa.org/tsr と、検証用のCA証明書(cacert.pem)とTSA証明書(tsa.crt)を公開しており、RFC 3161の往復をそのまま試せます。
注意点は1つです。FreeTSAは総務省の認定時刻認証業務の一覧(令和8年3月現在6件)に載っていません。電子帳簿保存法の要件を満たすタイムスタンプとしては使えないので、ここでの用途は形式の確認と開発環境のテストに限ります。本番の送信先は、契約した認定事業者のエンドポイントに差し替えます。
openssl ts -queryでハッシュ値入りの要求ファイルを作るコマンド
OpenSSLのopenssl-tsマニュアルでは、-queryで要求を作り、-dataに原本を渡すとハッシュ値を計算して要求に入れます。ダイジェストの既定はSHA-256です。
# 検証用のCA証明書とTSA証明書を取得する
curl -sS -o cacert.pem https://freetsa.org/files/cacert.pem
curl -sS -o tsa.crt https://freetsa.org/files/tsa.crt
# 原本のハッシュ値を入れた要求ファイルを作る(-cert で応答にTSA証明書を同梱させる)
openssl ts -query -data invoice_20261020.pdf -sha256 -cert -out invoice_20261020.tsq
# 要求の中身を確認する(Hash Algorithm と Message data に原本のSHA-256が入る)
openssl ts -query -in invoice_20261020.tsq -text
要求ファイルに入るのはハッシュ値とアルゴリズム、乱数(nonce)で、原本の中身は送られません。-certを付けると、応答にTSAの署名用証明書が含まれ、検証時に-untrustedで証明書を渡す手間が省けます。
curlでTSAへ送信し-verifyで原本と応答を照合する2つのコマンド
openssl tsには、要求をHTTPで送る機能がありません。マニュアルにもHTTPやTCPでの自動送信は未対応と書かれているため、送信はcurlかアプリケーション側のHTTPクライアントで行います。
# 要求ファイルをTSAへ送り、応答(.tsr)を受け取る
curl -sS -H "Content-Type: application/timestamp-query" \
--data-binary @invoice_20261020.tsq \
-o invoice_20261020.tsr https://freetsa.org/tsr
# 原本と応答を照合する。成功すると「Verification: OK」と表示される
openssl ts -verify -data invoice_20261020.pdf -in invoice_20261020.tsr -CAfile cacert.pem
-verifyは、原本から計算し直したハッシュ値と応答内の値の一致、TSAの署名、証明書チェーンをまとめて確かめます。原本を1バイトでも書き換えて同じコマンドを実行すると、検証は失敗します。アプリケーションに組み込む場合も、送信部分をHTTPクライアントに置き換えるだけで、要求と検証の考え方は変わりません。
-text出力から読むgenTime・シリアル番号・ポリシーOIDと保存項目
応答を人が読める形にするには、-replyと-textを組み合わせます。
# 応答の中身を表示する(Time stamp・Serial number・Policy OID などが出る)
openssl ts -reply -in invoice_20261020.tsr -text
# 応答からトークン部分だけを取り出して保存する
openssl ts -reply -in invoice_20261020.tsr -token_out -out invoice_20261020.tst
表示される項目のうち、検索と監査で使うのは生成時刻(genTime)、通し番号、ポリシーOID、ハッシュアルゴリズムの4つです。トークン本体のファイルとは別に、この4つをデータベースの列へ書き出しておくと、期間指定の一括検証や事業者ごとの集計がSQLだけで済みます。
業務システムへ組み込む付与ジョブの構成とトークン保管テーブルの設計
付与を保存処理の中で同期的に呼ぶと、事業者側の障害がそのままアップロード失敗になります。保存と付与は分けて設計します。
保存処理と付与を切り離すキュー構成と失敗時の再送・期限超過の検知
構成は、証憑の保存トランザクションで「未付与」の行を作り、別プロセスの付与ジョブがキューから取り出して事業者へ要求する形が扱いやすくなります。ジョブは次の順で処理します。
- 保存済みの原本からSHA-256を計算し、保存時に記録したハッシュ値と一致するか確かめる
- 認定事業者へ要求を送り、応答を受け取ったらその場で-verify相当の検証をかける
- 検証に通った応答だけを保管し、genTimeなどの項目を列に書き込んで「付与済み」にする
- 失敗した行は待ち時間を延ばしながら再送し、期限日が近い未付与は担当者へ通知する
1の照合を省くと、保存から付与までの間に原本が差し替えられても気付けません。問61は、おおむね7営業日以内に付与できない特別な事由があっても、解消後直ちに付与すれば「速やかに」付与したものと扱うとしています。障害の発生と解消の時刻をログに残しておけば、この説明に使えます。
原本ハッシュとトークンを紐づけるPostgreSQLのテーブル定義例
証憑本体のテーブル(evidence)とは別に、タイムスタンプ専用のテーブルを持たせます。検索要件の列設計は電子帳簿保存法の検索要件をファイル名・索引簿・DB検索で実装する手順で扱っているので、ここではタイムスタンプ部分だけを示します。
CREATE TABLE evidence_timestamp (
evidence_id bigint PRIMARY KEY REFERENCES evidence(id),
save_kind text NOT NULL CHECK (save_kind IN ('scanner', 'e_transaction')),
received_on date NOT NULL, -- 作成・受領日(期限計算の起点)
deadline_on date NOT NULL, -- 7営業日または業務処理サイクル後の期限
sha256 char(64) NOT NULL, -- 付与時に送ったハッシュ値
status text NOT NULL DEFAULT 'pending',
tsa_name text, -- 認定時刻認証業務の名称
policy_oid text,
serial_no text,
gen_time timestamptz, -- トークン内の生成時刻
tsr_key text, -- 応答ファイルの保存先キー
ca_bundle_key text, -- 検証に使う証明書束の保存先キー
retry_count int NOT NULL DEFAULT 0
);
CREATE INDEX evidence_timestamp_gen_time_idx ON evidence_timestamp (gen_time);
CREATE INDEX evidence_timestamp_pending_idx ON evidence_timestamp (deadline_on) WHERE status = 'pending';
tsa_nameとca_bundle_keyを行ごとに持たせているのは、事業者の乗り換えや証明書の更新があっても、過去のトークンを当時の証明書で検証できるようにするためです。gen_timeの索引は、次の章の一括検証で期間を絞り込むときに効きます。
PDF台紙に添付して付与する方式とトークン別ファイル保存の選び分け
トークンの持たせ方は、原本と別ファイルで保管する方式と、PDFの中に埋め込む方式の2つに分かれます。システムで機械的に検証するなら、原本を一切加工しない別ファイル方式のほうが単純です。
WordやExcelで受け取った請求書や、パスワード付きPDFのように原本へ直接付与できないデータもあります。問63が認めているのは、PDFを台紙にしてそれらのデータを添付し、台紙にタイムスタンプを付ける方法です。ただし検索要件がかかる会社は、取引先ごとに台紙を分けるなど、台紙そのものを探せるようにしておく必要があります。台紙方式を採るなら、台紙1枚と添付ファイルの対応表を証憑テーブル側に持たせてください。
課税期間の一括検証バッチと保存期間を通じて検証を維持する運用設計
条文の「一括して検証することができること」は、システムに期間指定の検証手段が備わっていれば満たせます。税務調査のときに初めて動かすのでは遅いので、月次で回すバッチとして実装しておきます。
課税期間を指定して全トークンを再検証するPythonバッチの実装例
次の例は、前出のテーブルから期間内のトークンを取り出し、openssl ts -verifyで1件ずつ照合して結果を記録するバッチです。ストレージの読み出し部分は自社の保存先に合わせて置き換えます。
"""課税期間を指定してタイムスタンプを一括検証する。
使い方: python verify_period.py 2026-04-01 2027-03-31
"""
import subprocess
import sys
import psycopg
from storage import fetch_to_tmp # 保存先から一時ファイルへ取り出す自社関数
start, end = sys.argv[1], sys.argv[2]
SQL = """
SELECT t.evidence_id, e.file_key, t.tsr_key, t.ca_bundle_key
FROM evidence_timestamp t JOIN evidence e ON e.id = t.evidence_id
WHERE t.status = 'stamped' AND t.gen_time::date BETWEEN %s AND %s
ORDER BY t.gen_time
"""
failed = []
with psycopg.connect("dbname=docs") as conn:
rows = conn.execute(SQL, (start, end)).fetchall()
for evidence_id, file_key, tsr_key, ca_key in rows:
cmd = ["openssl", "ts", "-verify",
"-data", fetch_to_tmp(file_key),
"-in", fetch_to_tmp(tsr_key),
"-CAfile", fetch_to_tmp(ca_key)]
r = subprocess.run(cmd, capture_output=True, text=True)
ok = "Verification: OK" in r.stdout
conn.execute(
"INSERT INTO timestamp_verify_log (evidence_id, ok, detail) VALUES (%s, %s, %s)",
(evidence_id, ok, (r.stdout + r.stderr)[-500:]),
)
if not ok:
failed.append(evidence_id)
print(f"検証 {len(rows)} 件、失敗 {len(failed)} 件", failed[:20])
sys.exit(1 if failed else 0)
失敗が1件でもあれば終了コード1を返すので、ジョブ管理側で通知に回せます。検証ログを残しておくと、「いつ、どの範囲を、どの結果で検証したか」を調査時に提示できます。
TSA証明書の期限切れと事業者の乗り換えで検証を壊さないための手順
opensslの検証は、TSAの証明書チェーンも確かめます。証明書の有効期限が過ぎた後は、同じコマンドが失敗する可能性があります。施行規則が「当該業務を行う者に対して確認する方法」を挙げているのはこのためで、長期の確認は契約先の認定事業者に確認できる手段を契約時に確かめておき、自前のバッチは日常の点検と位置づけるのが安全です。
事業者を乗り換えるときは、旧事業者のトークンと証明書束を消さずに残します。問102は、システムを移行する際、電子取引データなら移行時の事務処理規程を定めて運用すれば改ざん防止措置を満たせる一方、スキャナデータを含めてまとめて移行する場合はこの方法が認められないとしています。スキャナ保存を扱うシステムでは、移行計画にタイムスタンプの扱いを最初から入れてください。総務省の一覧では、三菱電機デジタルイノベーションの業務が令和8年1月13日まで「MINDタイムスタンプサービス」という名称だったように、名称変更も起こります。tsa_name列は表示名ではなく、契約上の識別子で管理すると混乱しません。
訂正削除履歴のシステムでタイムスタンプを使わずに済ませる設計と条件
電子取引データには、タイムスタンプを使わない選択肢があります。実装の手間は小さくありませんが、事業者との契約や付与ジョブが不要になります。
電子取引で第3号を選ぶなら授受と保存を同じシステムで行う前提
施行規則第4条第1項第3号は、訂正削除の事実と内容を確認できるか、訂正削除ができないシステムを使って「授受及び保存」を行うことを求めています。問37は、スキャナ保存用の文書管理システムに電子取引のPDFを入れる場合、そのシステムで授受ができないなら、タイムスタンプか事務処理規程の方法で要件を満たす必要があると回答しています。メールで受け取ったPDFを担当者が文書管理システムへアップロードするだけの運用では、第3号に乗れません。
問39は、要件を満たすシステムの例として、訂正削除が物理的にできない仕様と、訂正削除前の内容を記録して事後に検索・閲覧・出力できる仕様の2つを示しています。取引先がアップロードする受領ポータルや、EDIの受信口を自社システムに持つ場合が、第3号を検討できる構成です。
更新と削除を禁じて版を積み上げる追記型テーブルとトリガーの実装例
訂正削除の履歴を残す方式は、上書きをやめて版を追加していく追記型にすると、条文の「事実及び内容を確認することができる」を素直に満たせます。PostgreSQLなら、更新と削除をトリガーで拒否します。
CREATE TABLE evidence_version (
evidence_id bigint NOT NULL,
version int NOT NULL,
file_key text NOT NULL,
sha256 char(64) NOT NULL,
is_deleted boolean NOT NULL DEFAULT false, -- 削除も「削除済みの版」の追加で表す
reason text,
changed_by text NOT NULL,
changed_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (evidence_id, version)
);
CREATE FUNCTION evidence_version_append_only() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE EXCEPTION 'evidence_version は追記のみ。訂正や削除は新しい版で記録する';
END
$$;
CREATE TRIGGER evidence_version_no_change
BEFORE UPDATE OR DELETE ON evidence_version
FOR EACH ROW EXECUTE FUNCTION evidence_version_append_only();
REVOKE UPDATE, DELETE ON evidence_version FROM app_user;
トリガーと権限の両方で塞いでいるのは、アプリケーションの不具合と運用者の誤操作の両方を止めるためです。データベースの管理者権限ならトリガーを外せてしまう点は残ります。管理者の操作ログを別系統に残す設計はワークフローシステムの操作ログ取得:監査証跡に残す項目と電帳法対応が参考になります。
スキャナ保存は自社システムの時刻記録でタイムスタンプを代替できない壁
スキャナ保存にも代替の道はあります。施行規則第2条第6項第2号は、入力期間内に入力したことを確認できる場合はタイムスタンプ(ロ)の要件を除くという規定です。ただし一問一答【スキャナ保存関係】(令和8年7月)の問31は、NTPサーバーと同期したSaaS型クラウドのように、時刻証明機能を持つシステムで保存時刻が変更されていないと確認できる場合に限っています。
問32は、自社システムでは保存時刻の非改ざん性を完全には証明できないため、時刻証明機能を他社へ提供しているベンダー以外は代替要件を満たせないとしています。つまり、自社開発のシステムでサーバー時刻を記録しても、スキャナ保存のタイムスタンプは省けません。訂正削除履歴(ハ)はスキャナ保存では代替ではなく、タイムスタンプとは別に必要な要件です。スキャナ保存の要件全体はスキャナ保存制度とは?紙の請求書・領収書を電子保存する要件と始め方にまとめています。
認定タイムスタンプを自社開発に組み込むか既製サービスに任せるかの判断
ここまでの条文を前提に、どの会社が付与機能を自前で持つべきかを言い切ります。
スキャナ保存を自社システムで行う会社が認定事業者と直接連携すべき条件
組み込むべきなのは、紙で受け取る証憑を自社開発の業務システムに取り込み、そのデータで仕訳や支払まで流したい会社です。問32により自社システムでは時刻証明による代替が使えないため、スキャナ保存を自社で持つ以上、認定タイムスタンプとの連携は避けられません。取込み件数が多く、既製の受領サービスと業務システムの二重入力が負担になっている場合は、連携を作る費用を回収しやすくなります。
この場合の開発範囲は、付与ジョブ、トークン保管テーブル、一括検証バッチ、証明書束の管理の4つです。一問一答【電子取引関係】の問18が示すとおり、自社開発のプログラムを使う場合はシステム概要書の備付けも要件に入るため、設計書を税務調査で示せる形で残しておきます。保存対象の棚卸しからの設計は、文書管理システム開発で相談を受けています。
電子取引だけなら組み込みを見送る判断と自作で失敗しやすい典型パターン
扱うのが電子取引データだけなら、タイムスタンプの組み込みは見送ります。事務処理規程を定めて運用する第4号なら開発は要りません。規程の作り方は事務処理規程とは?真実性要件を満たす作成方法と国税庁サンプルにあります。受領ポータルを自社で持つなら第3号の追記型テーブルで足り、事業者との契約費用もかかりません。
自作で失敗しやすいのは次の3つの型です。付与だけ作って一括検証の手段を用意していない。保存処理の中で同期的に付与し、事業者の障害で証憑の登録そのものが止まる。証明書束を上書き更新して、旧証明書で発行されたトークンが検証できなくなる。どれも条文の2つの機能要件か、付与期限の管理に直結します。制度全体の中での位置づけは電子帳簿保存法とは?3区分の要件・対象書類と自社システム対応で確認できます。
電子帳簿保存法のタイムスタンプの付与と実装についてよくある質問
実装と運用の場面でよく出る疑問に、条文と一問一答の範囲で答えます。
電子帳簿保存法のタイムスタンプは無料のサービスで付けてもよいですか?
要件を満たすのは、総務大臣が認定する時刻認証業務のタイムスタンプだけです。総務省の一覧に載っている認定業務は令和8年3月現在で6件で、FreeTSAのような無償の公開サービスは含まれていません。無償のサービスは開発やテストでRFC 3161の形式を確かめる用途には使えますが、税務上の真実性の確保には使えません。費用を抑えたいなら、電子取引については事務処理規程や訂正削除履歴の残るシステムで要件を満たす方法を検討するほうが現実的です。
電子契約サービスのタイムスタンプで電子取引の要件は満たせますか?
電子契約サービスが総務大臣認定の時刻認証業務のタイムスタンプを付けた後に契約データを受け取るなら、施行規則第4条第1項第1号の「タイムスタンプが付された後の授受」に当たります。確認すべきなのは、使われているのが認定業務のタイムスタンプか、保存期間を通じた確認と期間指定の一括検証ができるかの2点です。サービス上で契約データを保存し、利用者側で訂正削除ができない仕様なら、第3号の要件で整理できる場合もあります。
付与期限の7営業日を過ぎてしまった場合はどうなりますか?
一問一答【電子取引関係】の問61は、おおむね7営業日以内に付与できない特別な事由がある場合、その事由が解消した後直ちに付与すれば、速やかに付与したものとして扱うとしています。災害その他やむを得ない事情で要件を満たせなかったことを証明した場合の規定もあります。一方、機器のメンテナンスを怠った故障のように保存義務者の責めに帰すべき事由があるときは、これらの扱いは受けられません。障害の記録と付与の再送履歴をシステムに残しておく理由はここにあります。
スキャナ保存の要件はタイムスタンプ以外に何がありますか?
施行規則第2条第6項第2号は、解像度200dpi以上かつ赤・緑・青それぞれ256階調以上で読み取るスキャナを使うこと(イ)、タイムスタンプを付すこと(ロ)、訂正削除の事実と内容を確認できるか訂正削除できないシステムであること(ハ)を定めています。入力期間(第1号)や帳簿との相互関連性(第3号)も、これらとは別に定められた要件です。解像度の判定方法は電子帳簿保存法の解像度要件|200dpi・256階調の判定基準で扱っています。
タイムスタンプを付けたPDFを後から編集するとどうなりますか?
タイムスタンプは付与時点の原本のハッシュ値に結びついているため、PDFを1か所でも編集すればハッシュ値が変わり、検証は失敗します。注釈を足しただけでも同じです。訂正が必要なときは原本を上書きせず、訂正後のファイルを新しい版として保存し、その版に改めてタイムスタンプを付けます。元の版とトークンは残しておけば、何がいつ変わったかを後から説明できます。
関連記事
- 電子帳簿保存法に対応する文書管理システムとは?要件と選び方・自社開発の判断:タイムスタンプ連携を含めた保存システムの選定軸
- 文書管理とワークフローの連携設計|承認済み版の確定と電帳法要件の満たし方:版を確定させる時点と付与のタイミングの合わせ方
- ハッシュ化とは?暗号化との違いとパスワード保管・改ざん検知の仕組み:付与と検証の土台になるハッシュ関数の性質
- タイムスタンプとは?仕組み・電子署名との違いと電子帳簿保存法での要否:認定6事業者の一覧と付与期限の数え方の詳細
- 電子帳簿保存法の検索要件:ファイル名・索引簿・DB検索の3方式で実装する手順:同じ証憑テーブルに持たせる検索項目の設計