メインコンテンツまでスキップ

署名検証

ここでは、Verify SDK を使用して取得した署名値と証明書を使って、署名検証を行う方法を説明します。

あらかじめAPI の利用開始を完了し、API トークンを取得しておいてください。

シーケンス

アプリとバックエンドの連携

Verify SDK を用いて取得した署名値と証明書は、何らかの方法でバックエンドサーバーに共有して署名検証を行ってください。

以下の実装例では、アプリとバックエンドの間での連携については省略しています。 実際のアプリケーションの実装例については、サンプルアプリをご覧ください。

要確認

Verify API の利用は、必ず SP 事業者で管理するサーバを経由して行ってください。 API トークンをアプリケーションに含めて配布することは、Verify API の不正利用ひいては JPKI への不正なアクセスにつながるため、絶対に行わないでください

実装例

クライアントライブラリのセットアップ方法は、クライアントライブラリをご参照ください。

package main

import (
"context"
"crypto/sha256"
"encoding/base64"
"fmt"
"log"
"net/http"

"buf.build/gen/go/pocketsign/apis/connectrpc/go/pocketsign/verify/v2/verifyv2connect"
verifyv2 "buf.build/gen/go/pocketsign/apis/protocolbuffers/go/pocketsign/verify/v2"
"connectrpc.com/connect"
)

var (
// APIエンドポイントを指定します。この値は環境によって異なります。
baseUrl = "https://verify.mock.p8n.app"

// Verify APIのトークンです。ご自身のトークンに置き換えてください。
token = "<YOUR_API_TOKEN>"

// 署名対象のドキュメントです。署名作成時と同じものを指定しています。
document = "Hello, world!"

// 署名値と証明書です。これらの値は、アプリ上で作成したものを何らかの方法で予め受け取っておいてください。
rawSignature = "n4bVa46x6/Ud44p7+zHMPpsTjZG7yqtnqc2WlcrOD738q+K61FdMy0aezKMsIZp8UaXanfRDExwRxHDsV1n2fACLKdNkWilNrGhOq9QqlNy5w8+n7ax2O5CQ1hiPKPjZo1wlecDl8D1z2n5ePL/VtszdqZ95QyHvPKYzE5yeDwaCd9QHMtxvbd7qkaac0RujRSdO9MUE4PoKz1YmRieysOIIf0cwHTUWmTy+++UA7itHwp/pPhiz2QWY0QGGMuDfBclISD1wuzqcXSAqOooCBOga7iqOKArYmCyRnAVUtOZJ0TKPnijhrlLe33cyvGR58YC6yBv4i9gnjuIQ7j1fZQ=="
rawCertificate = "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"
)

func run() error {
// Base64をデコードしてバイト列にします。
signature, err := base64.StdEncoding.DecodeString(rawSignature)
if err != nil {
return err
}
certificate, err := base64.StdEncoding.DecodeString(rawCertificate)
if err != nil {
return err
}

// 文書のハッシュ値を計算します。
digest := sha256.Sum256([]byte(document))

// 署名検証リクエストを作成します。
request := connect.NewRequest(&verifyv2.VerifyRequest{
Signature: signature,
Certificate: certificate,

// 作成したハッシュ値を送信します。もし、間違った内容に署名されている場合はハッシュ値が一致しないため、検証に失敗します。
Digest: digest[:],
HashAlgorithm: verifyv2.Verification_HASH_ALGORITHM_SHA256,
})

// リクエストにAPIトークンを設定します。
request.Header().Set("Authorization", "Bearer "+token)

// APIクライアントを作成します。
client := verifyv2connect.NewVerificationServiceClient(http.DefaultClient, baseUrl)

// 署名検証リクエストを送信します。
response, err := client.Verify(context.Background(), request)
if err != nil {
return err
}

// 結果を表示します。
fmt.Printf("Result: %s\n", response.Msg.Verification.Result)
fmt.Printf("CommonName: %s\n", response.Msg.CertificateContent.GetJpkiCardDigitalSignatureContent().CommonName)
return nil
}

func main() {
if err := run(); err != nil {
log.Fatalln(err)
}
}

リクエストに成功すると、以下のように結果が表示されます。

Result: RESULT_OK
CommonName: 原 智子

なお、証明書に含まれる基本 4 情報(氏名、住所、生年月日、性別)は、何らかの理由によって署名検証が失敗した場合でも API レスポンスに含まれます。

要確認

SP 事業者は、証明書の生データの保持が禁じられています。 データの保存について十分ご注意いただき、Verify API に送信後は速やかに削除するようにご実装ください。


次のステップ

署名検証時に作成される検証 ID を利用し、保存された署名を取得して過去に行った署名の確認を行いましょう。

その他、API の詳しい使い方やエラーの詳細等については、API リファレンスをご覧ください。