> ## Documentation Index
> Fetch the complete documentation index at: https://docs.enfuce.com/llms.txt
> Use this file to discover all available pages before exploring further.

# View PIN

> This operation retrieves card PIN encrypted with temporary PIN encryption key (tzpk) and tzpk encrypted
with the provided RSA public key.

**Note:** The card-holder device must be generating the RSA key, and must not allow any other system to
access the private RSA key. The RSA key should be a temporary one-time use key.

### Example flow
#### Step 1, executed on the CARD-HOLDER DEVICE, generating an RSA key pair
    // generate RSA key pair
    var kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    var keyPair = kpg.generateKeyPair();
    var publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());

#### Step 2, executed on the CLIENT BACK-END, requesting the encrypted PIN from the API
    // controlId received from pincontrol API
    var controlId = "83fa5f55-3dd7-453a-8233-4242a6bad179";

    // public RSA key, generated by the card-holder device in Step 1
    var publicKey = // fetched from the device

    // make request
    var pinResponse = pinApiClient.post()
            .uri("/pin/v3/view?auditUser={user}", "test")
            .bodyValue(Map.of(
                    "controlId", controlId,
                    "publicKey", publicKey
            ))
            .retrieve()
            .bodyToMono(ViewPinResponse.class)
            .block();

#### Step 3, executed on the CARD-HOLDER DEVICE, decrypting the PIN
    // response from the API call done in Step 2, given by the backend
    var pinResponse = // given by the backend

    // decrypt received tzpk with private key
    var rsa = Cipher.getInstance("RSA/ECB/OAEPPadding");
    rsa.init(Cipher.DECRYPT_MODE, keyPair.getPrivate(), new OAEPParameterSpec("SHA-256", "MGF1",
                MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
    var decryptedTzpk = rsa.doFinal(Base64.getDecoder().decode(pinResponse.getTzpk()));
    // convert double-length key to triple-length - used if the library support only triple-length 3DES
    var tzpk = new byte[24];
    System.arraycopy(decryptedTzpk, 0, tzpk, 0, 16);
    System.arraycopy(decryptedTzpk, 0, tzpk, 16, 8);
    // decrypt pinBlock with tzpk
    var des = Cipher.getInstance("DESede/ECB/NoPadding");
    des.init(Cipher.DECRYPT_MODE, new SecretKeySpec(tzpk, "DESede"));
    var decryptedPinBlock = Hex.toHexString(des.doFinal(Base64.getDecoder().decode(pinResponse.getPinBlock())));




## OpenAPI

````yaml pin post /v3/view
openapi: 3.0.3
info:
  description: >
    Endpoint for viewing and setting PIN.


    There are three different methods for operating with card PIN:

    - Using a pre-shared 3DES key with Enfuce

    - Using public key cryptography (PKI)

    - Using the web view solution, described in the pincontrol API


    ## PCI compliance

    Processing PIN codes is controlled with strict compliance regulations by the
    card schemes. There are multiple ways to

    access the PIN in Enfuce's APIs depending on the client solution, and
    whether the client is a card schema member

    themselves and therefore responsible for compliance.


    The least complex way to take this functionality into use is to use the
    pincontrol API, since with that the entire 

    PIN transport mechanism is handled by Enfuce. Please see the pincontrol API
    documentation for this option.


    In the API described in this document, there are two solutions, a PKI
    approach, and a pre-shared key approach.


    The PKI approach, implemented correctly, will avoid exposing PIN codes to
    the client's back-end systems, but the

    PIN will still be processed by the card-holder device. This means that the
    software running on the device may need

    to be assessed for security and compliance.


    The pre-shared key approach will expose the PIN code to the client's
    back-end and can only be used by customers

    responsible for PIN handling towards the card scheme.
  version: '1'
  title: Card PIN API
  contact:
    name: Enfuce Financial Services
    url: https://enfuce.com
    email: info@enfuce.com
  x-logo:
    url: https://developer.enfuce.com/images/enfuce.svg
    altText: Enfuce logo
servers:
  - url: >-
      https://integration-api-cat1.{{environment}}.ext.{{realm}}.cia.enfuce.com/pin
  - url: https://integration-api-cat1.live.ext.prod.cia.enfuce.com/pin
    description: Live environment
security: []
tags:
  - name: PIN operations with pre-shared key
    description: >-
      <p>Endpoint for card PIN operations using pre-shared
      key.</p><p><strong>Note:</strong> If this endpoint is used, the client
      (that decrypts the PIN block and thus has access to the clear PIN) must be
      responsible for PIN handling towards the card scheme.</p>
  - name: PIN operations using PKI
    description: >-
      <p>Endpoint for Card PIN operations using public key
      cryptography.</p><p><strong>Note:</strong> If this endpoint is used, the
      client must make sure that the RSA key pair is generated and used by the
      card-holder device, giving no access to the private RSA key to any other
      system. This way, no other system will have any means to access the PIN
      code.</p>
paths:
  /v3/view:
    post:
      tags:
        - PIN operations using PKI
      summary: View PIN
      description: >
        This operation retrieves card PIN encrypted with temporary PIN
        encryption key (tzpk) and tzpk encrypted

        with the provided RSA public key.


        **Note:** The card-holder device must be generating the RSA key, and
        must not allow any other system to

        access the private RSA key. The RSA key should be a temporary one-time
        use key.


        ### Example flow

        #### Step 1, executed on the CARD-HOLDER DEVICE, generating an RSA key
        pair
            // generate RSA key pair
            var kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(2048);
            var keyPair = kpg.generateKeyPair();
            var publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());

        #### Step 2, executed on the CLIENT BACK-END, requesting the encrypted
        PIN from the API
            // controlId received from pincontrol API
            var controlId = "83fa5f55-3dd7-453a-8233-4242a6bad179";

            // public RSA key, generated by the card-holder device in Step 1
            var publicKey = // fetched from the device

            // make request
            var pinResponse = pinApiClient.post()
                    .uri("/pin/v3/view?auditUser={user}", "test")
                    .bodyValue(Map.of(
                            "controlId", controlId,
                            "publicKey", publicKey
                    ))
                    .retrieve()
                    .bodyToMono(ViewPinResponse.class)
                    .block();

        #### Step 3, executed on the CARD-HOLDER DEVICE, decrypting the PIN
            // response from the API call done in Step 2, given by the backend
            var pinResponse = // given by the backend

            // decrypt received tzpk with private key
            var rsa = Cipher.getInstance("RSA/ECB/OAEPPadding");
            rsa.init(Cipher.DECRYPT_MODE, keyPair.getPrivate(), new OAEPParameterSpec("SHA-256", "MGF1",
                        MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
            var decryptedTzpk = rsa.doFinal(Base64.getDecoder().decode(pinResponse.getTzpk()));
            // convert double-length key to triple-length - used if the library support only triple-length 3DES
            var tzpk = new byte[24];
            System.arraycopy(decryptedTzpk, 0, tzpk, 0, 16);
            System.arraycopy(decryptedTzpk, 0, tzpk, 16, 8);
            // decrypt pinBlock with tzpk
            var des = Cipher.getInstance("DESede/ECB/NoPadding");
            des.init(Cipher.DECRYPT_MODE, new SecretKeySpec(tzpk, "DESede"));
            var decryptedPinBlock = Hex.toHexString(des.doFinal(Base64.getDecoder().decode(pinResponse.getPinBlock())));
      operationId: viewPinPubKeyV3
      parameters:
        - name: auditUser
          in: query
          description: The audit user to log the request
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/viewPinRequest'
        description: The related PIN control request data
        required: true
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/viewPinResponse'
        '401':
          $ref: '#/components/responses/error401'
        '403':
          $ref: '#/components/responses/error403'
        '404':
          $ref: '#/components/responses/controlIdNotFoundResponse'
        '500':
          $ref: '#/components/responses/error500'
components:
  schemas:
    viewPinRequest:
      type: object
      properties:
        controlId:
          type: string
          description: Control ID received from PIN control API.
          example: 83fa5f55-3dd7-453a-8233-4242a6bad179
        publicKey:
          type: string
          description: >
            RSA public key under which the received temporary PIN encryption key
            (tzpk) will be encrypted.

            Key should be base64-encoded, without any begin or end markers.
          example: >-
            MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP7yu/kPSEPHjqsUYIfarstoX4mx9PeJPZl/2zYFbN3dOAk0YnJYYC5udW+fkfNoaj2cf20XMrXGAatK/N30P9YoksJg8SINss+zn+/suDL/cRDXnVvYUn8fHwMcNNFYx7RbpYGaZHqshp5D96yfTTESu90nP8wrnjXH8iY4JIewIDAQAB
      required:
        - controlId
        - publicKey
      title: viewPinRequest
    viewPinResponse:
      type: object
      properties:
        pinBlock:
          type: string
          description: >-
            ISO format 1 PIN block 3DES encrypted with temporary PIN encryption
            key (tzpk). Base64 encoded.
          example: tACuB41yyfU=
        tzpk:
          type: string
          description: >-
            Temporary PIN encryption key, encrypted using the RSA public key
            provided. Base64 encoded.
          example: >-
            i6IWYm4FzTTBrtGF0FFdcHjEEQh8X3qCUcKkNgIXs2R4jLhECfoUHULWoyUu8T9R90MFZnPOuY5tel1Pww4iyKpRG2ChAwPWaHO2g0j9/xKYDBQHY57HklwBdazp03qU9vJIbmwpEOkrJIW1AW7FpypY4amoO565bCg2WfyG69U=
      required:
        - pinBlock
        - tzpk
      title: viewPinResponse
    errorResponse:
      type: object
      properties:
        code:
          type: string
          description: An error code indicating what kind of error. I.e. HTTP error code
        message:
          type: string
          description: Error message in human-readable format
        id:
          type: string
          format: uuid
          description: Unique error identifier
        errorCode:
          type: string
          description: Enfuce code for a specific error type
        errorType:
          type: string
          description: Error type
          enum:
            - STATIC_VALIDATION_ERROR
            - DYNAMIC_VALIDATION_ERROR
            - INTEGRATION_ERROR
            - SECURITY_ERROR
            - UNEXPECTED_ERROR
        errorReason:
          type: string
          description: Free-form text explaining the error reason
        timestamp:
          type: string
          format: date-time
          description: Datetime when error occurred
  responses:
    error401:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/errorResponse'
    error403:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/errorResponse'
    controlIdNotFoundResponse:
      description: Control id does not exist or is expired
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/errorResponse'
    error500:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/errorResponse'

````