Visa Click to Pay

Merchants and Payment Service Providers

JavaScript Reference Appendix - Visa SRC SDK

Appendix A - Decrypting the SRC Payload

Java Example for SRC Payload Symmetric Decryption

The following Java code, using the JOSE4j API jose4j-0.6.5.jar, provides an example of decrypting the payload.

package ...;
import java.security.MessageDigest;
import javax.crypto.spec.SecretKeySpec; import org.jose4j.jwe.JsonWebEncryption;
public class DecryptJWE {
public static String decryptJWE(String secret, String jwe) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] digest = md.digest(secret.getBytes("UTF-8"));
        JsonWebEncryption jweDecryptor = new JsonWebEncryption(); jweDecryptor.setCompactSerialization(jwe); jweDecryptor.setKey(new SecretKeySpec(digest, "AES"));
        return jweDecryptor.getPlaintextString();
    }
}
		

Node.js Example for SRC Payload Symmetric Decryption

var jose = require('node-jose'); var crypto = require('crypto');
module.exports = {
    decryptJWE: function (secret, payload) {
        return new Promise(function (resolve, reject) {
            var SS_Hashed =
                crypto.createHash('sha256').update(secret).digest('hex'); jose.JWK.asKey({
                    kty: 'oct', k: Buffer.from(SS_Hashed,
                        'hex')
                })
                    .then(function (key) {
                        jose.JWE.createDecrypt(key)
                            .decrypt(payload)
                            .then(function (result) {
                                resolve(result);
                            })
                            .catch(function (error) {
                                reject(error);
                            });
                    })
                    .catch(function (error) {
                        reject(error);
                    });
        });
    }
};
		

Appendix B - Generating a JWE for PAN Encryption

Encrypting the PAN

This code snippet is used for creating PAN JWE on the browser side. This example uses the node-jose library in browserify format.

// getNodeJoseLib(); Get node-jose library in browserify format
// Code to generate JWE using node-jose library
/**
*	@param kid kid for public certificate. Contact Visa representative for this value
*	@param keys Public key to be used for encryption.
Contact Visa representative for *
@param payload Card information to be encrypted,
{"card":{ "primaryAccountNumber":"424..2", "panExpirationMonth":"10",
.."panExpirationYear":"2022", "cardSecurityCode":"123",
.."cardholderFullName":"cardholder name"}
}
* @param cb Returning encrypted PAN as JWE string to this callback function */

function generateJWE(kid, keys, payload, cb) {
    const keyInput = {
        "kty": "RSA",
        "e": keys.e, // Public key exponent "kid": kid,
        "use": "enc",
        "n": keys.n, // Public key modulus "alg": "RSA-OAEP-256",
        "ext_content": "payload"
    };
    jose.JWK.asKey(keyInput)
        .then((key) => {
            console.log("JWK ", JSON.stringify(key)); const contentAlg = 'A25..CM';
            let options = {
                format: 'compact',
                contentAlg: contentAlg, fields: {
                    kid: key.kid, typ: 'JOSE',
                    iat: Date.now(), alg: key.alg, enc: contentAlg
                }
            };
            jose.JWE.createEncrypt(options, key).update(payload).
                final().then((serializedJWE) => {
                    console.log("Encrypted data: ", JSON.stringify(serializedJWE));
                    cb(serializedJWE);
                }, (error) => {
                    console.log("Error occurred: ", error.message); cb(null);
                });
        }, (error) => {
            console.log("Error occurred: ", error.message); cb(null);
        })
}
		

Appendix C - JWE Composition Details

JSON Web Encryption (JWE) Using Shared Secret

The encryption key provided during onboarding is used to encrypt and decrypt payloads. JSON Web Encryption (JWE) content should be signed or encrypted using the shared secret that was provided to client at the time of onboarding.

Introduction

Visa uses JSON Web Encryption (JWE) to encode sensitive field level information. Encrypted input parameters should be constructed before sending them in API requests.

Visa Installment Solutions APIs use the following naming convention for fields that require encryption in this document.

"enc<FIELD>" : "JWE ( ... ) "

See the complete specification for JWE: https://tools.ietf.org/html/draft-ietf-jose-json-web- encryption-40.

JWE Composition and Conventions

BASE64URL (UTF8 (JWE Header)) || ‘.’ ||
BASE64URL (JWE Encrypted Key) || ‘.’ || BASE64URL (JWE IV) || ‘.’ ||
BASE64URL (JWE Ciphertext) || ‘.’ || BASE64URL (JWE Authentication Tag)
		

The conventions are as follows:

  • BASE64URL encoding with NO padding.
  • Compact serialization style (elements separated by “.”)
  • Use a CEK (Content Encryption Key) of 256bits size.
  • Authentication Tag will be generated as an additional output of the AES-GCM-256 encryption. Size of this field is 128 bits.
  • All String to byte and vice-versa conversions are done with UTF-8 charset.

Note: The JWE Protected Header is input as the AAD (Additional Authenticated Data) parameter of the authenticated encryption (AES-GCM) of the “text to encrypt”.

Sample JWE Header for Asymmetric Encryption

"header": {
    "alg": "RSA-OAEP-256""typ": "JOSE",
    "kid": "50charAPIKey", // API key "enc": "A256GCM"
}
		

Sample JWE Header for Symmetric Encryption

"header": {
    "alg": "AGCM256KW""typ": "JOSE",
    "tag": "<128bitvalue>", // HMAC generated from applying AES-256-GCM-KW to the CEK
    "kid": "50charAPIKey", // API key "enc": "AGCM256"
}
		

Sample JWE Body

  • encrypted_key: base64 encoded form. CEK encrypted using AGCM256KW (alg) algorithm and the CEK IV
  • iv: base64 encoded form. IV for the text encryption. Size of IV is to be 96 bit Base64 encoded form
  • ciphertext: encrypted blob generated using the AES-GCM encryption (enc) of the text to encrypt
  • tag: base64 encoded form. HMAC generated using the AES-GCM encryption of the text to encrypt. The size of the tag should be 128 bits
“encrypted_key”: “UghIOgu ... MR4gp_A=”, “iv”: “AxY8DctDa….GlsbGljb3RoZQ=”,
“ciphertext”: “KDlTthhZTGufMY…….xPSUrfmqCHXaI9wOGY=”, “tag”: “Mz-VPPyU4…RlcuYv1IwIvzw=”