Anonymous Signing

Table of Contents

1. Introduction

This is general walk-through for getting start iAM Smart APIs development of Anonymous Signing use case.

Developers of Online Services adopting iAM Smart may find this guide useful when designing and developing application flows for anonymous digital signing adopting iAM Smart functions.

In this guide we will provide guides on:

  • Setting up your iAM Smart development environment
  • Request Anonymous Signing
  • Obtain Anonymous Signing Result
  • Online Service Acknowledges Signing Result

2. User Journey

3. Flow

Please find below the sequence diagram for the whole digital signing process:

In this guide, we will focus on some of the key steps that online service and users will be involved into when adopting and using “iAM Smart”.

4. Click sign by iAM Smart

Online service shall display the following buttons:
Digital Signing
Traditional Chinese 智方便數碼簽署
Simplified Chinese 智方便数码签署
English Signing with iAM Smart
Sample Button for Digital Signing
Traditional Chinese
Simplified Chinese
English
Open “iAM Smart”
Usage The button for user open specific authorisation page in “iAM Smart” mobile app.
Traditional Chinese 開啟智方便
Simplified Chinese 开启智方便
English Open iAM Smart
Sample Button for Open iAM Smart
Traditional Chinese
Simplified Chinese
English

Continue with iAM Smart

Usage

For Anonymous Flow only

Traditional Chinese

以智方便繼續

Simplified Chinese

以智方便继续

English

Continue with iAM Smart

Sample Button for Continue with iAM Smart

Traditional Chinese

Simplified Chinese

English

Online services is required to add a link / button, “More info” or “了解更多” in the initiation page. The link / button shall be linked to the “iAM Smart” thematic webpage based on language preference of user.  The initiation page refers to the page that initiates the “iAM Smart” service, which user clicks the “iAM Smart” button to initiate the interaction with “iAM Smart” mobile application. 

Language

Link

English

https://www.iamsmart.gov.hk/en/

Traditional Chinese

https://www.iamsmart.gov.hk/tc/

Simplified Chinese

https://www.iamsmart.gov.hk/sc/

5. Submit “Request Anonymous Signing”

5.1 Composing Request Body

Parameter

Type

Presence

Description

businessIDStringRequiredbusinessID is a unique identifier for Online Service to differentiate different request. It could be ASCII string with length less than or equal to 36 chars.
hashCodeStringRequiredthe document hash to be signed. Online Service should compute the hash and send this hash to iAM Smart System for signing. The value should be Base64 encoded.
sigAlgoStringOptional

signature algorithm to be used. Online Service can specify either SHA256withRSA or NONEwithRSA. The default value is SHA256withRSA.

While using NONEwithRSA, hashCode provided must be hashed with SHA256

HKICHashStringRequired

Signing request will only be processed when the hash of the HKIC number of the iAM Smart user is matched with the HKICHash provided by Online Service. Online Service should convert the HKIC number into hash value using SHA256 before sending to iAM Smart System.

Only the identifier of HKIC number will be hashed, no check digit is needed e.g. A123456.

The value should be Base64 encoded.

departmentStringOptionalThe department that initiates the signing request
serviceNameStringRequiredThe service name
documentNameStringRequiredThe document name that the user is going to sign

Your request body should look something like this:

				
					POST  
https://<iAM_Smart_domain>/api/v1/anonymous/signing/initiateRequest 
// Request Headers
clientID: "edae2e2529ff46228af1e4d18c8405d1"
signatureMethod: "HmacSHA256"
signature: "5X42Y1B7MEd8Mm%2BonwjiQz9VCZkkrntADskXsYntavU%3D"
timestamp: 1557048906183
nonce: "e893647dc4204eb9b7b8eddd527b687c"
// Request Body
{
    "businessID": "bbb8aae57c104cda40c93843ad5e6db8",
    "hashCode": " 965e638fda4c70f667efc2d68c40c6111e5965bfc82356d",
    "HKICHash": " 6ea37e641260714009a880a8057032a414009a80f667efc",
"department": " Office of the Government Chief Information Officer",
    "serviceName": "Online Service1",
    "documentName": "Doc0001"
}
				
			

Encryption​

To better protect the data in transit, an additional layer of data encryption will be applied to all APIs POST request (except the one that Online Service request for getting symmetric encryption key)

Info
To encrypt the data, a Content Encryption Key is required, please refer to iAM Smart API Specification 6.3.1.1 or online mockup API. 

In this case we will use a mock-up Content Encryption Key (CEK), please find below a base64-encoded mock CEK:

pvD2Zc1mf7tKVh17JOftmzyTaDyVmcULg92nB9qeEoQ=

You may refer to the pseudo code below for the encryption implementation:

				
					private static final String AES_GCM_NOPADDING = "AES/GCM/NoPadding";
/**
 * AES GCM encryption
 * @param contentByte - Bytes of content to be encrypted
 * @param key - CEK (AES 256)
 * @return
 */
public static String encrypt(byte[] contentByte, byte[] key) {
	SecretKeySpec skeySpec = new SecretKeySpec(key, AES);
	byte[] encrypted = null;
	try {
		SecureRandom secureRandom = new SecureRandom();
		byte[] iv = new byte[12]; 
		// do not reuse iv with the same key
		secureRandom.nextBytes(iv);

		Cipher cipher = Cipher.getInstance(AES_GCM_NOPADDING);
		GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); 
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parameterSpec);
		encrypted = cipher.doFinal(contentByte);
		
		ByteBuffer byteBuffer = ByteBuffer.allocate(
			4 + iv.length + encrypted.length);
		byteBuffer.putInt(iv.length);
		byteBuffer.put(iv);
		byteBuffer.put(encrypted);
		byte[] cipherMessage = byteBuffer.array();
		
		return Base64Util.base64Encode(cipherMessage);
	} catch (NoSuchAlgorithmException | NoSuchPaddingException 
		| InvalidKeyException | InvalidAlgorithmParameterException 
		| IllegalBlockSizeException | BadPaddingException e) {
		log.error("Encryption error: {}", e); 
		throw new IAMSmartException(e);
	}
}
				
			

Note

Please note that the pseudo code ONLY aims for reference and shall provide NO SUPPORT for any issue on the pseudo code.

Please find below an example of base64-encoded IV:

vM7EArooK0hCCX8E

If you use the above json and encrypt with the above CEK and IV, concatenated and base64 encoded, you should get the following result:

AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA

Now put it in the value of JSON name/value pair called “content” as the request body:

				
					{"content": "AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA" }
				
			

5.2 Composing Common Request Header

ParameterTypePresenceDescription
clientIDStringRequiredOnline Service client identifier. The clientID will be assigned to online service at the initial registration 
signatureMethodStringRequired

signature algorithm:

HmacSHA256 

timestampLongRequired

The timestamp is the request submit time expressed in the number of milliseconds since January 1, 1970 00:00:00 GMT. It is used to prevent replay attack.

The value MUST be a positive integer and equal or greater than the timestamp used in previous requests.

nonceStringRequired

A nonce is a random string, uniquely generated for each request by online service. It is used to prevent replay attack.

A nonce can be an ASCII string of any length less than or equal to 36 (UUID string length) as long as the uniqueness requirement is met.

signatureStringRequiredIt is a signature of the submitted data. Online service uses clientSecret to sign the concatenated string of clientID, signatureMethod, timestamp, nonce, and request body to get the signature. The pseudo code to generate the signature is shown at below.

Online Service uses clientSecret to sign the concatenated string of ClientID, signatureMethod, timestamp, nonce and request body to get the signature.

In this case, we will use the following parameters for signature generation:

clientID: clientID20220817demo 

clientSecret: clientSecret20220817demo 

signatureMethod: HmacSHA256 

timestamp: 1660721425291 

nonce: nonce20220817

The concatenated string of ClientID, singatureMethod, timestamp, nonce and request body should be as follow:

				
					clientID20220817demoHmacSHA2561660721425291nonce20220817{"content": "AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA"}
				
			

You may refer to the pseudo code below for the signature generation:

				
					message = clientID + signatureMethod + timestamp + nonce + request_body
sha256_HMAC = Mac.getInstance("HmacSHA256");
secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
sha256_HMAC.init(secret_key);
hash = Base64.encodeBase64String(sha256_HMAC.doFinal(message.getBytes()));
// If the hash needs to be URL encoded
signature = URLEncoder.encode(hash, "UTF-8")
				
			

With the parameters provided you should get the following result:

17uX5GHbU7x1mz1czXBLifRqOJ%2BwzZG105bj%2FWpuwU0%3D

Now construct the request header with all the parameters:

				
					{ 
"clientID": "clientID20220817demo", 
"signatureMethod": "HmacSHA256", 
"timestamp": 1660721425291, 
"nonce": "nonce20220817", 
"signature": "17uX5GHbU7x1mz1czXBLifRqOJ%2BwzZG105bj%2FWpuwU0%3D" 
}
				
			

The completed request should be like following:

				
					[Post] https://<iAM_Smart_domain>/api/v1/auth/getToken
// Request Header
{ "clientID": "clientID20220817demo", 
"signatureMethod": "HmacSHA256", 
"timestamp": 1660721425291, 
"nonce": "nonce20220817", 
"signature": "17uX5GHbU7x1mz1czXBLifRqOJ%2BwzZG105bj%2FWpuwU0%3D" }

// Request Body
{"content": "AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA" }
				
			

Upon success you should receive the encrypted response:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
“secretKey”:"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA",
"content":"AAAADLzOxAK6KCtIQgl/BJRVECazUaNiaf13rfcGNApA3K0BI0qZkB5pMWAjcTF0z0PLOnsCyxCtVUytAbA/cm2U5W83FrRXvtZZ74SrCWY4cQiAlq38TLSeOY9B418Tc5dUr1JnbCVeHe8HNrEY81QyI3r7JMZfXGaWgRoz0os8C7zbzty88vPGPSmBE7WqZF5I84IJ7wzwpRs+ifz9DfpFqWzj55mftTHQERWDhcKRALgdZECoFCqtmNhRFERxAm+MrIkypZG/JAdcho0cLyIGTkw7KLqKT0/NmQgQ3vsi6IxGOF4u8gPfLHfRkLopZkU7sXXHNC5hVtEmGXz0zrp+Pq9diKIX6MyrAtwjhIxxKu5iI9MO7XB272hpeonpJYWA0dvh0F882tjNnN6oRJrQ1ZxPXfeA"
}
				
			

Decryption

The structure of the encrypted content of response body is the same as the encrypted request body:

4 bytes IV length + IV + ciphertext

To decrypt the encrypted content, you will have to locate the following data:

  • 4 bytes IV length
  • IV
  • Ciphertext
  • authTag (if necessary)

You may refer to the pseudo code below for the decryption implementation:

6. Calculate identification code

				
					private static final String AES_GCM_NOPADDING = "AES/GCM/NoPadding";
/**
 * AES GCM encryption
 * @param contentByte - Bytes of content to be encrypted
 * @param key - CEK (AES 256)
 * @return
 */
public static String encrypt(byte[] contentByte, byte[] key) {
	SecretKeySpec skeySpec = new SecretKeySpec(key, AES);
	byte[] encrypted = null;
	try {
		SecureRandom secureRandom = new SecureRandom();
		byte[] iv = new byte[12]; 
		// do not reuse iv with the same key
		secureRandom.nextBytes(iv);

		Cipher cipher = Cipher.getInstance(AES_GCM_NOPADDING);
		GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); 
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec, parameterSpec);
		encrypted = cipher.doFinal(contentByte);
		
		ByteBuffer byteBuffer = ByteBuffer.allocate(
			4 + iv.length + encrypted.length);
		byteBuffer.putInt(iv.length);
		byteBuffer.put(iv);
		byteBuffer.put(encrypted);
		byte[] cipherMessage = byteBuffer.array();
		
		return Base64Util.base64Encode(cipherMessage);
	} catch (NoSuchAlgorithmException | NoSuchPaddingException 
		| InvalidKeyException | InvalidAlgorithmParameterException 
		| IllegalBlockSizeException | BadPaddingException e) {
		log.error("Encryption error: {}", e); 
		throw new IAMSmartException(e);
	}
}
				
			

You should get the following result:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
  "content": {
    "accessToken": "0ad186353c424c64897fcc00445c9ba1",
    "tokenType": "Bearer",
    "issueAt": 1557053922938,
    "expiresIn": 14400000, // 4 hours
"openID": "liR14%2BvX%2F5hSum5uf4ERczu0KcDnIJA5BM7FoM1ag9c%3D",
"lastModifiedDate": 1560849218006,
    "userType": "sign",
    "scope": "eidapi_auth eidapi_formFilling"
  }
}
				
			

6. Calculate identification code

After online service initiates an anonymous signing request, iAM Smart System verifies and confirms receipt of the anonymous signing request to Online Service Server by returning POST response with parameter “tickerID”, online service server uses the Document Hash / PDF digest, HKICHash and hash of clientID to calculate a 4-digit identification code to inform iAM Smart user to process the signing authorisation request in iAM Smart Mobile App.

4-digit identification code generation algorithm is as follows:

  1. Concatenate the Document Hash and the Tokenised ID hash value (calculated with SHA-512), and perform the digital digest for the concatenation result with SHA-512.
  2. Perform the MD5 calculation to obtain a unique MD5 hash value.

Divide the 128-bit MD5 hash value into four groups of 4 bytes binary value and then extract the fistt byte from each group as a data sample.

Perform 4-bit unsigned right shift to each byte of the result obtained above for the hexadecimal data.

Perform the modulo operation on each byte (modulo 10) to obtain a number of 0-9.

Assemble the 4 numbers obtained above as a 4-digit identificatin code.

You may refer the pseudo code below for the calculation of identification code:

				
					private static final char hexDigits[] = {‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’};
public static String getSignCode (String hashCode, String openlD) {
// Assume Document Hash is BASE64 encoded and perform decode
byte[] hashCodeBytes = Base64Util.base64Decode(hashCode);
// Calculate SHA-512 hashcode of Tokenised ID
byte[] openlDBytes = DigestUtil.digestToByte(openlD, Alg.SHA512);             
char code[] = new char [4];
byte[] source = new byte[hashCodeBytes.length + openlDBytes.length];
System.arraycopy(hashCodeBytes, 0, source, 0, hashCodeBytes.length);
System.arraycopy(openlDBytes, 0, source, hashCodeBytes.length, openlDBytes.length);
// Calculate SHA-512 hashcode from concatenated Document Hash and 
// SHA-512 hashed Tokenised ID
byte[] inData = DigestUtil.digestToByte(source, Alg.SHA512);                         
// Calculate MD% hashcode 
byte[] digestMD5Data = DigestUtil.digestToByte(inData, Alg.MD5);              
// Convert MD5 value 4-digit identification code 
for (int i = 0; i < 4; i++) {
	code[i] = hexDigits[(digestMD5Data[i * 4] >>> 4 & 0xf) % 10];
return new String(code);
}
				
			

Note

Please note that the pseudo code ONLY aims for reference and shall provide NO SUPPORT for any issue on the pseudo code.

7. Instruction Page for requesting signing

After online service sends the initiate signing request to “iAM Smart” system, online service is required to instruct to open the “iAM Smart” app in his/her mobile phone. Please refer to the table below for different scenarios.

Online service name
Document name
Identification code
Traditional Chinese識別碼: [9999]
Simplified Chinese识别码: [9999]
EnglishIdentification code: [9999]
Instructions
Traditional Chinese

請按照以下步驟:

  1. 記錄上述文件資料及識別碼
  2. 開啟手機上的「智方便」
  3. 核對「智方便」內顯示的文件資料及識別碼,然後完成數碼簽署

請按照以下步驟:

  1. 記錄上述文件資料及識別碼
  2. 開啟手機上的「智方便」並掃描二維碼
  3. 核對「智方便」內顯示的文件資料及識別碼,然後完成數碼簽署
Simplified Chinese

请按照以下步骤:

  1. 记录上述文件资料及识别码
  2. 开启手机上的「智方便」
  3. 核对「智方便」内显示的文件资料及识别码,然后完成数字签署

请按照以下步骤:

  1. 记录上述文件资料及识别码
  2. 开启手机上的「智方便」并扫描二维码
  3. 核对「智方便」内显示的文件资料及识别码,然后完成数字签署
English

Please follow the steps below:

  1. Record the above information and identification code
  2. Open “iAM Smart” in mobile device
  3. Check the document information and identification code in “iAM Smart” and complete the digital signing

Please follow the steps below:

  1. Record the above information and identification code
  2. Open “iAM Smart” in mobile device and scan the QR code
  3. Check the document information and identification code in “iAM Smart” and complete the digital signing
Example 

8. Request QR Page/App broker page

Depending on your device, the construction of the request is different:

Web(Same Device)

#get QR page(same device) https://<iAM_Smart_domain>/api/v1/auth/getQR? clientID=clientID20220817demo &responseType=code &source=<source> &redirectURI=<redirect_URI> &scope=eidapi_formFilling &lang=en-US &state=8273829213458 &ticketID=561b6f1ce5a043ba8aae33fb5c50386d &brokerPage=True

Web(Different Device)

#get QR page(different device) https://<iAM_Smart_domain>/api/v1/auth/getQR? clientID=clientID20220817demo &responseType=code &source=<source> &redirectURI=<redirect_URI> &scope=eidapi_formFilling &lang=en-US &state=8273829213458 &ticketID=561b6f1ce5a043ba8aae33fb5c50386d

Mobile App(Same Device)

#open iAM Smart Mobile App for Getting Context <iAM_Smart_URL_Scheme>://anon_form-filling? ticketID=561b6f1ce5a043ba8aae33fb5c50386d &source=<source> &redirectURI=<redirect_URI> &state=8273829213458

Mobile App(Different Device)

#get QR page(different device) https://<iAM_Smart_domain>/api/v1/auth/getQR? clientID=clientID20220817demo &responseType=code &source=<source> &redirectURI=<redirect_URI> &scope=eidapi_formFilling &lang=en-US &state=8273829213458 &ticketID=561b6f1ce5a043ba8aae33fb5c50386d

 

Tip

Please make sure that the redirectURI has to be registered on the self-service portal (ESP).

 

Upon request, user will proceed to open the “iAM Smart” Mobile App directly via URL Scheme of QR/Broker Page.

 

If user give consent to the request, webpage will return the code and state (if presented) to the redirectUri provided in the request through redirection.

 

<redirect_URI>?code=xxxa42e76bf4cb0846a68e6d83d6096&state=8273829213458

 

9. Verify businessID

When online service server gets the authCode and businessID, it needs to verify busineesID as generated when online service server initiates an anonymous signing request.

10. Request access token with auth_code

With the authCode received from the redirect endpoint, please construct the request body for requesting access token.

				
					{ "code": "xxxa42e76bf4cb0846a68e6d83d6096", "grantType": "authorization_code" }
				
			

Note

Same as the previous steps, you have to encrypt the request body and construct the request header accordingly.

Now initiate the request with POST method to the access token endpoint.

				
					https://<iAM_Smart_domain>/api/v1/auth/getToken
				
			

Upon success you should receive the encrypted response:

				
					{ "txID": "<T=938ffb193b4b4370b6c2584372c6a588>", "code": "D00000", "message": "SUCCESS", "secretKey": "XlUu98zV6/W4LPDfZZxzOVY62e4PHZ1e3BzENgA/ysO+rxmnBlqmYRUOqYKS8Fj/6EpuCA1jsnNY/NJWh8KBz/Kxfe03I1SuD/lHemzMahXLc9x58ecGU0q59VRNO+powUdPTyu0EPH8izh8GQ+Ht33gicl4GMmXuwjmqoo4TZl6h4hPGf6al6piQ9gucsjgFpIoP9genqXqcDCmNkhLoLUMrk5t/ZsA97AP7DHAGh5RcUT3Qktwz+D1I7Nd4oWUS6yo8ci39epiYSrG9B06OZ/kVo7k6to1Q7KVoCKj3PsMJgCUVfOQ0HP1YnH599Cu4eyULaa3rIpafpycPvqh9g==", "content": "AAAADFaP8/FuTcoymbq2hswpgHER9BUM5itaTKWo2/UwtG4wWRsMgri9bSMZ6uLxjKgmGxKTiR/5N8JuqgX1WJjoMJHp8wnLgSU4FFuGr5yNuGiLpW62fmf95GdF/ikInE5zkzT3hJRzTXbdTALeXWWPu/88WyZn1REGqSs6m2AdMY5pIhgia8bCHBxSIPBGuBtAujMII7Nlb6ocFwUL0QuaZqPF/hNJWt/EI46YGHegKiRB6KP6hxg6K5I9Sz77uQfO60PV5833fnvU" }
				
			

After decryption you may retrieve the access token to obtain the form filling result:

				
					{ "txID": "<T=938ffb193b4b4370b6c2584372c6a588>", "code": "D00000", "message": "SUCCESS", "content": { "accessToken": "0ad186353c424c64897fcc00445c9ba1", "tokenType": "Bearer", "issueAt": 1557053922938, "expiresIn": 14400000, // 4 hours "openID": "liR14%2BvX%2F5hSum5uf4ERczu0KcDnIJA5BM7FoM1ag9c%3D", "lastModifiedDate": 1560849218006, "userType": "sign", "scope": "eidapi_auth eidapi_formFilling" } }
				
			

11. Request “Obtain Anonymous Signing Request”

With the access token and the openID, please construct the request body for obtaining the signing result.

				
					{ "accessToken": "xxxa42e76bf4cb0846a68e6d83d6096", "openID": "liR14%2BvX%2F5hSum5uf4ERczu0KcDnIJA5BM7FoM1ag9c%3D" }
				
			

Now initiate the request with POST method to the obtain Anonymous Signing endpoint.

				
					https://<iAM_Smart_domain>/api/v1/anonymous/signing/initiateRequest
				
			

Upon success you should receive the encrypted response:

				
					{ "txID": "<T=938ffb193b4b4370b6c2584372c6a588>", "code": "D00000", "message": "SUCCESS", "secretKey": "XlUu98zV6/W4LPDfZZxzOVY62e4PHZ1e3BzENgA/ysO+rxmnBlqmYRUOqYKS8Fj/6EpuCA1jsnNY/NJWh8KBz/Kxfe03I1SuD/lHemzMahXLc9x58ecGU0q59VRNO+powUdPTyu0EPH8izh8GQ+Ht33gicl4GMmXuwjmqoo4TZl6h4hPGf6al6piQ9gucsjgFpIoP9genqXqcDCmNkhLoLUMrk5t/ZsA97AP7DHAGh5RcUT3Qktwz+D1I7Nd4oWUS6yo8ci39epiYSrG9B06OZ/kVo7k6to1Q7KVoCKj3PsMJgCUVfOQ0HP1YnH599Cu4eyULaa3rIpafpycPvqh9g==", "content": "AAAADFaP8/FuTcoymbq2hswpgHER9BUM5itaTKWo2/UwtG4wWRsMgri9bSMZ6uLxjKgmGxKTiR/5N8JuqgX1WJjoMJHp8wnLgSU4FFuGr5yNuGiLpW62fmf95GdF/ikInE5zkzT3hJRzTXbdTALeXWWPu/88WyZn1REGqSs6m2AdMY5pIhgia8bCHBxSIPBGuBtAujMII7Nlb6ocFwUL0QuaZqPF/hNJWt/EI46YGHegKiRB6KP6hxg6K5I9Sz77uQfO60PV5833fnvU" }
				
			

After decryption you may retrieve the access token to obtain the signing result:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS",
  "content": {
"businessID": "2YotnFZFEjr1zCsicMWpAA",
"state": "unesidkd",
"hashCode": "tGzv3JOkF0XG5Qx2TlKWIA",
"timestamp": 1556450176000,
"signature": "nnoadisauflanefhykdjf",
"cert": "sdfGSDGsdfaGDEHfjslgGQG……GSGjljlkjwmh",
  }
}
				
			

12. Online Service Acknowledge Signing Result

Online service completes the document signing process, verify the result and acknowledge iAM Smart System the signing result using iAM Smart API with the same “businessID” of the signing request.

You may refer the pseudo code below for the verification of signing result:

				
					public static boolean verifySignature(PublicKey publicKey, String algName, byte[] signatureByte, byte[] hash) {
        boolean isCorrect = false;
        try {
            Signature signature = Signature.getInstance(algName);
            signature.initVerify(publicKey);
            signature.update(hash);
            isCorrect = signature.verify(signatureByte);
        } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
            e.printStackTrace();
        } 
        return isCorrect;
    }
				
			

12.1 Composing Request body

ParameterTypePresenceDescription
businessIDStringRequiredbusinessID is a unique identifier for Online Service to differentiate different request. It should be ASCII string with length less than or equal to 36 chars.
signingResultStringRequired

“SR001”: digital signature is accepted

“SR002”: digital signature is rejected

“SR003”: no digital signature was received

Your request body should look something like this:

				
					https://<iAM_Smart_domain>/api/v1/account/signing/ackResult 
// Request Headers
clientID: "edae2e2529ff46228af1e4d18c8405d1"
signatureMethod: "HmacSHA256"
signature: "5X42Y1B7MEd8Mm%2BonwjiQz9VCZkkrntADskXsYntavU%3D"
timestamp: 1557048906183
nonce: "e893647dc4204eb9b7b8eddd527b687c"
// Request Body
{
"businessID": "bbb8aae57c104cda40c93843ad5e6db8",
"signingResult": "SR001",
}
				
			

As an additional layer of data encryption will be applied to all APIs POST request, please follow above section to construct the encrypted request header and request body.

Upon success you should receive the encrypted response:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS"
}
				
			

Decryption

Please refer to above section for decryption of the content data, and you should get the following result:

				
					{
  "txID": "<T=938ffb193b4b4370b6c2584372c6a588>",
  "code": "D00000",
  "message": "SUCCESS"
}
				
			

Online service server matches the result using the “businessID” and shows the signing result in corresponding online service website.

PHP Code Snippets Powered By : XYZScripts.com