Card PIN management

Introduction

Physical cards have an additional security feature i.e. PINs (Personal Identification Number). It is a number used to verify the identity of the cardholder and make transactions more secure. The PIN is required to validate the cardholder when the physical card is used on the terminals (like POS or ATM). Initially a random PIN is set for a newly activated card. The initial random PIN can be securely retrieved and presented to the cardholder through a cardholder facing app. The nCore platform also provides the feature to change the card PIN if the cardholder wishes to set his own preferred PIN.
The length of the PIN to support can be set on the card product. To maintain security, the nCore platform implements PIN security standards which require PINs to be random PIN values and certain PIN values (e.g. 1111, 2222, 3333, 1234 etc.) are considered as weak PINs and cannot be used. The nCore platform maintains a table of weak PINs, the PINs to be set are compared against the weak PINs table whenever a change PIN request is received from the authorized cardholders.
If the cardholder’s entered PIN is present in the weak PINs table then the change PIN request will be declined. A PIN is treated as a password and it should be kept secret to prevent unauthorized access to cardholder's accounts and related information.

Types of PINs

There are two types of card PINs and both have different validation processes as given below.
  • An online PIN is entered by the cardholder, then it is transmitted along with the card details to the nCore platform via the merchant acquirer system for authentication. The online PIN is not stored on the card. The nCore platform receives the authentication request in real time from the card network, the platform validates the PIN, then confirms to the merchant terminal where the card is inserted.
  • An offline PIN is entered by the cardholder, then transferred in encrypted form to the card’s integrated chip where the PIN is stored. The chip uses its internal procedures to validate and confirm the PIN to the merchant terminal where the card is inserted without transmitting it in real time to the issuer.
Please note that the Card PIN management features (such as get card PIN and change card PIN) are available for PCI DSS compliant customers. nCore platform provides a set of PCI widgets for non-PCI DSS compliant customers. For further information please refer to the PCI Widget section.
Card PIN Management APIs
There are some pre-requisites, which you have to know before dealing with card PIN management. It is preferred to have knowledge of such cryptographic algorithms as 3DES, AES and RSA . Also you should have an understanding of such concepts as encryption/decryption, Base64 encoding, symmetric/asymmetric keys, PIN block formats.
nCore platform provides the following card PIN management features though APIs:
  • Set card PIN
  • Get card PIN

Change card PIN

A cardholder can change his/her card PIN as required. Send a PUT request to /cards/{id}:changePin endpoint as given below to change the card PIN.
Please note:
  • Remove "enters" from the sample message given above when testing on sandbox.
  • An encrypted PIN is required to get a successful response.

Card PIN enciphering method

Below you can see the encryption flow:
Please refer to the following steps to encrypt the digital envelope:
1. Generate a 16-byte random <IV component> and encode it into Base64 URL encoding (RFC 4648) to get <b64_IVcomponent>
2. Create a PIN Block <clearPINBlock> in ISO 9564-1 format 1 as given below format:
ISO 9564-1 format 1 = <Format Version><PIN Length><PIN><Random HEX digits to make 8 bytes PIN block>
Below you can find an example of code snippet:
1
// function createPINBlock(plaintext){
2
var pinLength = plaintext.length;
3
var pinBlock = '1' + pinLength + plaintext + forge.util.bytesToHex(forge.random.getBytesSync(8));
4
pinBlock = pinBlock.substring(0, 16);
5
console.log(pinBlock);
6
}
Copied!
3. Generate a random 3DES key <3DESkey> of 16 bytes.
Below you can find an example of code snippet:
1
// function generateDESKey(){
2
var key = forge.random.getBytesSync(16);
3
var secretKey = forge.util.createBuffer(key, 'raw');
4
console.log(secretKey.toHex().toUpperCase());
5
}
Copied!
4.1. Encrypt the <clearPINBlock> with <3DESkey>, you will get <encryptedData>
4.2. Transform the <encryptedData> into Hex bytes to get the data in Hex <encryptedDataHex>
4.3. Now encode the <encryptedDataHex> into Base64 URL encoding (RFC 4648), you will get <b64_encryptedData>
Below you can find an example of code snippet:
1
// function encrypt3DES(key, pinBlock) {
2
var secretKey = forge.util.createBuffer(forge.util.hexToBytes(key), 'raw');
3
secretKey.putBytes(forge.util.hexToBytes(secretKey.toHex().substring(0, 16), 'raw'));
4
5
var cipher = forge.cipher.createCipher('3DES-ECB', secretKey);
6
var data = forge.util.createBuffer(forge.util.hexToBytes(pinBlock));
7
cipher.start({iv: ''});
8
cipher.update(data);
9
cipher.finish();
10
var encryptedPIN = forge.util.bytesToHex(cipher.output);
11
encryptedPIN = encryptedPIN.substring(0, 16);
12
console.log(encryptedPIN);
13
}
14
Copied!
5. Encrypt the <3DESkey> with NymCard's shared key <publicKey> in PKCS1 to get <encryptedSecretKey>
6. Encode<encryptedSecretKey> into Base64 URL encoding (RFC 4648) to get <b64_encryptedSecretKey>
Below you can find an example of code snippet:
1
// function encryptRSA(desKey, pubKey) {
2
var publicKey = forge.pki.publicKeyFromPem(pubKey);
3
var encryptedData = forge.util.encryptRSA2(forge.util.hexToBytes(desKey), publicKey);
4
var encoded = forge.util.base64urlencode(forge.util.encode64(encryptedData));
5
console.log(encoded);
6
}
7
Copied!
7. Create a digital envelope with the separator “:” in the format <protocol>:2:<b64_IVcomponent>:<b64_encryptedSecretKey>:<b64_encryptedData> and send the created digital envelope in Change Card PIN request.
Below you can find an example of code snippet:
1
// function createEnvelope(encodedEncryptedSecretKey, pinBlock) {
2
var encodedIV = forge.util.base64urlencode( forge.util.encode64(forge.random.getBytesSync(8)) );
3
var encBuffer = forge.util.createBuffer();
4
encBuffer.putBytes(forge.util.hexToBytes(pinBlock.substring(0, 16), 'raw'));
5
var encodedEncryptedData = forge.util.base64urlencode( forge.util.encode64( encBuffer.bytes()) );
6
7
var envelope = `ncrypt:2:${encodedIV}:${encodedEncryptedSecretKey}:${encodedEncryptedData}`;
8
console.log(envelope);
9
}
10
Copied!
Encryption example
Below you can find an encryption example steps:
1. Create a PIN Block <clearPINBlock> in ISO 9564-1 format 1 as given below format
Where, for example: Version: 1 PIN Length: 4 PIN: 1234 Random HEX digits: 3CB5055865
<clearPINBlock> = 1412343CB5055865
2. Generate a random 3DES key of 16 bytes
<3DESkey> = 1FB3F48A6D51832CE91C1C734554086D
3.1 Now encrypt the <clearPINBlock> with <3DESkey>, you will get <encryptedData>
<encryptedData> = 3A4F4E79B16E4704
3.2. Transform the <encryptedData> into Hex bytes to get the data in Hex <encryptedDataHex>
3.3. Now convert the <encryptedDataHex> into Base64 URL encoding (RFC 4648), you will get <b64_encryptedData>
<b64_encryptedData> = Ok9OebFuRwQ
4. Encrypt the <3DESkey> with NymCard's shared key <publicKey> in PKCS1 and encode it in Base64 URL encoding (RFC 4648), you will get <b64_encryptedSecretKey>
<b64_encryptedSecretKey> = kjQRz3M9wzOFPU3cphAomtHoMv3aC2-CkMtAgiLvYfpy1cEwTm3ag7_caXHFThWN_SBxHpj9aviki9rr7okJKN-Bqd O46d7Uu4Bx9dNo0_Tn9ZcKV7X-dAGLgNViYeAaGbA2jlcESYZZLecqPBq BADQ12DdGV4VfRtEb3pDZRO3VRP1hXL4VgN_H1vRwIwT5vTyBLuzQA 3Lh3xqrlVrrRFHah42oH3YkgaY6M8mc3r3e3pBItNMiwW10wjfO50z7dy 2O0yAGyy-QSWqu4LQYMLKMAPx4wsuEcAQg3Xpmnv3GmP_goAvu88 ASH9u4iKWGh0OtrldQZlmUqiYcq9mWMQ
5. Generate a 16-byte random <IV component> and convert it into Base64 URL encoding (RFC 4648)
<IV component> = c31378867535cc5d1159613388253dab
<b64_IVcomponent> = wxN4hnU1zF0RWWEziCU9qw
6. Create a digital envelope with the separator “:” in the format <protocol>:2:<b64_IVcomponent>:<b64_encryptedSecretKey>:<b64_encryptedData> and send the created digital envelope in Change Card PIN request. Sample message is given in below table:
Component
Position
Sample message
<protocol>
1
ncrypt
<protocolVersion>
2
2
<64_IVcomponent>
3
bP6dZTzopk6TTYeP4lETrw
<64_encryptedsecretKey>
4
kjQRz3M9wzOFPU3cphAomtHoMv3aC2-CkMtAgiLvYfpy1cEwTm3ag7_caXHFThWN_SBxHpj9aviki9rr7okJKN-Bqd O46d7Uu4Bx9dNo0_Tn9ZcKV7X-dAGLgNViYeAaGbA2jlcESYZZLecqPBq BADQ12DdGV4VfRtEb3pDZRO3VRP1hXL4VgN_H1vRwIwT5vTyBLuzQA 3Lh3xqrlVrrRFHah42oH3YkgaY6M8mc3r3e3pBItNMiwW10wjfO50z7dy 2O0yAGyy-QSWqu4LQYMLKMAPx4wsuEcAQg3Xpmnv3GmP_goAvu88 ASH9u4iKWGh0OtrldQZlmUqiYcq9mWMQ
<64_encryptedData>
5
Ok9OebFuRwQ
Test keys which can be used in the sandbox environment are given in the Test Keys section.
For non-PCI compliant customers:
To change the card PIN, please integrate nCore’s PCI widget in your cardholder facing applications to enable your cardholders to securely change their card PIN. Please check the PCI Widget section for further details.

Get card PIN

For PCI compliant customers:
Send GET request to /cards/{id}:getPin endpoint to get an encrypted card PIN, which can be decrypted by your application to show the PIN in clear form to the cardholder.
Where {id} is the card ID and it is a mandatory field.

Card PIN deciphering method

Let's send a Get PIN request and receive the encrypted envelope message as given below.
Get PIN request
Remove "enters" from the sample message given above when testing on sandbox.
Now we will apply the steps to decrypt the Card PIN as shown below.
Steps to decrypt a digital envelope:
1. Parse the digital envelope with separator “:”.
2. Now decode the components <b64_IVcomponent>, <b64_encryptedSecretKey> and <64_encryptedData> with BASE64 (RFC 4648), after that you will get <IVcomponent>, <encryptedSecretKey>, <encryptedData>
Below you can find an example of code snippet:
1
// function parseEnvelope(envelope) {
2
var envelopeComponents = envelope.split(":");
3
var encIVh forge.util.bytesToHex(forge.util.decode64(forge.util.base64urldecode(envelopeComponents[2])));
4
var encKey = forge.util.bytesToHex(forge.util.decode64(forge.util.base64urldecode(envelopeComponents[3])));
5
var encPIN = forge.util.bytesToHex(forge.util.decode64(forge.util.base64urldecode(envelopeComponents[4])));
6
console.log(encIVh);
7
console.log(encKey);
8
console.log(encPIN);
9
}
10
Copied!
3. Decrypt the <encryptedSecretKey> with the receiver's private key in PKCS1 to get the you will get the 3DES key <3DESkey>
Below you can find an example of code snippet:
1
// function decryptRSA(encKey, privateKey) {
2
var encryptedSecretKey = forge.util.decode64(forge.util.base64urldecode( encKey ));
3
var privateKey = forge.pki.privateKeyFromPem(privateKey);
4
5
var decryptedSecretKey = forge.util.decryptRSA2(encryptedSecretKey, privateKey);
6
console.log(forge.util.bytesToHex(decryptedSecretKey).toUpperCase());
7
}
8
Copied!
4. Now decrypt <encryptedData> with <3DESkey> so that you will get the clear PIN block <clearPINBlock> in ISO 9564-1 format 1
Below you can find an example of code snippet:
1
// function decrypt3DES(desKey, encPin) {
2
var decryptedSecretKey = forge.util.hexToBytes(desKey);
3
var buffer = forge.util.createBuffer(decryptedSecretKey);
4
if(buffer.length() !== 24) {
5
buffer.putBytes(forge.util.hexToBytes(buffer.toHex().substring(0, 16), 'raw'));
6
}
7
var decipher = forge.cipher.createDecipher('3DES-ECB', buffer.bytes());
8
9
var encryptedData = forge.util.hexToBytes(encPin);
10
11
var dataBuffer = forge.util.createBuffer(encryptedData);
12
if(dataBuffer.length() !== 16) {
13
dataBuffer.putBytes(forge.util.hexToBytes(dataBuffer.toHex().substring(0, 16), 'raw'));
14
}
15
16
decipher.start({iv: ''});
17
decipher.update(dataBuffer);
18
var result = decipher.finish();
19
var pinBlock = decipher.output.toHex();
20
var pinLength = pinBlock.substring(1, 2);
21
var pin = pinBlock.substring(2, parseInt(pinLength) + 2);
22
console.log(pin);
23
}
24
Copied!
5. Now parse the clear PIN block as per the following ISO 9564-1 format 1, you will get the clear PIN <PIN>
ISO 9564-1 format 1 = <Format Version><PIN Length><PIN><Random HEX digits to make 8 bytes PIN block>
Test keys which can be used in the sandbox environment are given in the Test Keys section.
For non-PCI compliant customers:
To retrieve the card PIN and show it to the cardholder, please integrate nCore’s PCI widget in your cardholder facing applications to enable your cardholders to securely retrieve and see their card PIN. Please check the PCI Widget section for further details.
Decryption example
Below you can find a decryption example steps:
1. Parse the digital envelope with separator “:” as given below.
Component
Position
Parsed Message
<protocol>
1
ncrypt
<protocolVersion>
2
2
<64_IVcomponent>
3
xKzHT-2NJ8yCZIv7Ra9oFQ
<64_encryptedsecretKey>
4
VETEcevv-ZyndOeLF7CqO-4aNJ6Z5Tha0wcMFoJEDAJAoLsst1ccMSeeMdbJUwq1GfKjCp m5mMwkEn51ZAFqLW43EcNkapSiPPVRJtU5V1z9u4ZGEXi4swPVzY2j0NfaM4a4aGM_W dpKSx6r7m86vhjI5901GXRd2vpyGAztfL9krOMA7KgLGaVlqj1i-xIaxvGbIDhFVepIWcxTxiSHqwZxLMN1HMojtf2pJacwoq5nOBP3DX3DgdapIdJN8AWCSIpZ 8M6nwf4-2Wr8GGTJrUChU1eJiALKZ-lliP8RvIERG9zP3Z41kQDoWP9JlEFr547xREvXIf6IS4a_ixuwrg
<64_encryptedData>
5
1Ya9e6e0Los
2. Now decode the components <b64_IVcomponent>, <b64_encryptedSecretKey> and <64_encryptedData> with BASE64 (RFC 4648), after that you will get <IVcomponent>, <encryptedSecretKey>, <encryptedData> as given below.
<IVcomponent> = c4acc74fed8d27cc82648bfb45af6815
<encryptedSecretKey> = VETEcevv+ZyndOeLF7CqO+4aNJ6Z5Tha0wcMFoJEDAJAoLsst1ccMSeeMdbJUwq1 GfKjCpm5mMwkEn51ZAFqLW43EcNkapSiPPVRJtU5V1z9u4ZGEXi4swPVzY2j0NfaM4a4aGM/WdpKSx6r7m 86vhjI5901GXRd2vpyGAztfL9krOMA7KgLGaVlqj1i+xIaxvGbIDhFVepIWcxTxiSHqwZxLMN1HMojtf2pJacwoq 5nOBP3DX3DgdapIdJN8AWCSIpZ8M6nwf4+2Wr8GGTJrUChU1eJiALKZ+lliP8RvIERG9zP3Z41kQDoWP9JlE Fr547xREvXIf6IS4a/ixuwrg==
<encryptedData> = D586BD7BA7B42E8B
3. Decrypt the <encryptedSecretKey> with the receiver's private key in PKCS1 to get the you will get the 3DES key <3DESkey>
<3DESkey> = 9D233E02CD9D26E3519768B50B0BEC31
4. Now decrypt <encryptedData> with <3DESkey> so that you will get the clear PIN block <clearPINBlock> in ISO 9564-1 format 1
<clearPINBlock> = 141234284C1B97D0
5. Now parse the clear PIN block as per the following ISO 9564-1 format 1, you will get the clear PIN <PIN>
ISO 9564-1 format 1 = <Format Version><PIN Length><PIN><Random HEX digits to make 8 bytes PIN block>
<clearPINBlock> = <1><4><1234><284C1B97D0>
<PIN> = <1234>
Test keys which can be used in the sandbox environment are given in the Test Keys section.

Test Keys

You can use the following test keys to perform Get and Change PIN operations.
Remove "enters" from the Test keys given below when testing.
Test Keys Name
Test Keys
NymCard’s Public Key
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqce2Sf8MgdBGO4sv0yiOrBpMkvV3pOVZGtuM4d0rQ rA/jXAS1JjSEaUauLJipM2X+JiziUMDgofKPPQKZakMfH3ZnDvV8TgOpQwJ61iI6xGhU+Y3DTPP+BtvdyKvxeTbrQc 5Et9LOhFzYCblXN3POdlrrpec4VsEQN9szuQfDRtDEqkNpgjanS5PUKBluwdpkUPdAJuA17wRkYVJd5FsgZF6qmt/ GvooLrQMOU4C8yTPFUwYuDNiXXe520JA9adi4YD/WXCkl8uB2vfZjXyqKcNqKoMi3Wm3yI128SBYX2hg/PYt6j O+DrvoxmQJm9iFi3aTWFhuy/2nSY6DNyM/hwIDAQAB
-----END RSA PUBLIC KEY-----
Client’s Public Key
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvlWX39E2k2CYRKGZFwlZLHE7p139zkaQkCy4Yx1T70I GFtHIKBmPnjb9uzDmxTW1AihjO4iExYZh1OJz7/PYbgjRufEJ28uzJaCAJGKJZaXtgrKqgLAgxJr0IHQ+KFtilqbrqecFO0 aBdptxY3jvBblg2cfb/AS5U3RmUwF6RzmJuTSeSK7sxnezheeubFusnxrop3iiopqJv9iGkVa97P3jAiF/tVN1HqmsAHaiXo bnOV2xXsNfHUJ0J8xW61Vpy7SvtEx0SLcVb/kMaUstQNdIIvEeSxEmdmUHj3JakGWhFC79pQXP/tDaeH71mVZJFHq O+Mfbm5+EtHU7OzfzKwIDAQAB
-----END RSA PUBLIC KEY-----
Client’s Private Key
-----BEGIN RSA PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC+VZff0TaTYJhEoZkXCVkscTunXf3ORpCQLLhjHVP vQgYW0cgoGY+eNv27MObFNbUCKGM7iITFhmHU4nPv89huCNG58Qnby7MloIAkYollpe2CsqqAsCDEmvQgdD4oW2 KWpuup5wU7RoF2m3FjeO8FuWDZx9v8BLlTdGZTAXpHOYm5NJ5IruzGd7OF565sW6yfGuineKKimom/2IaRVr3s/eMC IX+1U3UeqawAdqJehuc5XbFew18dQnQnzFbrVWnLtK+0THRItxVv+QxpSy1A10gi8R5LESZ2ZQePclqQZaEULv2lBc/+0 Np4fvWZVkkUeo74x9ubn4S0dTs7N/MrAgMBAAECggEATyDqiQRDejXYWAAO00LxrcZNlKFA2TcA9s+AwMP6lyeNvIL uga1Oxen6xo3oAuj3HbSIvMFe4XeiyIx0wrdPrT9BYdpRzOz8x5HYdEf68yVufr2koOeYV+RLxgpNpR2I+TTgGLyQsjn3rMW m+EHYrTqKhz/NtxKHsahcufmNSnprMlFnhR81HkwMTJVFduD8awNQgywOoEKky9LtsdRi59uH+PZfxZM1AubuChIezO QwiSu+IiL+ypgTv7gSyYeChsZJPFN7oyTjU0gx2IKpUOiPMxPsOVY6SxXDbQFoakyA/tuH3a3xWi4TsbNk3tIgyZbIkPPvHfj eTA6IZCxeUQKBgQDuPTA6vt78ilJG0TidMaVPIxJ4/mskVVfPcSZplXKGNbJDDUD5vaTU3zMLV3CXdcvu8d9gQDdOaFu WIbVZY0NbwiZPVy7E6eKTpgAzsEbVXw/P4GSFSMuUErOOKFNeGOgj+6b81j/XNk3YmPkKhN+bEc4ADpEU7tKU9/bX EYMutQKBgQDMhiPnc5MlFP3008nJ6cp1zRDD79EsesMo0TnQHlrTAjuY2T/6fuErlnNxY7ynE+xcJQbYcJmfyndyoX/OVJ QOPcoiU5AgjBgwweCYOQpW6Kh7LRQXv1TQvzVjM9lssZ+Lwmda5xxFympCgANiqyn+iSbfTvh7E6EOIfYb+ifmXwKBg DFL9gPh5RBKqvW+a0GTuUojzrm8o3z0L+Rb3H/yja0ZxVY8ktpalJX7zXsmT8T3eghqgjdPcmJGE9WACh+B+7kr9nNqbe IPJ3Q34EjRzAZw0jvIieROiNmN+RuMWpvY+YgglZAx4SnuMbOFC9tSXVagG4lFel3jgS2UFb6w//0VAoGAcOVazFgv0ThV Nt/xc1NqPryDlKS8giEBuXZEw2z+FZwV6bmCZ3PCN51E/EJh0Jhe0D5gGPmO03WfmdcsBWkKkRHqkiguVsj+UWuz3lM eMfsbhWLMxI8I8nGZtrjYO/eQakVVaAhKwvuIzEx9kemJtMdgfcPJxaaAMJzujWL4w2ECgYBc09fYu8CamUpVDTgCUGizV 4fBzeBiygmxUAyg1wcV3E5HHSrCmZRL0jRi0RqlURprgb2R3wyvD9nDobDY6AZYEqTw8DKP2U55Fxo1aoua1TT/uQe0z RnDugAu/BNAboe0FWMNd004NiM73TC/x8yUP+wo2B3o0+G7OCiUqvqGMw==
-----END RSA PRIVATE KEY-----

Card PIN Controls

The card PIN settings such as PIN length, PIN type, and PIN retries are defined on the card product. A card inherits all of the PIN setting from the card product. When the cardholder performs a transaction with an incorrect PIN (bad PIN), a counter shall be maintained and updated at the card level to keep track of successive bad PIN attempts.
Before reaching the threshold if the cardholder is able to perform a successful PIN verification, then the counter shall be reset. If the bad PIN retries threshold is achieved, the card status shall be automatically changed to suspended status and the status reason code shall indicate that the card is suspended because PIN retries are exhausted.
When the card is suspended, all POS and ATM authorizations are blocked. The card status can be changed from suspended to active. The cardholder KYC must be performed before resetting the PIN, the PIN counter and the card status. Once KYC is verified then you can perform the following steps to update card PIN and card status.
  • Call change PIN API to reset the card PIN Send PUT request to /cards/{id}:changePin endpoint as given below.
  • Once you change the card PIN you can reset the card status from Suspended to Active using the change card status API Send PUT request to /cards/{id}:statuschange endpoint to change card status from suspended to active as given below.