cancel
Showing results for 
Search instead for 
Did you mean: 

CyberSource card number encryption (RSA-OAEP-256)

Is there anyone know here how do I encrypt card number in cybersource?

i tried to encrypt mine using online RSAOAEP encryption tool but i got this response

{
    "responseStatus": {
        "status": 400,
        "reason": "DECRYPTION_ERROR",
        "message": "Cannot decrypt PAN (RsaOaep256): data hash wrong",
        "correlationId": null,
        "details": [],
        "_embedded": {}
    },
    "_links": {
        "self": null,
        "documentation": [],
        "next": []
    }
}

there documentation seems not enough for newbie like me

JiwanFilembar
Member
2 REPLIES 2

I've been able to get Flex API to work. But whay kind of SDK have you been using? I've implemented it with React Native v0.61.5 with Typescript and with multiple cryptographic libraries: voojio react-native-crypto, isomorphic-webcrypto, crypto-js, js-base64  omegle shagle and buffer. But basically this could be done on any Javascript framework.

I suppose you have /Keys request working and i guess you have specified the encryptionType to RsaOaep256.

Next step is to import the JSON web key (JWK) you received from previous step and encrypt the card number with imported key.

Import the JWK

import webcrypto from "isomorphic-webcrypto"

const importKey = async (jsonWebKey: any) => {
  return webcrypto.subtle.importKey(
    "jwk",
    {
      ...jsonWebKey,
      alg: "RSA-OAEP-256",
      ext: true,
    },
    {
      name: "RSA-OAEP",
      hash: "SHA-256",
    },
    false,
    ["encrypt"],
  )
}

Encrypting the card number

import { Buffer } from "buffer"
import webcrypto from "isomorphic-webcrypto"
import { Base64 } from "js-base64"

const encryptCardNumber = async (cardNumber: string, jsonWebKey: any): Promise<T> = {
  const cardNumberBuffer = Buffer.from(cardNumber)

  const publicKey = await importKey(jsonWebKey, "encrypt")

  const encryptedCardNumberBuffer = await webcrypto.subtle.encrypt(
    {
      name: "RSA-OAEP",
      hash: "SHA-256",
    },
    publicKey,
    cardNumberBuffer
  )

  return Base64.btoa(String.fromCharCode.apply(null, new Uint8Array(encryptedCardNumberBuffer)))
}

Result from this function can be dirrectly passed as cardNumber in body of a request under cardInfo.

After this, you'll receive token, signature, signedFields and some other fields. You should verify received values against the signature to ensure the values have not been tampered with.

Verifying the signature

This one is pretty simple, we'll just need the public key from /Keys request that we can find under der/publicKey.

import crypto from "react-native-crypto"

const verifySignature = (publicKey: string, signature: string, signedFields: string, data: any): booelan => {
  const dataToVerify = data.signedFields.split(",").map(field => data[field]).join(",")
  const verificationKey = `-----BEGIN PUBLIC KEY-----\n${publicKey}\n-----END PUBLIC KEY-----`

  return crypto.createVerify("RSA-SHA512").update(dataToVerify).verify(verificationKey, signature, "base64")
},

I hope this will help you or others having trouble with implementing the Flex API of CyberSource because that has taken toll on me...

JiwanFilembar
Member

There are several suitepayments partners that already have integrated tokens. As noted by nick, cybersource does not have their suitepayments bundle ready yet. If you re interested in seeing some examples of integrated vendors, fee free to Dm me

 
kaludon209
New Member