Update card Pin

Encrypt Request Data Before Updating PIN Code

Encrypted Data Structure

  {
   "pinCode": "123456", 
   "cardId": "32cc3815-73a9-4ad2-ada0-20f2a583fc28", 
   "timestamp":  "1212137112"
  }
  • Encryption Parameter Description
  1. pinCode: PIN code
  2. cardId: Card ID
  3. timestamp: Timestamp

Encryption Method

We provide the following encryption method to encrypt data. You only need to prepare the apiKey to start trying. After successful encryption, send the encrypted data through the API request as defined.

package com.example

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;


public class CardDataEncryption {
    private static final String APP_IDENTIFIER = "dogpay-open-api-v1";
    private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
    private static final int GCM_IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 16;
    private static final int PBKDF2_ITERATIONS = 100000;
    private static final int KEY_LENGTH = 32;



    public static void main(String[] args) {
        try {
             

            String apiKey = "test-api-key-123";
            Long currentTimestamp = System.currentTimeMillis();
            String jsonString = "{\"pinCode\":\"123456\",\"cardId\":\"32cc3815-73a9-4ad2-ada0-20f2a583fc28\",\"timestamp\":"+currentTimestamp+"}";

            CardDataEncryption.EncryptedData encryptedCardData = CardDataEncryption.encrypt(jsonString, apiKey);
            System.out.println("EncryptedData: " + encryptedCardData);

        } catch (Exception e) {
            System.err.println("Errror: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 生成用户特定的盐值
     */
    private static String generateSalt(String apiKey) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(apiKey.getBytes(StandardCharsets.UTF_8));
        String userHash = bytesToHex(hash);
        return userHash + APP_IDENTIFIER;
    }


    public static EncryptedData encrypt(String data, String apiKey) throws Exception {
        String salt = generateSalt(apiKey);
        
        PBEKeySpec spec = new PBEKeySpec(apiKey.toCharArray(), salt.getBytes(StandardCharsets.UTF_8), PBKDF2_ITERATIONS, KEY_LENGTH * 8);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        byte[] keyBytes = factory.generateSecret(spec).getEncoded();
        SecretKey key = new SecretKeySpec(keyBytes, "AES");


        byte[] iv = new byte[GCM_IV_LENGTH];
        new SecureRandom().nextBytes(iv);


        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec);

        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));


        byte[] cipherText = new byte[encrypted.length - GCM_TAG_LENGTH];
        byte[] tag = new byte[GCM_TAG_LENGTH];
        System.arraycopy(encrypted, 0, cipherText, 0, cipherText.length);
        System.arraycopy(encrypted, cipherText.length, tag, 0, tag.length);

        return new EncryptedData(
                bytesToHex(cipherText),
                bytesToHex(iv),
                bytesToHex(tag)
        );
    }


    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }
    public static class EncryptedData {
        private final String encrypted;
        private final String iv;
        private final String tag;

        public EncryptedData(String encrypted, String iv, String tag) {
            this.encrypted = encrypted;
            this.iv = iv;
            this.tag = tag;
        }

        public String getEncrypted() {
            return encrypted;
        }

        public String getIv() {
            return iv;
        }

        public String getTag() {
            return tag;
        }

        @Override
        public String toString() {
            return "EncryptedData{" +
                    "encrypted='" + encrypted + '\'' +
                    ", iv='" + iv + '\'' +
                    ", tag='" + tag + '\'' +
                    '}';
        }
    }
}