Tutorial 3: Implementing PKI Digital Signature
Last updated
Was this helpful?
Last updated
Was this helpful?
Now that you have successfully used the OAuth2 process to get Myinfo Person data, the final step is to implement PKI digital signature in your server-to-server calls to Myinfo APIs.
Please refer to our for this tutorial.
You may use test personas found in the when testing Tutorial 3.
Security is of utmost importance for Myinfo. To enhance security, Myinfo APIs requires your application to implement PKI digital signature when calling our server-to-server APIs, namely, the token and person APIs.
Using PKI digital signature, we can ensure the following:
The caller (your application) and the receiver (Our API Gateway) are both valid and trusted identities; i.e. they are who they say they are.
The request (from your application) and the response (from Our API Gateway) has not been changed in transit.
Digital signatures are like electronic “fingerprints.” In the form of a coded message, the digital signature securely associates a signer with a document in a recorded transaction. Digital signatures use a standard, accepted format, called Public Key Infrastructure (PKI), to provide the highest levels of security and universal acceptance. They are a specific signature technology implementation of electronic signature (eSignature).
A cryptographic system that uses two keys, a public key known to everyone and a private key, the private key has full control to the key owner, and has to keep in secured environment. A unique element to the public key system is that the public and private keys are related in such a way that only the public key can be used to encrypt messages and only the corresponding private key can be used to decrypt them. Moreover, it is virtually impossible to deduce the private key if you know the public key.
The first step is to generate the public/private keypair for your app, based on your CA cert. Please refer to your CA certificate vendor for instructions on how to do so. Once this is complete, you should have the files similar to the list shown below:
privatekey.key
private key
Make sure you save a copy of the private key in a safe place. If you lose this key you will need to generate a new key pair. You will sign your request using the private key.
mycert.cer
X.509 cert (public key)
Important:Submit this file in the Deploy step of your onboarding process upon approval of your linkup request. The API uses this file for signature verification on your app’s API calls.
For implementation on your own application, please make sure that your business user/partner has submitted your public key to Myinfo as part of the onboarding process.
Modify the configuration in the sample application you downloaded in Tutorial 2.
For Linux/MacOSFor Windows
Now access the sample application via your browser at http://localhost:3001
and click on the Retrieve Myinfo button on the application and go through the MockPass login and on the consent page, click on I Agree.
Note:The process for this is exactly the same as in Tutorial 2.
The token and person API calls will follow automatically once you have finished the consent page.
We will look at the code for these 2 APIs in the following sections.
Look at the code in the file routes/index.js
in the sample application.
You should see the following code:
You will notice that the code is calling securityHelper.generateAuthorizationHeader()
before sending out the request. This function is found in lib/security/security.js
and generates the security headers for calling Our API Gateway. Here's the code for this function:
Let's have a closer look at the generateAuthorizationHeader()
function in the lib/security/security.js
file.
To sign your request, a few steps are required: A. Constructing the Authorisation Token B. Forming the Signature Base String C. Signing the Base String to get the Digital Signature D. Assembling the Header
You can see the different steps involved in the code below:
The following sections explain in detail each of the steps and how to do it for your own application.
In order for the platform to recognize your app, you must construct a token and send it with the request message. This token is sent in the header of your request.
app_id
The AppID assigned to your application. For our sample application, this is STG2-MYINFO-SELF-TEST
nonce
A random string, uniquely generated for each request. The nonce allows the server to verify that a request has never been made before and helps prevent replay attacks when requests are made over a non-secure-channel. For more information, see Generating a Nonce Value.
signature_method
A value indicating the signature method. Value = RS256
signature
The signature value. For information on how the signature value is calculated, see later sections.
timestamp
The timestamp of the request, expressed as the number of milliseconds since January 1, 1970 00:00:00 GMT. The timestamp must be a positive integer and must be greater than or equal to the timestamp used in previous requests. For more information, see Generating the Timestamp.
A nonce is a random string that is uniquely generated for each request. The nonce allows the API providers to verify that a request has never been made before. A nonce is sent in the message header for both Shared Secret and PKI security mechanisms. In the Shared Secret mechanism, the same nonce value sent in the message header is also used in creating the Secret Digest.
The way you create the nonce will depend on your development environment. Most programming languages include a method for creating a nonce.
Below is an example of generating a nonce value in Java:
The timestamp of the request is sent in the message header. The timestamp must be in Unix epoch time, expressed as the number of milliseconds since January 1, 1970 00:00:00 GMT. The timestamp must be a positive integer and must be greater than or equal to the timestamp used in previous requests. In most implementations, the timestamp is taken from the host server. It's important that the timestamp in the message is accurate; if the timestamp is off, the message might be rejected.
A Java example of generating the timestamp is shown below.
The basestring is a string constructed to represent the contents of your request, which is then signed to create the digital signature of your request. This ensures that the contents of your request can be verified to ensure it has not been changed in transit.
Base String Examples: Below is an example of the Signature Base String that you will see in the onscreen logs of our demo application when calling the token API.
Likewise, the Base String for the person API looks like this:
The process of constructing the Signature Base String consists of three steps:
Once the Signature Base String is constructed, the next step is signing:
Use the SHA-2 algorithm to generate the hash of the Signature Base String.
Sign the hashed value using the private key of the app.
Base64-encode the signature value.
Set the string as the value for the signature parameter.
Example code in Java below:
Example code in NodeJS below:
Now that you have gotten the digital signature, you are ready to assemble the final header for your request. Make sure you include the following parameters in the header:
app_id
nonce
signature_method
signature
timestamp
Sample header with authorization parameters
Below is an example of an Authorization header for the sample application. Make sure you list the parameters in the sequence shown below.
Once the header is assembled, you are ready to send out your request. If you have done the steps correctly, Our API Gateway should recognize your request to be valid and send back a valid response, similar to the one you saw in Tutorial 2.
Validate the JWT response sent back to you in the way that we went through in Tutorial 2.
Now that you have the JWT access token, you can call the person API in the same way as the token API.
The response payload for the Person API (for test and production environments) is first signed, then encrypted:
Encryption protects the data at rest while a signed payload means, if necessary, you will be able to pass this signed payload to a 3rd party where they can verify the payload's integrity with our public certificate.
In order to read the payload, you have to perform the following steps in order:
Decrypt the payload with your application's private key.
Validate the decrypted payload signature with our public key.
After doing the above steps, your application will be able to extract the payload in JSON format.
Encryption is done using your application's public key that you provided during onboarding. Decryption of the payload should be using the private key of that key-pair.
Current encryption algorithms used:
RSA-OAEP (for content key wrapping)
AES256GCM (for content encrytion)
What is the JSON Web Encryption Compact Serialization format?
The format consist of five parts separated by dots (.), which are:
Header
Contains the encryption algorithms used to produce the 1. cipher text (encrypted data) and 2. encrypted key (symmetric key encrypted with application's RSA public key)
Encrypted Key
The encrypted symmetric key that was used to encrypt the data.
Initialization Vector
Secure random value used together with the symmetric key to encrypt the data.
Cipher Text
The encrypted data.
Tag
Value used to ensure integrity of the encrypted data and header.
Therefore, a JWE typically looks like the following: aaaaa.bbbbb.ccccc.ddddd.eeeee
How can I decrypt the JWE?
You will need to use a library that performs JWE decryption in order to decrypt the cipher text. Such libraries are readily available on the internet.
For example, in our sample application, which is implemented with Node.js, we use the jose
library, and we call the jose.jwe.decrypt
method. If the decryption fails then the library will throw an error which the application needs to handle.
Firstly, the Encrypted Key
is decrypted using your application's RSA private key with the "alg" algorithm specified in the Header
to produce the symmetric key. Next, the JWE decryption library is used to decrypt the Cipher Text
using the symmetric key, Initialization Vector
, Tag
and ascii-encoded Header
, with the "enc" algorithm in the Header
.
Look at the code in the file lib/security/security.js
and search for the following code snippet:
This calls the library to decrypt the JWE and return the decrypted JSON object, which is the signed person's data.
signature algorithm used is RS256
.
You may download Myinfo X.509 Public Key Certificate used for verification, after application is created during onboarding in the application details page upon login.
Sample Code in NodeJS
Once you have decrypted the JWE and verified the JWS, you will get the Person JSON data format which we saw in Tutorial 1 and 2. Use this data to prefill your application form.
You've successfully used the OAuth2 process and PKI digital signature to get the Person data from Myinfo sandbox environment.
You are now ready to use the same method to integrate your own application to our Staging and Production APIs
For more information on Unix epoch time, and examples of implementation of the timestamp in different programming languages, see ._ _
Signing is done using format
Encryption is done using format
The decrypted payload is signed according to format, similar to the access token.