Appearance
Message Security
RSA/AES Encryption
Optionally, message encryption may be used when making a POST
request to the API.
- Message encryption uses a combination of AES and RSA encryption.
- The message payload is encrypted using AES-CTR-256.
- The resultant AES key is then encrypted using an RSA 2048-bit public key.
- RSA key-pairs can be created in the Nexus portal
Settings
view, and the public key can be copied.- A maximum of 2 keys can be created for key rotation purposes.
- Public keys are copied in PCKS #8 format.
- Public keys can also be retrieved from the partner public key API.
- Use the API routes as documented, except the payload will always be an object with 'encrypted' and 'hash' properties.
- The 'encrypted' property will the Key ID used to encrypt the AES key
- The 'hash' will be a built-up string containing the RSA encrypted combination of the AES key plus IV, and the AES encrypted payload.
- rsaEncryptedAesKeyAndIv delimited with a bar character
|
'${aesKey}.toString('base64')}|${aesIv}.toString('base64')'
- aesEncryptedPayload
aesCipher.update(payload, 'utf8', 'base64') + aesCipher.final('base64')
- Final hash value is the rsaEncryptedAesKeyAndIv and aesEncryptedPayload delimited with a bar character
|
${rsaEncryptedAesKeyAndIv}|${aesEncryptedPayload}
- rsaEncryptedAesKeyAndIv delimited with a bar character
Example Node.js Encryption
javascript
import { createCipheriv, randomBytes } from 'crypto'
import NodeRSA from 'node-rsa'
const algorithm = 'aes-256-ctr'
const inputEncoding = 'utf8'
const outputEncoding = 'base64'
function preparePayload(payload) {
// Get the public key from the Nexus portal or the partner public key API endpoint
const publicKeyString = '' // https://bdcs.q2developer.com/docs/api/partner/public-key.html
// Encrypt the payload with AES
const aesKey = Buffer.from(randomBytes(32))
const aesIv = Buffer.from(randomBytes(16))
const aesCipher = createCipheriv(algorithm, aesKey, aesIv)
let aesEncryptedPayload = aesCipher.update(payload, inputEncoding, outputEncoding)
aesEncryptedPayload += aesCipher.final(outputEncoding)
// Combine the AES key and iv into a single string
const aesKeyPlusIv = `${aesKey.toString(outputEncoding)}|${aesIv.toString(outputEncoding)}`
// Now Encrypt the AES key and iv with RSA
const publicKey = new NodeRSA()
publicKey.importKey(publicKeyString, 'pkcs8-public')
const rsaEncryptedAesKeyAndIv = publicKey.encrypt(aesKeyPlusIv, outputEncoding)
// Return the perpared hash value for the request
return `${rsaEncryptedAesKeyAndIv}|${aesEncryptedPayload}`
}
Example Encrypted Request
json
{
"encrypted": "os8th269xgj7tyku7wxl",
"hash": "PQ5...Q==|H87c...Q=="
}
RSA Request Signing
Optionally, 2048-bit asymmetric request signing may be used when making requests to the API.
Example Signed Request
shell
curl "https://api.q2open.io/v1/client/create-token" \
-H "Authorization: Bearer dc220490-e6ee-11e5-8a94-e7385a8d929e" \
-H "Signature: MzfMtn6M9rpHyzGSvBPkzbNZlne+rf3tkcLUeMUW8mOMmdP1VtnnVdQA9hdYVObjwibOGdRQmCeoI9Xba5DXGT2/l9wOSJQ4FI90DssY1l+orOiwVwY8quAgBUYd2YDDUGyEJ31Y9yOgwLBp2xC4pA5vfkYtWAC9PccdxDyMZcCm6pz3AVgfCRN1m2rcZsE/VrhWhZof3sYitP3zTfV7KCF3T232HPHQtEYtEMLE4Pi7t4i+KvR4Rejt4a7DIgba3OfVmWf5La7WzdlU4eneIPnVjk3CGUo4t9PIPJQVbLyDSIXiF9pRD8ZlW+19XUe/HyWFHR4em00nbaNjBG4TSQ==" \
-H "kid": "key001" \
-H "Date: 2019-09-17T14:14:24.874Z" \
-H "Content-Type: application/json" \
-d '{
"identifier": "5b2bd638bdf6035960b98694"
}'
-X POST
Keypair Provisioning
API request signing key-pairs can be added manually in the Nexus portal or in automated fashion by providing an API endpoint. If the kid
is left out of the request headers, then the first key in the system will be used which may cause problems when rotating keys. Easiest is to just pass in the kid
every time if request signing is set up and enabled.
Manual
- Create a 2048-bit RSA keypair following the PKCS #1/sha-256 signing scheme.
- Update the API Request Signing Public Key in the Q2 Nexus portal
Settings
view.
Partner Provided API
An API endpoint may be provided by the partner which the CardSwap system will use to keep signing keys synchronized. Keys will be requested from the API daily. It is assumed that the expiration of a new partner RSA signing key will be several days at a minimum. If no valid keys are present, the CardSwap retrieval job will ping the partner endpoint several times daily to request valid keys. The API must return keys in standard JWKS (JSON Web Key Set) format. Please refer to the JWK standards for more information.
When setting up the API endpoint in Nexus, a collection of headers can also be added if the endpoint requires additional metadata to function. Headers are provided in JSON format.
Signing the API Request
- With each request to the API, generate a signature using the following formula:
- Request method in all uppercase:
POST/PUT/GET/DELETE
plus a colon. - Path and query of the request plus a colon.
- Your API Key plus a colon.
- The current date and time in ISO format
- Example:
POST:/v1/client/create-token:YOUR_API_KEY:2019-09-17T14:14:24.874Z
- Request method in all uppercase:
- Use an RSA signing library to create an RSA signature from the signature text with the pkcs1-sha256 signing scheme.
- Encode the produced signature as a Base64 string.
- Add the Base64 signature in the
Signature
header of the request. - Add the date that was included in the signature to the
Date
header of the request.
When request signing is enabled, a signature must be provided with every API request. If the signature is not provided, a 401-Unauthorized
response will result.