

# Generate, translate and verify PIN data
<a name="data-operations.pindata"></a>

PIN data functions allow you to generate random pins, pin verification values (PVV) and validate inbound encrypted pins against PVV or PIN Offsets. 

Pin translation allows you to translate a pin from one working key to another without exposing the pin in clear text as specified by PCI PIN Requirement 1.

**Note**  
 As PIN generation and validation are typically issuer functions and PIN translation is a typical acquirer function, we recommend that you consider least priviledged access and set policies appropriately for your systems use case. 

**Topics**
+ [Translate PIN data](translate-pin-data.md)
+ [Generate PIN data](generate-pin-data.md)
+ [Verify PIN data](verify-pin-data.md)

# Translate PIN data
<a name="translate-pin-data"></a>

Translate PIN data functions are used for translating encrypted PIN data from one set of keys to another without the encrypted data leaving the HSM. It is used for P2PE encryption where the working keys should change but the processing system either doesn't need to, or is not permitted to, decrypt the data. The primary inputs are the encrypted data, the encryption key used to encrypt the data, the parameters used to generate the input values. The other set of inputs are the requested output parameters such as the key to be used to encrypt the output and the parameters used to create that output. The primary outputs are a newly encrypted dataset as well as the parameters used to generate it. 

**Note**  
For PCI compliance, the incoming and outgoing PrimaryAccountNumber values must match. Translating a PIN from one PAN to another is not permitted.

**Topics**
+ [PIN from PEK to DUKPT](#crypto-ops-pindata.pektodukpt)
+ [PIN from PEK to PEK](#crypto-ops-pindata.pektopek)

## PIN from PEK to DUKPT
<a name="crypto-ops-pindata.pektodukpt"></a>

**Example**  
In this example, we will translate a PIN from an AES ISO 4 PIN Block using the [DUKPT](terminology.md#terms.dukpt) to PEK TDES encryption using ISO 0 PIN block. This is common where a payment terminal encrypts a pin in ISO 4 and then it may be translated back to TDES for downstream processing if the next connection doesn't yet support AES.   

```
$ aws payment-cryptography-data translate-pin-data --encrypted-pin-block "AC17DC148BDA645E" --outgoing-translation-attributes=IsoFormat0='{PrimaryAccountNumber=171234567890123}' --outgoing-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt  --incoming-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/4pmyquwjs3yj4vwe --incoming-translation-attributes IsoFormat4="{PrimaryAccountNumber=171234567890123}" --incoming-dukpt-attributes KeySerialNumber="FFFF9876543210E00008"  
```

```
    {
            "PinBlock": "1F4209C670E49F83E75CC72E81B787D9",
            "KeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt",
            "KeyCheckValue": "7CC9E2"
        }
```

## PIN from PEK to PEK
<a name="crypto-ops-pindata.pektopek"></a>

**Example**  
In this example, we translate a PIN encrypted under one PEK (PIN Encryption Key) to another PEK. This is commonly used when routing transactions between different systems or partners that use different encryption keys, while maintaining PCI PIN compliance by keeping the PIN encrypted throughout the process. Both keys use TDES 3KEY encryption in this example, but a variety of options are available including AES ISO-4 to TDES ISO-0, DUKPT to PEK, or AS2805 to PEK.  

```
$ aws payment-cryptography-data translate-pin-data --encrypted-pin-block "AC17DC148BDA645E" \
    --incoming-translation-attributes IsoFormat0='{PrimaryAccountNumber=171234567890123}' \
    --incoming-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt \
    --outgoing-translation-attributes IsoFormat0='{PrimaryAccountNumber=171234567890123}' \
    --outgoing-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/alsuwfxug3pgy6xh
```

```
{
    "PinBlock": "E8F2A6C4D1B93E7F",
    "KeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/alsuwfxug3pgy6xh",
    "KeyCheckValue": "9A325B"
}
```
The output PIN block is now encrypted under the second PEK and can be safely transmitted to the downstream system that holds the corresponding key.

# Generate PIN data
<a name="generate-pin-data"></a>

Generate PIN data functions are used for generating PIN-related values, such as [PVV](terminology.md#terms.pvv) and pin block offsets used for validating pin entry by users during transaction or authorization time. This API can also generate a new random pin using various algorithms.

# Generate a random pin and matching Visa PVV
<a name="generate-pvv-random"></a>

**Example**  
In this example, we will generate a new (random) pin where the outputs will be an encrypted `PIN block` (PinData.PinBlock) and a `PVV` (pinData.Offset). The key inputs are `PAN`, the `Pin Verification Key`, the `Pin Encryption Key` and the `PIN block format`.   
 This command requires that the key is of type `TR31_V2_VISA_PIN_VERIFICATION_KEY`.   

```
$ aws payment-cryptography-data generate-pin-data --generation-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2 --encryption-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt --primary-account-number 171234567890123 --pin-block-format ISO_FORMAT_0 --generation-attributes VisaPin={PinVerificationKeyIndex=1}
```

```
{
            "GenerationKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2",
            "GenerationKeyCheckValue": "7F2363",
            "EncryptionKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt",
            "EncryptionKeyCheckValue": "7CC9E2",
            "EncryptedPinBlock": "AC17DC148BDA645E",
            "PinData": {
                "VerificationValue": "5507"
            }
        }
```

# Generate a Visa PVV for a known pin
<a name="generate-pvv-givenpin"></a>

**Example**  
In this example, we will generate a PVV for a given (encrypted) pin. An encrypted pin may be received upstream such as from a payment terminal or from a cardholder using the [ user selectable pin flow](https://github.com/aws-samples/samples-for-payment-cryptography-service/tree/main/python_sdk_example/ecdh_flows). The key inputs are `PAN`, the `Pin Verification Key`, the `Pin Encryption Key`, the `Encrypted Pin Block` and the `PIN block format`.   

```
$ aws payment-cryptography-data generate-pin-data --generation-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2 --encryption-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt --primary-account-number 171234567890123 --pin-block-format ISO_FORMAT_0 --generation-attributes VisaPinVerificationValue={PinVerificationKeyIndex=1,EncryptedPinBlock=AA584CED31790F37}
```

```
{
            "GenerationKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2",
            "GenerationKeyCheckValue": "7F2363",
            "EncryptionKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt",
            "EncryptionKeyCheckValue": "7CC9E2",
            "EncryptedPinBlock": "AC17DC148BDA645E",
            "PinData": {
                "VerificationValue": "5507"
            }
        }
```

# Generate IBM3624 pin offset for a pin
<a name="generate-ibm3624"></a>

 IBM 3624 PIN Offset also sometimes called the IBM method. This method generates a natural/intermediate PIN using the validation data (typically the PAN) and a PIN Key (PVK). Natural pins are effectively a derived value and being deterministic are very efficient to handle for an issuer because no pin data needs to be stored at a cardholder level. The most obvious con is that this scheme doesn't account for cardholder selectable or random pins. To allow for those types of pins, an offset algorithm was added to the scheme. The offset represents the difference between the user selected(or random) pin and the natural key. The offset value is stored by the card issuer or card processor. At transaction time, the AWS Payment Cryptography service internally recalculates the natural pin and applies the offset to find the pin. It then compares this against the value provided by the transaction authorization. 

Several options exist for IBM3624:
+ `Ibm3624NaturalPin` will output the natural pin and an encrypted pin block
+ `Ibm3624PinFromOffset` will generate an encrypted pin block given an offset
+ `Ibm3624RandomPin` will generate a random pin and then the matching offset and encrypted pin block.
+  `Ibm3624PinOffset` generates the pin offset given a user selected pin.

Internal to AWS Payment Cryptography, the following steps are performed:
+ Pad the provided pan to 16 characters. If <16 are provided, pad on the right hand side using the provided padding character.
+ Encrypts the validation data using the PIN generation key.
+ Decimalize the encrypted data using the decimalization table. This maps hexidecimal digits to decimal digits for instance 'A' may map to 9 and 1 may map to 1.
+ Get the first 4 digits from a hexidecimal representation of the output. This is the natural pin.
+ If a user selected or random pin was generated, modulo subtract the natural pin with customer pin. The result is the pin offset.

**Topics**
+ [Example: Generate IBM3624 pin offset for a pin](#generate-ibm3624-random-example)

## Example: Generate IBM3624 pin offset for a pin
<a name="generate-ibm3624-random-example"></a>

In this example, we will generate a new (random) pin where the outputs will be an encrypted `PIN block` (PinData.PinBlock) and an `IBM3624` offset value (pinData.Offset). The inputs are `PAN`, validation data (typically the pan), padding character, the `Pin Verification Key`, the `Pin Encryption Key` and the `PIN block format`.

 This command requires that the pin generation key is of type `TR31_V1_IBM3624_PIN_VERIFICATION_KEY` and the encryption key is of type `TR31_P0_PIN_ENCRYPTION_KEY` 

**Example**  
The following example shows generating a random pin then outputting the encrypted pin block and IBM3624 offset value using Ibm3624RandomPin   

```
$ aws payment-cryptography-data generate-pin-data --generation-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2 --encryption-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt --primary-account-number 171234567890123 --pin-block-format ISO_FORMAT_0 --generation-attributes Ibm3624RandomPin="{DecimalizationTable=9876543210654321,PinValidationDataPadCharacter=D,PinValidationData=171234567890123}"
```

```
{
              "GenerationKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2",
              "GenerationKeyCheckValue": "7F2363",
              "EncryptionKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt",
              "EncryptionKeyCheckValue": "7CC9E2",
              "EncryptedPinBlock": "AC17DC148BDA645E",
              "PinData": {
                  "PinOffset": "5507"
              }
          }
```

# Verify PIN data
<a name="verify-pin-data"></a>

Verify PIN data functions are used for verifying whether a pin is correct. This typically involves comparing the pin value previously stored against what was entered by the cardholder at a POI. These functions compare two values without exposing the underlying value of either source. 

## Validate encrypted PIN using PVV method
<a name="verify-pin-data.pvv-example"></a>

**Example**  
In this example, we will validate a PIN for a given PAN. The PIN is typically provided by the cardholder or user during transaction time for validation and is compared against the value on file (the input from the cardholder is provided as an encrypted value from the terminal or other upstream provider). In order to validate this input, the following values will also be provided at runtime: The key used to encrypt the input pin (this is often an `IWK`), `PAN` and the value to verify against (either a `PVV` or `PIN offset`).   
If AWS Payment Cryptography is able to validate the pin, an http/200 is returned. If the pin is not validated, it will return an http/400.  

```
$ aws payment-cryptography-data verify-pin-data --verification-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2 --encryption-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt --primary-account-number 171234567890123 --pin-block-format ISO_FORMAT_0  --verification-attributes VisaPin="{PinVerificationKeyIndex=1,VerificationValue=5507}" --encrypted-pin-block AC17DC148BDA645E 
```

```
        {
            "VerificationKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2",
            "VerificationKeyCheckValue": "7F2363",
            "EncryptionKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt",
            "EncryptionKeyCheckValue": "7CC9E2",
    
        }
```

## Validate encrypted PIN using PVV method - error bad pin
<a name="verify-pin-data.pvv-example.badpin"></a>

**Example**  
In this example, we will attempt to validate a PIN for a given PAN but it will fail due to the pin being incorrect.   
When using SDKs, this appears as \$1"Message":"Pin block verification failed.","Reason":"INVALID\$1PIN"\$1  

```
$ aws payment-cryptography-data verify-pin-data --verification-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2 --encryption-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt --primary-account-number 171234567890123 --pin-block-format ISO_FORMAT_0  --verification-attributes VisaPin="{PinVerificationKeyIndex=1,VerificationValue=9999}" --encrypted-pin-block AC17DC148BDA645E 
```

```
        An error occurred (VerificationFailedException) when calling the VerifyPinData operation: Pin block verification failed. 
```

## Validate encrypted PIN using PVV method - error bad inputs
<a name="verify-pin-data.pvv-example.badkey"></a>

**Example**  
In this example, we will attempt to validate a PIN for a given PAN but it will fail due to bad inputs and the incoming data was not a valid pin. Common causes are: 1/wrong key being used 2/input parameters such as pan or pin block format are incorrect 3/pin block is corrupted.   

```
$ aws payment-cryptography-data verify-pin-data --verification-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2 --encryption-key-identifier  --primary-account-number 171234567890123 --pin-block-format ISO_FORMAT_0  --verification-attributes VisaPin="{PinVerificationKeyIndex=1,VerificationValue=9999}" --encrypted-pin-block AC17DC148BDA645E 
```

```
        An error occurred (ValidationException) when calling the VerifyPinData operation: Pin block provided is invalid. Please check your input to ensure all field values are correct.
```

# Validate a PIN against previously stored IBM3624 pin offset
<a name="verify-pin-data.ibm3624-example"></a>

In this example, we will validate a cardholder provided PIN against the pin offset stored on file with the card issuer/processor. The inputs are similar to [Generate IBM3624 pin offset for a pin](generate-ibm3624.md) with the additional of the encrypted pin provided by the payment terminal (or other upstream provider such as card network). If the pin matches, the api will return http 200. where the outputs will be an encrypted `PIN block` (PinData.PinBlock) and an `IBM3624` offset value (pinData.Offset). 

 This command requires that the pin generation key is of type `TR31_V1_IBM3624_PIN_VERIFICATION_KEY` and the encryption key is of type `TR31_P0_PIN_ENCRYPTION_KEY` 

**Example**  

```
$ aws payment-cryptography-data generate-pin-data --generation-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2 --encryption-key-identifier arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt --primary-account-number 171234567890123 --pin-block-format ISO_FORMAT_0 --generation-attributes Ibm3624RandomPin="{DecimalizationTable=9876543210654321,PinValidationDataPadCharacter=D,PinValidationData=171234567890123}"
```

```
{
"GenerationKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/37y2tsl45p5zjbh2",
"GenerationKeyCheckValue": "7F2363",
"EncryptionKeyArn": "arn:aws:payment-cryptography:us-east-2:111122223333:key/ivi5ksfsuplneuyt",
"EncryptionKeyCheckValue": "7CC9E2",
"EncryptedPinBlock": "AC17DC148BDA645E",
"PinData": {
  "PinOffset": "5507"
}
}
```