# 署名API

<br>

## **概要**
    
署名APIは、インターネット等で利用者が作成・送信した電子文書が「利用者が作成した真正なものであり、利用者が送信したものであること」を確かめるために署名検証を行うAPIです。
マイナンバーカードのICチップまたはスマートフォンのマイナンバーカードから署名用電子証明書を読み取り、利用者によって作成された電子文書を秘密鍵を使用して暗号化することで電子署名を生成します。
これにより、受領した電子文書の利用者の実在性、氏名・住所等を正確・確実に把握し、かつ、改ざんや送信否認のおそれがないものとして申請書等を安心して受け取ることができます。

## **アクセスコントロール**

<AccordionGroup>
    <Accordion title="マイナンバーカード">
        署名用電子証明書の暗証番号（6〜16桁の半角英数字）
        ※5回連続で署名用電子証明書の暗証番号を間違えた場合には、マイナンバーカードにロックがかかってしまいますのでご注意ください。
    </Accordion>
    <Accordion title="スマートフォンのマイナンバーカード">
        署名用電子証明書の暗証番号（6〜16桁の半角英数字）
        ※5回連続で署名用電子証明書の暗証番号を間違えた場合には、マイナンバーカードにロックがかかってしまいますのでご注意ください。
    </Accordion>
 </AccordionGroup>

## **処理の流れ**
<Tabs>
    <Tab title="対面">
        <Steps>
            <Step title="電子文書の作成（サービスプロバイダ事業者）">
                マイナンバーカードまたはスマートフォンのマイナンバーカードを読み取る前に、契約書や申し込み情報など、署名対象となる電子文書を作成します。
            </Step>
            <Step title="署名用電子証明書の読み取り（サービスプロバイダ事業者）">
                SDKを使用して利用者のマイナンバーカードまたはスマートフォンのマイナンバーカードを、ICカードリーダーまたは読み取り用スマートフォンのNFC機能で読み取り、6〜16桁の署名用電子証明書の暗証番号を入力することで署名用電子証明書のデータを取得します。
                
           ※スマートフォンのマイナンバーカード読み取りは、機種ごとに読み取り手順が変わります。
                <AccordionGroup>
                    <Accordion title="iPhoneのマイナンバーカードを読み取る">
                        <Steps>
                            <Step>Appleウォレットを起動し、マイナンバーカードを選択します。</Step>
                            <Step>Face IDまたはTouch IDによる認証を行います。</Step>
                            <Step>認証完了後、iPhoneの画面に「リーダーにかざしてください」の表示が出ている状態で、ICカードリーダーまたは読み取り用スマートフォンのNFC機能で読み取りを行います。</Step>
                        </Steps>
                    </Accordion>
                    <Accordion title="Androidスマホ用電子証明書を読み取る">
                        <Steps>
                            <Step>設定アプリより、NFC機能をオンにします。</Step>
                            <Step>NFC機能がオンになっていることを確認し、Android端末をICカードリーダーまたは読み取り用スマートフォンのNFC機能で読み取りを行います。</Step>
                            </Steps>
                    </Accordion>
                </AccordionGroup>
            </Step>
            <Step title="電子文書のハッシュ値生成（サービスプロバイダ事業者）">
                作成した電子文書から電子署名に使うハッシュ値をSDKで生成します。
        ※使用するハッシュ関数は、SHA-1、SHA-256、SHA-384、SHA-512のいずれかを指定します。
            </Step>
            <Step title="電子署名の生成（サービスプロバイダ事業者）">
                署名用電子証明書の秘密鍵を用いてハッシュ値から電子署名をSDKで生成します。サービスプロバイダ事業者は、生成されたハッシュ値、電子署名、署名用電子証明書、失効状態確認方式を指定してAPIでリクエストを送信します。
        ※デフォルト設定ではCRL方式による失効状態の確認が行われるため、OCSP方式を利用する場合は明示的に指定する必要があります。
            </Step>
            <Step title="署名検証（プラットフォーム事業者）">
                受信した電子署名を署名用電子証明書の公開鍵で検証し、復元したハッシュ値と元のハッシュ値を照合することで署名の正当性を検証します。なお、検証結果はAPIの応答として返却されます。
            </Step>
            <Step title="署名用電子証明書の有効性確認（プラットフォーム事業者）">
                署名検証後、署名用電子証明書をJ-LISに送信することで有効性確認を行います。ここまでの結果は証跡としてプラットフォーム事業者側のデータベースに保存され、管理されます。
            </Step>
            <Step title="処理結果の整形・返却（プラットフォーム事業者）">
                有効性確認後、署名検証および署名用電子証明書の有効性確認の結果をサービスプロバイダ事業者に返却します。
            </Step>
        </Steps>
    </Tab>
    <Tab title="非対面">
        <Steps>
            <Step title="電子文書の作成（サービスプロバイダ事業者）">
                マイナンバーカードを読み取る前に、契約書や申し込み情報など、署名対象となる電子文書を作成します。
            </Step>
            <Step title="署名用電子証明書の読み取り（サービスプロバイダ事業者）">
                SDKを使用して利用者のマイナンバーカードを、読み取り用スマートフォンのNFC機能で読み取り、6〜16桁の署名用電子証明書の暗証番号を入力することで署名用電子証明書のデータを取得します。
            </Step>
            <Step title="電子文書のハッシュ値生成（サービスプロバイダ事業者）">
                作成した電子文書から電子署名に使うハッシュ値をSDKで生成します。
        ※使用するハッシュ関数は、SHA-1、SHA-256、SHA-384、SHA-512のいずれかを指定します。
            </Step>
            <Step title="電子署名の生成（サービスプロバイダ事業者）">
                署名用電子証明書の秘密鍵を用いてハッシュ値から電子署名をSDKで生成します。サービスプロバイダ事業者は、生成されたハッシュ値、電子署名、署名用電子証明書、失効状態確認方式を指定してAPIでリクエストを送信します。
        ※デフォルト設定ではCRL方式による失効状態の確認が行われるため、OCSP方式を利用する場合は明示的に指定する必要があります。
            </Step>
            <Step title="署名検証（プラットフォーム事業者）">
                受信した電子署名を署名用電子証明書の公開鍵で検証し、復元したハッシュ値と元のハッシュ値を照合することで署名の正当性を検証します。なお、検証結果はAPIの応答として返却されます。
            </Step>
            <Step title="署名用電子証明書の有効性確認（プラットフォーム事業者）">
                署名検証後、署名用電子証明書をJ-LISに送信することで有効性確認を行います。ここまでの結果は証跡としてプラットフォーム事業者側のデータベースに保存され、管理されます。
            </Step>
            <Step title="処理結果の整形・返却（プラットフォーム事業者）">
                有効性確認後、署名検証および署名用電子証明書の有効性確認の結果をサービスプロバイダ事業者に返却します。
            </Step>
        </Steps>
    </Tab>
</Tabs>
      
 ## **シーケンス図**
    
<Tabs>
    <Tab title="対面">
```mermaid
    %%{init:{'theme':'natural'}}%%
    sequenceDiagram
    participant 利用者
    participant SDK
    participant サービスプロバイダ事業者
    participant プラットフォーム事業者
    participant J-LIS

    利用者->>サービスプロバイダ事業者: 申し込み情報の入力内容・サービス規約への同意の送信
    サービスプロバイダ事業者->>サービスプロバイダ事業者: 電子文書の作成
    サービスプロバイダ事業者->>SDK: 電子文書の送信<br>署名用電子証明書の暗証番号の要求
    SDK->>利用者: 電子文書の送信<br>署名用電子証明書の暗証番号の要求
    利用者->>利用者: 電子文書の確認
    利用者->>SDK: 署名用電子証明書の読み取り<br>暗証番号の入力
    SDK->>SDK: 署名用電子証明書の取得
    SDK->>SDK: 電子文書からハッシュ値を生成
    SDK->>SDK: ハッシュ値から電子署名を生成
    SDK->>サービスプロバイダ事業者: ハッシュ値・電子署名<br>署名用電子証明書の返却
    サービスプロバイダ事業者->>プラットフォーム事業者: ハッシュ値・電子署名<br>署名用電子証明書・有効性確認の方法の送信
    プラットフォーム事業者->>プラットフォーム事業者: 署名検証
    alt CRLの場合
        プラットフォーム事業者->>プラットフォーム事業者: 有効性確認
    else OCSPの場合
        プラットフォーム事業者->>J-LIS: 署名用電子証明書の送信
        J-LIS->>J-LIS: 有効性確認
        J-LIS->>プラットフォーム事業者: 失効情報の返却

    end
        プラットフォーム事業者->>プラットフォーム事業者: 証跡の保存
    プラットフォーム事業者->>サービスプロバイダ事業者: 処理結果の整形・返却
    サービスプロバイダ事業者->>利用者: 本人確認結果の表示などの処理
```
    </Tab>
    <Tab title="非対面">
```mermaid
    %%{init:{'theme':'natural'}}%%
    sequenceDiagram
    participant 利用者
    participant SDK
    participant サービスプロバイダ事業者
    participant プラットフォーム事業者
    participant J-LIS

    利用者->>サービスプロバイダ事業者: 申し込み情報の入力内容・サービス規約への同意の送信
    サービスプロバイダ事業者->>サービスプロバイダ事業者: 電子文書の作成
    サービスプロバイダ事業者->>SDK: 電子文書の送信<br>署名用電子証明書の暗証番号の要求
    SDK->>利用者: 電子文書の送信<br>署名用電子証明書の暗証番号の要求
    利用者->>利用者: 電子文書の確認
    利用者->>SDK: 署名用電子証明書の読み取り<br>暗証番号の入力
    SDK->>SDK: 署名用電子証明書の取得
    SDK->>SDK: 電子文書からハッシュ値を生成
    SDK->>SDK: ハッシュ値から電子署名を生成
    SDK->>サービスプロバイダ事業者: ハッシュ値・電子署名<br>署名用電子証明書の返却
    サービスプロバイダ事業者->>プラットフォーム事業者: ハッシュ値・電子署名<br>署名用電子証明書・有効性確認の方法の送信
    プラットフォーム事業者->>プラットフォーム事業者: 署名検証
    alt CRLの場合
        プラットフォーム事業者->>プラットフォーム事業者: 有効性確認
    else OCSPの場合
        プラットフォーム事業者->>J-LIS: 署名用電子証明書の送信
        J-LIS->>J-LIS: 有効性確認
        J-LIS->>プラットフォーム事業者: 失効情報の返却

    end
    プラットフォーム事業者->>プラットフォーム事業者: 証跡の保存
    プラットフォーム事業者->>サービスプロバイダ事業者: 処理結果の整形・返却
    サービスプロバイダ事業者->>利用者: 本人確認結果の表示などの処理
```
    </Tab>
</Tabs>


## **実装例**

<Tabs>
    <Tab title="iOS">
```swift        
// 署名用電子証明書の暗証番号（6-16桁）
let pin = "123456"

// 電子文書（署名対象データ）
let targetData = "署名対象データ".data(using: .utf8)!
        
// エンドポイント
let endpoint = "APIのエンドポイント"

// SDKの呼び出し
let reader = NFCReader(delegate: _NFCDelegate())

// 署名用電子証明書の取得・ハッシュ値生成・電子署名の生成
reader.getSignVerify(pin: pin, data: targetData, algorithm: .sha256) { (certDER, signature) in
    
    let parameters = """
    {
        "type": "SIGNATURE",
        "cert": "\(certDER.base64EncodedString())",
        "signature": "\(signature.base64EncodedString())",
        "hash": "\(targetData.sha256().base64EncodedString())",
        "algorithm": "SHA256"
    }
    """
    let postData = parameters.data(using: .utf8)
    
    // リクエスト作成
    var request = URLRequest(url: URL(string: endpoint)!, timeoutInterval: Double.infinity)
    request.addValue("<token>", forHTTPHeaderField: "X-PTS-API-Key")
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    request.httpBody = postData
    
    // リクエストの送信・エラー処理の記述
}

```
    </Tab>
    <Tab title="Android">
```kotlin
// 署名用電子証明書の暗証番号（6-16桁）
val pin = "123456"

// 電子文書（署名対象データ）
val targetData = "署名対象データ".toByteArray(Charsets.UTF_8)

// エンドポイント
val endpoint = "APIのエンドポイント"

// SDKの呼び出し
val reader = NFCReader(delegate = NFCDelegate())

// 署名用電子証明書の取得・ハッシュ値生成・電子署名の生成
reader.getSignVerify(pin = pin, data = targetData, algorithm = SHA256) { certDER, signature ->
    val parameters = """
    {
        "type": "SIGNATURE",
        "cert": "${Base64.encodeToString(certDER, Base64.NO_WRAP)}",
        "signature": "${Base64.encodeToString(signature, Base64.NO_WRAP)}",
        "hash": "${Base64.encodeToString(targetData.sha256(), Base64.NO_WRAP)}",
        "algorithm": "SHA256"
    }
    """.trimIndent()
    
    val mediaType = "application/json".toMediaType()
    val requestBody = parameters.toRequestBody(mediaType)
    
    // リクエスト作成
    val request = Request.Builder()
        .url(endpoint)
        .post(requestBody)
        .addHeader("X-PTS-API-Key", "<token>")
        .addHeader("Content-Type", "application/json")
        .build()
    
    // リクエストの送信・エラー処理の記述
}
```
    </Tab>
    <Tab title="React Native">
```typescript
// 署名用電子証明書の暗証番号（6-16桁）
const pin = '123456';

// 電子文書（署名対象データ）
const targetData = '署名対象データ';

// エンドポイント
const endpoint = 'APIのエンドポイント';

// SDKの呼び出し
// 署名用電子証明書の取得・ハッシュ値生成・電子署名の生成
const { signedData, certData } = TrustServices.getSignVerify(
  pin,
  targetData,
  'sha256'
);
const hashBase64 = computeHash(targetData, 'sha256');
const algorithm = getAlgorithmName('sha256'); // "SHA256"

const parameters = {
  type: 'SIGNATURE',
  cert: certData,
  signature: signedData,
  hash: hashBase64,
  algorithm: algorithm
};

// リクエスト作成
const request = new Request(endpoint, {
  method: 'POST',
  headers: {
    'X-PTS-API-Key': '<token>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(parameters),
});

// リクエストの送信・エラー処理の記述
```
    </Tab>
    <Tab title="Windows">
```cpp
// 署名用電子証明書の暗証番号（6-16桁）
std::string pin = "123456";

// 電子文書（署名対象データ）
std::string targetDataStr = "署名対象データ";
std::vector<unsigned char> targetData(targetDataStr.begin(), targetDataStr.end());

// エンドポイント
std::string endpoint = "APIのエンドポイント";

// SDKの呼び出し
NFCReader reader(delegate);

// 署名用電子証明書の取得・ハッシュ値生成・電子署名の生成
reader.getSignVerify(pin, targetData, SHA256, [&](const std::vector<unsigned char>& certDER, const std::vector<unsigned char>& signature) {
    Json::Value parameters;
    parameters["type"] = "SIGNATURE";
    parameters["cert"] = base64_encode(certDER);
    parameters["signature"] = base64_encode(signature);
    parameters["hash"] = base64_encode(sha256(targetData));
    parameters["algorithm"] = "SHA256";
    
    std::string postData = Json::writeString(Json::StreamWriterBuilder(), parameters);
    
    // リクエスト作成
    CURL* curl = curl_easy_init();
    if (curl) {
        struct curl_slist* headers = curl_slist_append(nullptr, "X-PTS-API-Key:  <token>");
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_URL, endpoint.c_str());
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        
        // リクエストの送信・エラー処理の記述
    }
});
        
```
    </Tab>
</Tabs>
    
<br>

