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

チャレンジレスポンスの検証

ここでは、Verify SDK を使用して取得したレスポンス(Nonce に対する署名値)と証明書を使って、レスポンス検証を行う方法を説明します。

あらかじめ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"
"google.golang.org/protobuf/proto"
)

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

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

// チャレンジとして送信したNonceです。
nonce = []byte{0xCA, 0xFE, 0xBA, 0xBE}

// レスポンス(Nonceに対する署名値)と証明書です。これらの値は、アプリ上で作成したものを何らかの方法で予め受け取っておいてください。
rawSignature = "HHyqoE8l0M4JS4AIsCO4i7kQvrgE89VIwr3FilTGBXa6HVqgJNZxo0C/gZu40e1cJOhGWIfTtciT8XNPOHkERPXhvfdBhEkn8do/HpfyNEBVKrPa0NwWRRjq0JlKPtJdhlpvd0hgQfEwwFSTAvVR1RMEmKCfmKPIBEYkwqMsbGXsgHx+5be68UCy07wltVg+3XuS3ir6sbF7W5Hr0QjuFuNRc/xnokqZYLk6l1fDeL/mBcUTTBjkEQdgSxnE11XJCF4zzs8ZHPx3rXBpbVb2h1LWmFkX8moz62jbkXnnJfUTS7rdLFuT7ulQfnUqGD7o9J9VzQYAlxlIlMroBy4X5g=="
rawCertificate = "MIIF0TCCBLmgAwIBAgIUO+9GnQAAAAAAACAAQAAAAAAAAAAwDQYJKoZIhvcNAQELBQAwYDELMAkGA1UEBhMCSlAxETAPBgNVBAoMCFA4Ti1NT0NLMSQwIgYDVQQLDBtQOE4gZm9yIHVzZXIgYXV0aGVudGljYXRpb24xGDAWBgNVBAsMD1BvY2tldFNpZ24gSW5jLjAeFw0yMjA2MDYwNDU2NTRaFw0yNzA2MDUwNDU2NTRaMGAxCzAJBgNVBAYTAkpQMREwDwYDVQQKDAhQOE4tTU9DSzEkMCIGA1UECwwbUDhOIGZvciB1c2VyIGF1dGhlbnRpY2F0aW9uMRgwFgYDVQQLDA9Qb2NrZXRTaWduIEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIkmPwccDsOcYTPcnzzwdYs8WCMLt/spdDJwy83Qq+6CU1bSorFIlVxJClNyjo23mj2s4hIfGIlU/uvJP9RQHKc2bsIQljSYSPnFemJeXtTCD9y3AMPiQkdTtYoMcr5KYLA/GKtcG9XW30OYGrkDsOb6oRSeBr642A/tE3cls2MScwV790usJ/f71lw4b3qJbFZtExFPaylZyfjC7iAyN1EJYVzDWB9luCBHJNAwYB0lAXFFnJxLSIcPB5a+JVFH+Otg9Xi2+/44ZyEVpWcByoO5M1CFpHE/0Bl5hTIOV0zpbPXEgf4f920Ial/ian4sDrCx9PoVGvyuoq4VtxDQRDAgMBAAGjggKBMIICfTAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwgcYGA1UdEgSBvjCBu6SBuDCBtTELMAkGA1UEBhMCSlAxMzAxBgNVBAoMKuODneOCseODg+ODiOOCteOCpOODs+ODouODg+OCr+OCteODvOODk+OCuTFFMEMGA1UECww844Od44Kx44OD44OI44K144Kk44Oz44Oi44OD44Kv44K144O844OT44K55Yip55So6ICF6Ki85piO55SoMSowKAYDVQQLDCHjg53jgrHjg4Pjg4jjgrXjgqTjg7PmoKrlvI/kvJrnpL4wga4GA1UdHwSBpjCBozCBoKCBnaCBmqSBlzCBlDELMAkGA1UEBhMCSlAxETAPBgNVBAoMCFA4Ti1NT0NLMSIwIAYDVQQLDBlQOE4gZm9yIGRpZ2l0YWwgc2lnbmF0dXJlMSAwHgYDVQQLDBdDUkwgRGlzdHJpYnV0aW9uIFBvaW50czEVMBMGA1UECwwMUHJlZmVjdHVyZS0wMRUwEwYDVQQDDAxDaXR5LTAgQ1JMRFAwMQYIKwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vbW9jay5wOG4ubG9jYWwwgYkGA1UdIwSBgTB/gBRArZuYxg6SX1/WCQS/u4Uxo1F3vaFkpGIwYDELMAkGA1UEBhMCSlAxETAPBgNVBAoMCFA4Ti1NT0NLMSQwIgYDVQQLDBtQOE4gZm9yIHVzZXIgYXV0aGVudGljYXRpb24xGDAWBgNVBAsMD1BvY2tldFNpZ24gSW5jLoIBATAdBgNVHQ4EFgQUjoev5nBmMBSoh10aYCciNq/H4c8wDQYJKoZIhvcNAQELBQADggEBABsQUVXVR3goyqi+xzMSlRrUYrQx6uOWe+7zFeHIaK17U0HcPJgj90g549s5yOimra0Nw/vuw93GepWgpbrxUXROzScAoJYgJT1I3ELsxO5dJSE4zMWkXS9g3jC0TjI8AGHhK2LzwfYfQV3lCKsaStfOmtiErzbUFwFTa6k4YCdNmNPVRwtrbuM0XGHExhN7lDRbMFG7Goja9GyOQbIRZw4p5pXu8Aq0G7SHDsWUVfIWPTWIwCS7/wQm6AnENO8xPpp1MPuTlmO7iKa7vyEcrrPDM9PYfCZaHrZkTbzfZVVVKJwLVqOmd08IAHSVxOSivLQ5V5TY4zvpEpg3ylxxPOU="
)

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
}

// Nonceのハッシュ値を計算します。
digest := sha256.Sum256(nonce)

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

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

// 利用者IDを取得します。
IdentifyUser: proto.Bool(true),
})

// リクエストに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("UserID: %s\n", response.Msg.User.Id)
return nil
}

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

検証に成功すると、以下のように結果が表示されます。 UserID は、証明書の種別や世代に依らず一意な利用者識別子です。 これを利用して、1 人 1 アカウントの実現や、当人認証によるログインを実装することができます。

Result: RESULT_OK
UserID: 4defded7-cf7b-4f76-a87c-be8c289f7b9a

なお、証明書に含まれる利用者 ID は、何らかの理由によって署名検証が失敗した場合でも API レスポンスに含まれます。

要確認

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


次のステップ

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