RSA Authentication Guide
Generate RSA key pair
The following section outlines the steps involved in generating an RSA key pair with OpenSSL. We recommend that you generate a 2048 bit key pair as 1024 bit keys are no longer considered secure and 4096 bit keys use consume considerable CPU resources when signing API calls.
1) Generate a 2048-bit RSA private key and write it to a file private.pem
.
#Output an RSA private key with 2048 bit protection.
openssl genrsa -out private.pem 2048
2) Generate a PKCS8 formatted file from the private key and write it to file private8.pem
. The private8.pem file must be used in the RSA-DIGEST function to sign the requests.
#Generate a pk8 file from the private key.
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private.pem -out private8.pem
3) Generate the public key file from the private key and write it to a file public.pem
.
#Generate a public key from the private key.
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
Authentication Header Guide
The RSA authentication method is almost identical to HMAC. The only difference is that it uses a RSA private key to sign the string-to-hash and a RSA public key to validate that the signature is valid. RSA keys provide a more secure way of signing your auth headers than using a password. While a password can eventually be cracked with a brute force attack, RSA keys are nearly impossible to decipher by brute force alone. The downside of using RSA to sign API calls, is that RSA signatures require a lot more CPU resources (up to ~250 times) than HMAC hashing.
Our Generating an RSA key pair guide outlines how you can create a public and a private key. You must send the public key to Bluefin, and keep the private key on your server.
Property | Description |
---|---|
username | This property must be set to your partnerId. |
nonce | This property must be set to a nonce. A nonce can be any arbitrary string, however each nonce can once over a 15 minute period. Our service keeps a record of these nonces; if a nonce is encountered more than once during a 15 minute period the API call is rejected and an auth error response is produced. It is up to you to keep the nonce unique. |
timestamp | A unix timestamp. Our service will reject API calls with a timestamp older than 15 minutes. |
response | The response property is a RSA private key signature of a number of the API call's properties. See the guide Building the string to hash for a detailed description of string that must be included in the hash. Once you have the StringToSign, you can generate the response like this: Hex( RSA-DIGEST( privateKey, StringToSign ) ); |
Steps in building RSA Authentication header:
1) Generate a nonce
1l5daa1ju1b7lmljc5p4nev0ve
2) Generate a unix timestamp.
//In JavaScript/Node.js
Math.round(new Date().getTime()/1000)
//output 1489574949
//In Java
(int) (System.currentTimeMillis() / 1000L)
//output 1489574949
3) Generate the content hash by SHA-256 hashing the request body.
\n represents a newline character and \t represents a tab character.
sha256({ \n\t\"partnerId\": \"WATERFORD\",\n \t\"partnerKey\": \"ef1ad938150fb15a1384b883a104ce70\",\n \t\"devicePayload\": \"02C400C037001C0A8692;6011********3331=2212:***?*15=090210=2CB56EC5E025C2F3C2C67FCF2D0C4C39BB19E60EF31192675E5F1DB6A90070E3000000000000000000000000000000000000000035343154313132373038629949960E001D20004A029603\",\n \t\"clientId\": \"my_client\",\n \t\"reference\": \"723f57e1-e9c8-48cb-81d9-547ad2b76435s\"\n})
//output 9db4a2e377abca97c72c5d8b449948d3fb22fa18f305c3730f227e4f6514d4ce
4) Build the string to sign.
When creating the string to sign it is important that you follow the format described exactly as outlined below, otherwise the request will be rejected. The string to hash is composed of the following elements.
Element | Description |
---|---|
HttpVerb | Should be set to 'POST' for all API calls. |
CanonicalizedResource | Should be the HTTP Request URI, without protocol, port and domain parts; the following list outlines the appropriate value for each endpoint: - validate partner = /api/v1/partner/validate - validate device = /api/v1/device/validate - process payload = /api/v1/decrypt/parser |
nonce | Same value as set in the auth header nonce property. |
timestamp | Same value as set in the auth header timestamp property. |
ContentHash | A SHA-256 hash in hexadecimal format of the HTTP POST's body. Our service expects you to hash the whole body including any leading and trailing whitespaces that you may have included. See step 3. |
\n | The Unicode code point U+000A, commonly called newline). |
The string to sign is composed of these elements gathered together in this exact format. Once you have the string to hash you pass it into the HMAC-SHA256 hashing algorithm to generate the HMAC authentication header's response property.
HttpVerb + " " + CanonicalizedResource + "\n" + nonce + "\n" + timestamp + "\n" + "\n" + ContentHash;
For our example the string to sign is:
"POST /api/v1/authdebug\n1l5daa1ju1b7lmljc5p4nev0ve\n1489574949\n\n9db4a2e377abca97c72c5d8b449948d3fb22fa18f305c3730f227e4f6514d4ce"
5) RSA sign the string to hash with the PKCS8 formatted RSA private key
Hex( RSA-DIGEST( privateKey, "POST /api/v1/authdebug\n1l5daa1ju1b7lmljc5p4nev0ve\n1489574949\n\n9db4a2e377abca97c72c5d8b449948d3fb22fa18f305c3730f227e4f6514d4ce" ) )
//output 5581b975219cc758b2461fc680f6e1a3b725e804ca2fb0bdf9e0b63e0f83eef3f40b906602b4ec2b6c71dd994c7979c51ee042e124f24ebe1c60932815a00ebaee0d10ff32368f3d6d291f1a06024ba603b8562f0fd3128b7ed7419d2d8de72054071ebfb9d4e42599c4bc4b90fa80ef6f6e8f6a0fb566203c6d4a205dd6a43f26551e85226b31de495396018488946c5647d1cd3de7206f0d191ecfc20dda4f18e19c5e13edd802a2aed612345b6341327f01993dd3f777c253573e47b3ba3069c40c85267c095f66f5edf2702c7363f743fc73e7a5597b068a39439215d1df543734c677f3705b316a76f9e5c52ac9143ccaa76f9f6578b764199d1edde266
6) Build the Digest authentication header
Authorization: Rsa username="WATERFORD", nonce="1l5daa1ju1b7lmljc5p4nev0ve", timestamp=1489574949, response="5581b975219cc758b2461fc680f6e1a3b725e804ca2fb0bdf9e0b63e0f83eef3f40b906602b4ec2b6c71dd994c7979c51ee042e124f24ebe1c60932815a00ebaee0d10ff32368f3d6d291f1a06024ba603b8562f0fd3128b7ed7419d2d8de72054071ebfb9d4e42599c4bc4b90fa80ef6f6e8f6a0fb566203c6d4a205dd6a43f26551e85226b31de495396018488946c5647d1cd3de7206f0d191ecfc20dda4f18e19c5e13edd802a2aed612345b6341327f01993dd3f777c253573e47b3ba3069c40c85267c095f66f5edf2702c7363f743fc73e7a5597b068a39439215d1df543734c677f3705b316a76f9e5c52ac9143ccaa76f9f6578b764199d1edde266"
Example:
The following example is for demonstration purposes only. The WATERFORD user is not configured for RSA authentication and the header's timestamp is out of date; if you try the cURL command you will receive an authentication required error message.
curl 'https://cert-parser.decryptx.com/api/v1/partner/validate' \
-X POST \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'authorization: Rsa username="WATERFORD", nonce="1l5daa1ju1b7lmljc5p4nev0ve", timestamp=1489574949, response="5581b975219cc758b2461fc680f6e1a3b725e804ca2fb0bdf9e0b63e0f83eef3f40b906602b4ec2b6c71dd994c7979c51ee042e124f24ebe1c60932815a00ebaee0d10ff32368f3d6d291f1a06024ba603b8562f0fd3128b7ed7419d2d8de72054071ebfb9d4e42599c4bc4b90fa80ef6f6e8f6a0fb566203c6d4a205dd6a43f26551e85226b31de495396018488946c5647d1cd3de7206f0d191ecfc20dda4f18e19c5e13edd802a2aed612345b6341327f01993dd3f777c253573e47b3ba3069c40c85267c095f66f5edf2702c7363f743fc73e7a5597b068a39439215d1df543734c677f3705b316a76f9e5c52ac9143ccaa76f9f6578b764199d1edde266"' \
-d '{
"reference" : "723f57e1-e9c8-48cb-81d9-547ad2b76435"
}'