xorkeesign Javascript Client API Guide
Welcome to the xorkeesign API guide . Find everything you want to know about how to integrate this API and how it works.
xorkeesign India G2C comes pre-integrated with many websites. Users of the supported websites only need to enroll with xorkeesign and add the G2C extension to their browser to carry out digital signatures. Odyssey does such pre-integration for websites which in Odyssey’s opinion benefits a large majority of users. In such cases, the cost of integration is borne by Odyssey and not charged to the site owners.
For the benefit of sites that do not meet Odyssey’s criteria for pre-integration, the G2C extension exposes a few JavaScript functions that can be used by the website developer to integrate the functionality. For this too, the site owners should seek and Odyssey should enable access to the extension (in G2C) for the domain of the website that intends to use the API, but this is a simple process. These functions will then be available to the website pages if the user has added the G2C extension.
Like most other interfaces in xorkeesign here too the processing of the users’ data and documents will be done in the browser itself and only the digest is sent to xorkeesign. The document to be signed or the data to be processed will not be shared with xorkeesign and stays within the confines of the user’s browser.
Usage
A JavaScript variable XORKEESIGN will be available to the website which is accesses the G2C JavaScript API. If this is not available it indicates that the G2C extension is not installed or access has not been obtained for the website’s domain from Odyssey. All the required interfaces should be referred using this XORKEESIGN name space.
The G2C extension validates all the inputs from the caller which when not provided in the expected format will return an error to the caller. The extension also records custom messages detailing the error along with the name of the function called in the web browser's console to aid troubleshooting during the development.
The interfaces to sign or decrypt (the ones that access the user’s private key) need user’s consent in their xorkee app. The xorkee notification will carry the domain name of the host website and some additional information to clarify the context in which the API was invoked. The information presented in the xorkee app cannot be customized.
To identify the user, the API takes either the digital certificate or the xorkee handle of the user. The host site should obtain the user’s xorkee handle by framing an appropriate interface. The host site can then obtain the digital certificate of a user through the “XORKEESIGN.p7SignData” interface by providing the user’s handle. It is advised to capture and save the digital certificate of the user and then provide the digital certificate in later calls that need user’s consent.
If the interfaces to sign or decrypt are invoked with neither the digital certificate nor the xorkee handle, the API will display its own prompt to capture the xorkee handle from the user. This prompt will also have pointers to Odyssey website to download the xorkee app and obtain a handle.
Signing PDF document
- The functions exposed by the G2C extension should be called by the host site in the following sequence to sign a PDF document:
-
get the signer
the xorkee handle or digital certificate should be provided to identify the signer
-
provide the PDF document to be signed along with the signature positions
the returned intermediate PDF (without the signature) and the digest should be preserved in the context of the web page or the host server
-
sign the digest
the extension will proffer the digest to the user for signature through the xorkee app
if the user requires subscription the extension will return a subscription URL and the site should encourage the user to subscribe through the URL
-
apply the signature
the signature returned in the previous call will be embedded in the intermediate PDF to produce the final signed PDF
Signing multiple PDF document
Due to restrictions imposed by the browsers (primarily memory) the host site cannot simultaneously input multiple documents to the API. If the host site has a need to sign multiple PDF documents it should obtains the digest of each document one after the other.
The host site has the option to provide a complete PDF document as an ArrayBuffer or provide a URL (src) from which the extension can obtain the input PDF. Similarly the computed intermediate PDF can either be held in the page or saved to a destination URL (destURL) temporarily. Similarly the final signed PDF can also be stored to a designated URL.
It is strongly advised not to hold the intermediate PDF in the web page when more than one document is to be signed. Leverage the server storage by providing appropriate src and destURL.
The sign request can then be invoked with all the digests in the web page in a JavaScript array. This will trigger a xorkee notification to obtain all the signatures. The returned signatures can then be embedded into the respective documents one after the other by the API.
The input URL to fetch the PDF should not contain any request payload. All the required parameters should be sent as part of the query string. The response payload should contain the raw PDF buffer without any encoding. A response status code other than 200 will be treated as error. Similarly the output URL to store the PDF should expect to receive only the raw PDF buffer in the request payload without any encoding. The response status code should be 200 to denote success.
It is strongly discouraged to avoid signing multiple documents in one go as this will complicate the host application and significantly degrade the user experience. Taking signatures one at a time will keep things simple for a better user experience and conformance to the best principles of digital signatures. Further the users that sign multiple documents in one request may require additional subscription to xorkeesign too. For scenarios where multiple signatures are absolutely necessary, requests carrying up to 100 digests at a time are permitted.
1. Get Signer
This function is used to identify the signer through the xorkee handle or digital certificate and hence should be called before using any other function pertaining to PDF signing. As the signer should carry a qualified digital certificate to sign PDF documents, the extension also takes care of validating that before returning to the caller.
Function name
XORKEESIGN.getSigner
Input
Parameter
Data Type
Description
signerId
String
The signer’s X.509 certificate in base 64 encoded format or xorkee handle in plain without any encoding.
This should be null or undefined when neither the certificate nor the xorkee handle is available, in which case the signer’s xorkee handle will be prompted.
| Parameter | Data Type | Description |
|---|---|---|
| signerId | String |
The signer’s X.509 certificate in base 64 encoded format or xorkee handle in plain without any encoding. This should be null or undefined when neither the certificate nor the xorkee handle is available, in which case the signer’s xorkee handle will be prompted. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
| Parameter | Data Type | Description |
|---|---|---|
| signer | Object |
Refer the signer certificate schema below for information returned by the extension. |
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
Signer certificate schema
The following is the schema for the information extracted from the signer certificate ie. from the signer.info Object:
| Parameter | Data Type | Description |
|---|---|---|
| subjectCn | String | Subject common name |
| issuerCn | String | Issuer common name |
| validFrom | Number | The date from which the certificate was valid in epoch time format |
| validTill | Number | The date till which the certificate will be valid in epoch time format |
| subjectDn | Object |
Subject distinguished name as a JavaScript Object with the attribute type as the key and attribute value as the value. The attribute type will carry either the name defined in the X.520 specification or the corresponding OID whenever an unrecognized type is encountered. |
| issuerDn | Object |
Issuer distinguished name as a JavaScript Object with the attribute type as the key and attribute value as the value. The attribute type will carry either the name defined in the X.520 specification or the corresponding OID whenever an unrecognized type is encountered. |
Usage
Method 1 (synchronous)
try {
const signer = await XORKEESIGN.getSigner();
//'signer' contains information about the signer
//should be preserved for use in subsequent calls
}catch( [ errorCode , errorString , handle ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.getSigner()
.then( ( signer ) => {
//'signer' contains information about the signer
//should be preserved for use in subsequent calls
})
.catch( [ errorCode , errorString , handle ] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
2. Initialize PDF signing
This function prepares the PDF for signing by adding signature related objects to the PDF and calculate and return the digest to be signed. If the host site permits more than one PDF document to be signed in a single call to the user, this function should be called once for each document.
The extension signs PDF with the signature status indicator (tick mark) in the bottom-left position of the signature by default.
Function name
XORKEESIGN.init
Input
Parameter
Data Type
Description
signerId
String
The output of XORKEESIGN.getSigner function should be provided.
Later the XORKEESIGN.sign function also takes the same input.
src
String/ArrayBuffer
Document to be signed can be fetched from a URL (string) or provided as a raw PDF (arraybuffer). Currently the size of the PDF document to be signed is restricted to 8 MB.
When provided as a URL the request payload should be empty. The response on connecting to the URL should be a raw PDF (without any encoding) with status code 200.
width
Number
The width of the area within which the signature appearance should be rendered. Defaults to 150 when not provided.
height
Number
The height of the area within which the signature appearance should be rendered. Defaults to 50 when not provided.
appearance
Array of strings
The default appearance when an empty array is provided will contain the text:
Digitally signed by
<subject common name in the digital certificate>
Otherwise only the line items specified will be printed where each item in the array will be rendered in separate lines.
If the length of a line exceeds the specified width, it will be wrapped to the next line.
If the height of the appearance exceeds the specified height, the additional line items will not be visible. In this case either reduce the number of line items or increase the height of the appearance.
positions
Array of objects
Each item in the array contains the page number and the position in which the signature appearance should be rendered and is of the following format:
{pageNum: <Number>,x: <Number>,y: <Number>}
This is provided as an array of objects to allow the consumer to place the signature appearance in multiple positions within the PDF. The page number and position should be a positive integer.
The page number should be valid for the given PDF else the function fails. When the position provided is beyond the boundaries of the page, it will be auto-corrected to the nearest boundary to fall within the page. The position corresponds to the bottom-left of the appearance boundary.
destURL
String
Optional
The output of this function will be an intermediate PDF (without signatures) that should be provided as input to subsequent functions. This cannot be preserved in the client side (ie. the web page) when multiple documents are to be signed. In those scenarios a URL can be specified here to save/upload the intermediate PDF at the server end.
The URL should expect to receive only the raw PDF buffer (without any encoding) in the request payload where a response status code of 200 will be termed as success.
| Parameter | Data Type | Description |
|---|---|---|
| signerId | String |
The output of XORKEESIGN.getSigner function should be provided. Later the XORKEESIGN.sign function also takes the same input. |
| src | String/ArrayBuffer |
Document to be signed can be fetched from a URL (string) or provided as a raw PDF (arraybuffer). Currently the size of the PDF document to be signed is restricted to 8 MB. When provided as a URL the request payload should be empty. The response on connecting to the URL should be a raw PDF (without any encoding) with status code 200. |
| width | Number | The width of the area within which the signature appearance should be rendered. Defaults to 150 when not provided. |
| height | Number | The height of the area within which the signature appearance should be rendered. Defaults to 50 when not provided. |
| appearance | Array of strings |
The default appearance when an empty array is provided will contain the text:
Digitally signed by Otherwise only the line items specified will be printed where each item in the array will be rendered in separate lines. If the length of a line exceeds the specified width, it will be wrapped to the next line. If the height of the appearance exceeds the specified height, the additional line items will not be visible. In this case either reduce the number of line items or increase the height of the appearance. |
| positions | Array of objects |
Each item in the array contains the page number and the position in which the signature appearance should be rendered and is of the following format: {pageNum: <Number>,x: <Number>,y: <Number>} This is provided as an array of objects to allow the consumer to place the signature appearance in multiple positions within the PDF. The page number and position should be a positive integer. The page number should be valid for the given PDF else the function fails. When the position provided is beyond the boundaries of the page, it will be auto-corrected to the nearest boundary to fall within the page. The position corresponds to the bottom-left of the appearance boundary. |
| destURL | String |
Optional The output of this function will be an intermediate PDF (without signatures) that should be provided as input to subsequent functions. This cannot be preserved in the client side (ie. the web page) when multiple documents are to be signed. In those scenarios a URL can be specified here to save/upload the intermediate PDF at the server end. The URL should expect to receive only the raw PDF buffer (without any encoding) in the request payload where a response status code of 200 will be termed as success. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| ArrayBuffer |
An intermediate PDF (without signatures) as raw buffer (without any encoding) that should be passed to subsequent functions. This should be preserved in the web page when the destURL is not provided as input. |
|
| digest | ArrayBuffer |
The SHA2 digest of the PDF to be signed. This should be preserved in the web page and provided as input to subsequent calls. |
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
Usage
const appearance = [
"Location: Chennai",
"Reason: Signed using xorkee",
"Date: 25-03-2025 04:12:23"
];
const positions = [
{ pageNum: 1, x: 10, y: 10 },
{ pageNum: 2, x: 500, y: 10 }
];
Method 1 (synchronous)
try {
const [ temppdf , digest ] = await XORKEESIGN.init( signer ,
"https://yourdomain/get/unsigned.pdf" ,
150 , 50 , appearance , positions ,
"https://yourdomain/upload/unsignedtemp.pdf" );
/*
* 'temppdf' contains the temporary PDF without the signature
* can be preserved in the page context if destination URL is not available
* 'digest' is the hash of the data to be signed
* should be preserved in the page context to get the signature
*/
} catch( [ errorCode , errorString , handle ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.init( signer , "https://yourdomain/get/unsigned.pdf" ,
150 , 50 , appearance, positions ,
"https://yourdomain/upload/unsignedtemp.pdf" )
.then( ( [ temppdf , digest ] ) =>
/*
* 'temppdf' contains the temporary PDF without the signature
* can be preserved in the page context if destination URL is not available
* 'digest' is the hash of the data to be signed
* should be preserved in the page context to get the signature
*/
})
.catch( [ errorCode , errorString , handle ] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
3. Sign PDF digest
This function gets the signature from the user (identified by the xorkee handle) through xorkee. It would suffice to call this function once even to get multiple signatures. To sign multiple documents in one go the signer should have a dual subscription (2 units/month) to xorkeesign. Other signers need to have only a standard subscription (1 unit/month).
Function name
XORKEESIGN.sign
Input
Parameter
Data Type
Description
signer
Object
The output of XORKEESIGN.getSigner function should be provided.
The previous call to XORKEESIGN.init should have been made with the same signer object as input
digest
Array of ArrayBuffer
This is the digest returned from call(s) to XORKEESIGN.init function. This should be an array even if a single document is taken for signing. A maximum of 100 digests can be inputted at a time.
| Parameter | Data Type | Description |
|---|---|---|
| signer | Object |
The output of XORKEESIGN.getSigner function should be provided. The previous call to XORKEESIGN.init should have been made with the same signer object as input |
| digest | Array of ArrayBuffer |
This is the digest returned from call(s) to XORKEESIGN.init function. This should be an array even if a single document is taken for signing. A maximum of 100 digests can be inputted at a time. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
| Parameter | Data Type | Description |
|---|---|---|
| signature | Array of ArrayBuffer |
The PKCS#7 formatted signatures from the user. The number of signatures in the array can be one or many depending on the number of digests provided as input. |
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
| subscriptionUrl | String | Optional. When available this URL points to a web page in xorkeesign where the user can make payment to purchase or renew the xorkeesign subscription. |
Usage
Method 1 (synchronous)
try {
const signatures = await XORKEESIGN.sign( signer , digest );
//'signatures' contains the list of signatures for the provided digests
//should be preserved in page context for attaching the signature to the temporary PDF
}catch( [ errorCode , errorString , handle , subscriptionUrl ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.sign( signer , digest ,
.then( (signatures) => {
//'signatures' contains the list of signatures for the provided digests
//should be preserved in page context for attaching the signature to the temporary PDF
})
.catch( [ errorCode , errorString , handle , subscriptionUrl ] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
4. Finalize PDF signing
The function packs the signature into the intermediate PDF (returned in XORKEESIGN.init) and make it final. As this function takes only one PDF and signature as input, it should be called multiple times when more than one document are signed in one go.
Function name
XORKEESIGN.finalize
Input
Parameter
Data Type
Description
src
String / ArrayBuffer
The intermediate PDF generated from a call to XORKEESIGN.init should be provided as input.
When this was previously uploaded to the server using the destURL parameter in the XORKEESIGN.init function, then a URL to fetch the same should be provided here as a string else this should contain the raw PDF as arraybuffer. (The host page can retrieve it from the server and present it here).
When provided as a URL the request payload should be empty. The response upon connecting to the URL should be a raw PDF (without any encoding) with status code 200.
signature
ArrayBuffer
The signature corresponding to the digest of the intermediate PDF should be provided here. The signature would have been received in a call to XORKEESIGN.sign function
destURL
String
Optional. The output of this function will be a signed PDF. The host page should take care of storing/uploading this document. It is advisable not to retain the PDF in the same ArrayBuffer that was returned from XORKEESIGN.init
Alternately, a URL can be specified here to save/upload the signed PDF to the server by the API itself.
The URL should expect to receive only the raw PDF buffer (without any encoding) in the request payload where a response status code of 200 will be termed as success.
| Parameter | Data Type | Description |
|---|---|---|
| src | String / ArrayBuffer |
The intermediate PDF generated from a call to XORKEESIGN.init should be provided as input. When this was previously uploaded to the server using the destURL parameter in the XORKEESIGN.init function, then a URL to fetch the same should be provided here as a string else this should contain the raw PDF as arraybuffer. (The host page can retrieve it from the server and present it here). When provided as a URL the request payload should be empty. The response upon connecting to the URL should be a raw PDF (without any encoding) with status code 200. |
| signature | ArrayBuffer |
The signature corresponding to the digest of the intermediate PDF should be provided here. The signature would have been received in a call to XORKEESIGN.sign function |
| destURL | String |
Optional. The output of this function will be a signed PDF. The host page should take care of storing/uploading this document. It is advisable not to retain the PDF in the same ArrayBuffer that was returned from XORKEESIGN.init Alternately, a URL can be specified here to save/upload the signed PDF to the server by the API itself. The URL should expect to receive only the raw PDF buffer (without any encoding) in the request payload where a response status code of 200 will be termed as success. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
| Parameter | Data Type | Description |
|---|---|---|
| signedPdf | ArrayBuffer |
The PDF signed by the user. This will be returned even where the caller contained a destination URL for the API to upload the document. |
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
| subscriptionUrl | String | Optional. When available this URL points to a web page in xorkeesign where the user can make payment to purchase or renew the xorkeesign subscription. |
Usage
Method 1 (synchronous)
try {
const signedpdf = await XORKEESIGN.finalize("https://yourdomain/upload/unsignedtemp.pdf",signature,
"https://yourdomain/upload/signed.pdf");
//'signedpdf' contains the final PDF with signature
//the signed PDF will be uploaded if the destination URL is provided
}catch( [ errorCode , errorString , handle ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.finalize( "https://yourdomain/upload/unsignedtemp.pdf" , signature , "https://yourdomain/upload/signed.pdf" )
.then( ( signedpdf ) => {
//'signedpdf' contains the final PDF with signature
//the signed PDF will be uploaded if the destination URL is provided
})
.catch( [ errorCode , errorString , handle ] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
Sign documents other than PDF
Documents other than PDF can be signed in a standard compliant PKCS#7 signed data format (RFC 5652). The call includes an option to include the data in the signature (attached signature). Another option can be specified to include the signer’s certificate in the signature. The API verifies the signatures before returning them to the caller.
It is recommended to provide the certificate while calling the function, as the signature can be later verified against that certificate. When not provided the signature verification will be performed with the certificate that is available within the signature received from the user. When the certificate is not passed as input and also not available within the signature the host site should verify the signature before acting on the same. PKCS#7 signature verification is available in many programming languages and tools like OpenSSL for the site to independently validate if desired.
The signature can be computed over the document/data or just using a digest. Whenever the data is provided, the API computes the digest locally in the browser and sends only the digest to xorkeesign for signature. Currently only SHA2 digest algorithm is supported. The maximum size of the document/data that can be provided is 8 MB.
Apart from signing documents, consumers can build various useful solutions using PKCS#7 signatures. It can be used for authentication, HTML form signing, workflow management, user consent, etc. Depending upon the use case the data to be signed should be framed in a manner that suits the need.
Consumers planning to use digital signatures for authentication can extract the digital certificate and save them against a user identifier. Later at the time of login the user identifier can be used as the data to be signed and the user can be allowed to login only if the resulting signature verifies fine.
1. Sign data as PKCS#7
This function is used to sign the data in PKCS#7 signed data format whenever the signer has a qualified digital certificate. If the signer certificate is not available, the host site can prompt for the xorkee handle of the signer to pass as input to this function. The caller is provided with options to pack the data and the certificate (along with the complete certificate chain if necessary).
Function name
XORKEESIGN.p7SignData
Input
Parameter
Data Type
Description
signer
String
The signer’s X.509 certificate in base 64 encoded format or xorkee handle in plain without any encoding.
This should be null or undefined when neither the certificate nor the xorkee handle is available, in which case the signer’s xorkee handle will be prompted.
tbs
String
The data to be signed in base 64 encoded format.
includeData
Boolean
Set this to true whenever the data to be signed needs to be included into the signature.
includeCert
Boolean
Should be true whenever the signer’s certificate needs to be packed into the signature. It is advised to set this to true whenever the consumer doesn’t have the certificate of the signer
includeChain
Boolean
Set this to true whenever the complete certificate chain corresponding to the signer should be included into the signature. It is advised not to set this flag indiscriminately as it will substantially increase the size and corresponding load on both the API and the host application. There could also be performance compromises.
| Parameter | Data Type | Description |
|---|---|---|
| signer | String |
The signer’s X.509 certificate in base 64 encoded format or xorkee handle in plain without any encoding. This should be null or undefined when neither the certificate nor the xorkee handle is available, in which case the signer’s xorkee handle will be prompted. |
| tbs | String |
The data to be signed in base 64 encoded format. |
| includeData | Boolean |
Set this to true whenever the data to be signed needs to be included into the signature. |
| includeCert | Boolean |
Should be true whenever the signer’s certificate needs to be packed into the signature. It is advised to set this to true whenever the consumer doesn’t have the certificate of the signer |
| includeChain | Boolean |
Set this to true whenever the complete certificate chain corresponding to the signer should be included into the signature. It is advised not to set this flag indiscriminately as it will substantially increase the size and corresponding load on both the API and the host application. There could also be performance compromises. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| signature | String | Signature will be returned as PKCS#7 signed data in base 64 encoded format. The data, signer certificate and certificate chain will be included based on the inputs provided while calling the function. |
| certificate | String | Digital certificate of the signer in base 64 encoded format. This will be null when the certificate itself is provided as input. |
| signerInfo | Object |
|
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
| subscriptionUrl | String | Optional. When available this URL points to a web page in xorkeesign where the user can make payment to purchase or renew the xorkeesign subscription. |
Usage
Method 1 (synchronous)
try {
const [ signature , certificate , signerInfo ] = await XORKEESIGN.p7SignData( certificate , tbs , true , true , false );
/*
* 'signature' contains the PKCS#7 signature from the signer
* 'certificate' is the digital certificate of the signer
* this will be 'null' when the certificate is provided as input
* 'signerInfo' contains information extracted from the signer's certificate
*/
} catch( [ errorCode , errorString , handle , subscriptionUrl ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.p7SignData(certificate , tbs , true , true , false)
.then( ( [ signature , certificate , signerInfo ] ) => {
/*
* 'signature' contains the PKCS#7 signature from the signer
* 'certificate' is the digital certificate of the signer
* this will be 'null' when the certificate is provided as input
* 'signerInfo' contains information extracted from the signer's certificate
*/
//should be preserved for use in subsequent calls
})
.catch( [errorCode , errorString , handle , subscriptionUrl] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
2. Sign digest as PKCS#7
This function is similar to the XORKEESIGN.p7SignDigest function where instead of the data we take the digest of the data as input. This would be useful in scenarios where the size of the data to be signed is greater than 8 MB. The host site can compute the digest at its server and send it to the web page to get the user’s signature.
If the host server can create the digest of a PDF document as per the PDF signature specifications, the signature from this function can be embedded into the document to form a signed PDF. To sign PDF documents the function should be invoked to include the digital certificate of the signer ie. the ‘includeCert’ argument should be true.
Function name
XORKEESIGN.p7SignDigest
Input
Parameter
Data Type
Description
signer
String
The signer’s X.509 certificate in base 64 encoded format or xorkee handle in plain without any encoding.
This should be null or undefined when neither the certificate nor the xorkee handle is available, in which case the signer’s xorkee handle will be prompted.
digest
String
The SHA256 digest of the data to be signed in base 64 encoded format.
includeCert
Boolean
Should be true whenever the signer’s certificate needs to be packed into the signature. It is advised to set this to true whenever the consumer doesn’t have the certificate of the signer.
includeChain
Boolean
Set this to true whenever the complete certificate chain corresponding to the signer should be included into the signature. It is advised not to set this flag indiscriminately as it will substantially increase the size and corresponding load on both the API and the host application. There could also be performance compromises.
| Parameter | Data Type | Description |
|---|---|---|
| signer | String |
The signer’s X.509 certificate in base 64 encoded format or xorkee handle in plain without any encoding. This should be null or undefined when neither the certificate nor the xorkee handle is available, in which case the signer’s xorkee handle will be prompted. |
| digest | String | The SHA256 digest of the data to be signed in base 64 encoded format. |
| includeCert | Boolean |
Should be true whenever the signer’s certificate needs to be packed into the signature. It is advised to set this to true whenever the consumer doesn’t have the certificate of the signer. |
| includeChain | Boolean |
Set this to true whenever the complete certificate chain corresponding to the signer should be included into the signature. It is advised not to set this flag indiscriminately as it will substantially increase the size and corresponding load on both the API and the host application. There could also be performance compromises. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| signature | String | Signature will be returned as PKCS#7 signed data in base 64 encoded format. The signer certificate and certificate chain will be included based on the inputs provided while calling the function. |
| certificate | String | Digital certificate of the signer in base 64 encoded format. This will be null when the certificate itself is provided as input. |
| signerInfo | Object |
|
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
| subscriptionUrl | String | Optional. When available this URL points to a web page in xorkeesign where the user can make payment to purchase or renew the xorkeesign subscription. |
Usage
Method 1 (synchronous)
try {
const [ signature , certificate , signerInfo ] = await XORKEESIGN.p7SignDigest( certificate , digest , true , false );
/*
* 'signature' contains the PKCS#7 signature from the signer
* 'certificate' is the digital certificate of the signer
* this will be 'null' when the certificate is provided as input
* 'signerInfo' contains information extracted from the signer's certificate
*/
} catch( [ errorCode , errorString , handle , subscriptionUrl ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.p7SignDigest(certificate , digest , true , false)
.then( ( [ signature , certificate , signerInfo ] ) => {
/*
* 'signature' contains the PKCS#7 signature from the signer
* 'certificate' is the digital certificate of the signer
* this will be 'null' when the certificate is provided as input
* 'signerInfo' contains information extracted from the signer's certificate
*/
//should be preserved for use in subsequent calls
})
.catch( [errorCode , errorString , handle , subscriptionUrl] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
3. Sign multiple digests as PKCS#7
This function is similar to the XORKEESIGN.p7SignDigest function where multiple digests can be provided at the same time to get the signatures. The maximum number of digests that can be provided is 100. All the digests will be signed through a single notification to the user’s xorkee app. Apart from the regular subscription, one unit will be additionally charged for a user-signer to avail this facility.
Function name
XORKEESIGN.p7SignMultipleDigest
Input
| Parameter | Data Type | Description |
|---|---|---|
| signer | String |
The signer’s X.509 certificate in base 64 encoded format or xorkee handle in plain without any encoding. This should be null or undefined when neither the certificate nor the xorkee handle is available, in which case the signer’s xorkee handle will be prompted. |
| digest | Array of String | The SHA256 digest of the data to be signed in base 64 encoded format. |
| includeCert | Boolean |
Should be true whenever the signer’s certificate needs to be packed into the signature. It is advised to set this to true whenever the consumer doesn’t have the certificate of the signer. |
| includeChain | Boolean |
Set this to true whenever the complete certificate chain corresponding to the signer should be included into the signature. It is advised not to set this flag indiscriminately as it will substantially increase the size and corresponding load on both the API and the host application. There could also be performance compromises. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| signatures | Array of String | Signatures corresponding to the digests provided as input will be returned in an array as PKCS#7 signed data in base 64 encoded format. The signer certificate and certificate chain will be included based on the inputs provided while calling the function. |
| certificate | String | Digital certificate of the signer in base 64 encoded format. This will be null when the certificate itself is provided as input. |
| signerInfo | Object |
|
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
| subscriptionUrl | String | Optional. When available this URL points to a web page in xorkeesign where the user can make payment to purchase or renew the xorkeesign subscription. |
Usage
Method 1 (synchronous)
try {
const [ signatures , certificate , signerInfo ] = await XORKEESIGN.p7SignMultipleDigest( certificate , digest , true , false );
/*
* 'signatures' contains the PKCS#7 signatures from the signer
* 'certificate' is the digital certificate of the signer
* this will be 'null' when the certificate is provided as input
* 'signerInfo' contains information extracted from the signer's certificate
*/
} catch( [ errorCode , errorString , handle , subscriptionUrl ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.p7SignMultipleDigest(certificate , digest , true , false)
.then( ( [ signatures , certificate , signerInfo ] ) => {
/*
* 'signatures' contains the PKCS#7 signature from the signer
* 'certificate' is the digital certificate of the signer
* this will be 'null' when the certificate is provided as input
* 'signerInfo' contains information extracted from the signer's certificate
*/
//should be preserved for use in subsequent calls
})
.catch( [errorCode , errorString , handle , subscriptionUrl] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
Encryption and Decryption
xorkeesign supports hybrid encryption following the PKCS#7 Enveloped Data Format (RFC 5652). Here the data is encrypted using AES-256 algorithm in GCM mode and the data encryption key is protected using RSA public keys (ie. the encryption certificate) of the intended recipients.
By principle and by design xorkeesign supports encryption only when the keys are certified by a public CA under the Indian CCA hierarchy. Moreover the encryption certificate holder should have a qualified signing certificate and a xorkee handle corresponding to the signing certificate. Both the signing and encryption certificates should be available in a cryptographic token (either same or different tokens).
The host site can query the encryption certificates that are under the possession of the user by providing the user's signing certificate to the API. On user's consent through xorkee, the API will return all the encryption certificates from the token carrying the signing certificate and any certificates found in any other USB tokens connected to the same system and the user will be allowed to choose one of the certificates. The encryption certificate that is chosen by the user can then be stored against the user identifier.
While mapping the encryption certificate against a user, it is advised to get the user's consent by means of a PKCS#7 signature using the XORKEESIGN.p7SignData or XORKEESIGN.p7SignDigest interfaces with the encryption certificate as the data to be signed. The host site should save the user consent against the user.
To encrypt the data, the encryption certificates of all the recipients (or the person whom the data is intended for) should be provided and the API will return a single PKCS#7 enveloped data encompassing all the information required to decrypt the same. Even here the encryption happens locally in the browser but the user's consent is not required as it involves only the public keys.
To decrypt the data, both the signing and encryption certificate of the recipient should be provided. The token carrying the decryption key and the signing key should be plugged into the same machine with the xorkee app and the data-encryption key will be decrypted once the user enters the token password. The actual data decryption will happen locally in the browser.
1. Get encryption certificates
To encrypt the data in hybrid format, the host site should have the encryption certificate of the recipient/user for whom the data is to be encrypted. This function gets all the encryption certificates available with the intended recipient. The recipient will be identified through the signing certificate.
The host site can list all the certificates to the user allowing her to choose the one that will be used for encryption. This function also returns a few information extracted from the certificate that can be presented to the user to aid her select a certificate.
Function name
XORKEESIGN.getEncryptionCerts
Input
Parameter
Data Type
Description
signerCert
String
The X.509 signing certificate of the user/recipient in base 64 encoded format
| Parameter | Data Type | Description |
|---|---|---|
| signerCert | String | The X.509 signing certificate of the user/recipient in base 64 encoded format |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
An array of JavaScript objects will be provided where each object will represent an encryption certificate with the following keys:
| Parameter | Data Type | Description |
|---|---|---|
| certificate | String | An encryption certificate in base 64 encoded format. |
| subjectCn | String | Subject common name as available in the encryption certificate. |
| issuerCn | String | Issuer common name as available in the encryption certificate. |
| validFrom | Number | The data from which the encryption certificate was valid in epoch time format |
| validTill | Number | The date till which the encryption certificate will be valid in epoch time format |
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
| subscriptionUrl | String | Optional. When available this URL points to a web page in xorkeesign where the user can make payment to purchase or renew the xorkeesign subscription. |
Usage
Method 1 (synchronous)
try {
const encCerts = await XORKEESIGN.getEncryptionCerts(signerCert);
//'encCerts' is an array of objects
//each object contains an encryption certificate
//and a few other information extracted from the certificate
}catch( [ errorCode , errorString , handle , subscriptionUrl] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.getEncryptionCerts(signerCert)
.then( ( signerCert ) => {
//'encCerts' is an array of objects
//each object contains an encryption certificate
//and a few other information extracted from the certificate
})
.catch( [ errorCode , errorString , handle , subscriptionUrl] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
2. Encryption
The data will be encrypted using a AES-256 symmetric key and this data encryption key will be encrypted using the certificates of one or more recipients. The data encryption key will be generated internally in the function and will not be available to the caller. The encryption certificates fetched from the recipients using the XORKEESIGN.getEncryptionCerts interface should be saved by the host site and provided here as input.
User consent is not required for encryption as only the public keys are involved. It is up to the caller to carefully preserve the list of recipients and input the corresponding encryption certificate at the time of decryption.
Function name
XORKEESIGN.encrypt
Input
Parameter
Data Type
Description
data
String
The data to be encrypted in base 64 encoded format.
encCerts
Array of Strings
The encryption certificate(s) in base 64 encoded format. If there are multiple recipients for the data, the encryption certificate of every user or the intended recipient should be provided.
| Parameter | Data Type | Description |
|---|---|---|
| data | String | The data to be encrypted in base 64 encoded format. |
| encCerts | Array of Strings | The encryption certificate(s) in base 64 encoded format. If there are multiple recipients for the data, the encryption certificate of every user or the intended recipient should be provided. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
| Parameter | Data Type | Description |
|---|---|---|
| encData | String | PKCS#7 enveloped data in base 64 encoded format encompassing all the information required at the time of decryption. |
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
Usage
Method 1 (synchronous)
try {
const encData = await XORKEESIGN.encrypt( data , encCerts );
//'encData' contains the encrypted data in PKCS#7 enveloped data format
}catch( [ errorCode , errorString , handle ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.encrypt(data, encCerts)
.then( ( encData ) => {
//'encData' contains the encrypted data in PKCS#7 enveloped data format
})
.catch( [ errorCode , errorString , handle ] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
3. Decryption
The PKCS#7 enveloped data can be decrypted using this function. The signing certificate will be used to identify the user/recipient and the encryption certificate will be used to identify the decryption key. Once the key is decrypted, the data decryption will happen locally in the browser. Even if there are multiple recipients, the presence of at least one recipient will be sufficient to decrypt the data.
Function name
XORKEESIGN.decrypt
Input
Parameter
Data Type
Description
signerCert
String
The X.509 signing certificate of the user/recipient in base 64 encoded format.
encCert
String
The certificate which was used for encryption in base 64 encoded format.
encData
String
PKCS#7 enveloped data in base 64 encoded format that has to be decrypted.
| Parameter | Data Type | Description |
|---|---|---|
| signerCert | String | The X.509 signing certificate of the user/recipient in base 64 encoded format. |
| encCert | String | The certificate which was used for encryption in base 64 encoded format. |
| encData | String | PKCS#7 enveloped data in base 64 encoded format that has to be decrypted. |
Output
A promise will be returned which will be resolved upon success or rejected upon error.
Success
| Parameter | Data Type | Description |
|---|---|---|
| decData | String | The decrypted data in base 64 encoded format. |
Error
The following parameters will be returned as an array in the specified order:
| Parameter | Data Type | Description |
|---|---|---|
| errorCode | Number | Based on the error code the host site can guide its users to take appropriate action. |
| errorString | String | The error message can be displayed as such or customized by the host site based on the error code. |
| handle | String | Optional. The xorkee handle of the user. |
| subscriptionUrl | String | Optional. When available this URL points to a web page in xorkeesign where the user can make payment to purchase or renew the xorkeesign subscription. |
Usage
Method 1 (synchronous)
try {
const encData = await XORKEESIGN.decrypt( signerCert , encCert , encData );
//'decData' contains the decrypted data in base 64 encoded format
}catch( [ errorCode , errorString , handle ] ) {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
}
Method 2 (asynchronous)
XORKEESIGN.decrpt( signerCert , encCert , encData )
.then( ( decData ) => {
//'decData' contains the decrypted data in base 64 encoded format
})
.catch( [ errorCode , errorString , handle , subscriptionUrl ] ) => {
//host site should take appropriate action based on the error code
//error message can be displayed by the host site
});
Error Code Interpretation
Based on the error code returned by the API, the host site can guide its users to take appropriate action. The following are the list of error codes and possible course of action:
| Error Code | Error Description | Action |
|---|---|---|
| -1014 | User declined to sign | Display an error message and tell the user to try again if the request was declined by mistake or else stop proceeding. |
| -1015 | User declined to enroll in xorkeesign | Whenever a user who is not enrolled in xorkeesign is a target of the API, xorkeesign will first notify in the xorkee app to enroll before proceeding. If the user declines this notification, display an error message and tell the user to try again if the request was declined by mistake or else stop proceeding. |
| -1016 | User failed to respond | The user might have missed the xorkee notification or her device is not connected to the network. Guide the user to check the network settings and attend to the notification the next time. |
| -1020 | DSC Unavailable | There is no DSC associated with the xorkee handle. User should connect the DSC token to an internet connected PC/mobile with xorkee app and then create a handle for that DSC. |
| -1037 | Invalid DSC | User should use an appropriate DSC or procure a new one. Probably the signing/encryption DSC was not issued by a CA under the Indian CCA hierarchy or not intended for the specified usage. |
| -1042 | User not reachable | The user can try again after connecting her crypto-token to an internet connected PC/mobile with xorkee app. If the token is already connected, the user should plug-out and plug-in the token again to continue. |
| -1043 | User blocked | User has been blocked from using xorkee. The user should contact her nominee (if any) associated with the handle to help regain access. |
| -1044 | Invalid handle | The handle is not registered in xorkee. Prompt the user to check the spelling of the entered handle. |
| -1050 | User certificate expired | The signing certificate has expired. User should get a new DSC and update it in xorkee to continue. |
| -1051 | User certificate revoked | The signing certificate has been revoked. User should get a new DSC and update it in xorkee to continue. |
| -1054 | User certificate on hold | The signing certificate is on hold. User should get a new DSC and update it in xorkee to continue. |
| -1076 | Incompatible xorkee app | Update the xorkee app to the latest version in the user’s PC/mobile in which the DSC token will be connected. |
| -1131 | DSC not registered in xorkee | User should connect the DSC token carrying the signing certificate to an internet connected PC/mobile with xorkee app and then create a handle for that DSC. |
| -1154 | Encryption certificate on hold | The encryption certificate is on hold. User should get a new DSC and update it in xorkee to continue. |
| -1158 | Subscription required |
User should purchase/renew her xorkeesign subscription. The API will also return the ‘subscriptionUrl’ in this case and the host site can direct the user to the subscription URL to complete the purchase and try again. |
| -1171 | Encryption DSC not found in same token | The encryption DSC is not found in the token carrying the signature DSC. User should connect the respective token carrying the DSC. |
| -1172 | Encryption DSC not found in different token | The encryption DSC is not found in any of the tokens connected to the machine in which the signature DSC is also connected. User should connect the respective token carrying the DSC. |
| -10000 | System error |
This is a result of the G2C extension or xorkeesign malfunction. Odyssey has taken appropriate measures to prevent this from happening. Inform the user a 'System error' and ask her to close the browser window/tab and try again from a new browser window/tab. |
| -10001 | Input error | This should occur only due to an error in the host site. Inform the user a 'System error' and request to try after some time. |
| -10002 | Network error |
The request was timed-out or aborted or resulted in an error due to restrictions in the system or the network. Guide the user to check their network connection and antivirus/firewall settings. Enterprise users should contact their network administrator. |
| -10003 | Payload size exceeded | Size of the input data or the parameters to the API cannot exceed 8 MB. |
| -10004 | User key changed | The DSC registered with the host site is different from the DSC available in xorkee. The host site should direct the user to update the association of the user identifier with the DSC available in xorkee ie. re-register the DSC in the host site. |
| -10005 | Recipient not found | The provided encryption DSC was not used to encrypt the data. This should occur only due to an error in the host site. Inform the user a 'System error' and request to try after some time. |
| -20001 | Encryption DSC expired | The encryption certificate has expired. User should get a new DSC and update it in the host site to continue. |
| -20002 | Encryption DSC revoked | The encryption certificate has been revoked. User should get a new DSC and update it in the host site to continue. |
When any error code other than the specified ones are received, the host site should treat it as a ‘System Error’ and handle accordingly.
Appendix A : Backward Compatibilty
The xorkeesign G2C JavaScript API version 1.* used the name space or variable xsPDF to expose the function calls. Starting from version 2.0 the name space is modified to XORKEESIGN as the scope of the API is expanded to documents other than PDF. But the older xsPDF name space will be preserved for backward compatibility. Newer consumers are discouraged from using the xsPDF name space as it will be deprecated in later releases.
Appendix B : xorkee handle
If the host site prompts the user for a xorkee handle, it should also validate the handle before passing it to the functions. The handle can be 4 to 64 characters in length (excluding the suffix '@xorkee.com') and can contain alphabets, numbers and a few special characters . (dot) , - (hyphen) , _ (underscore) , @ (address sign). The following regex pattern test will return false when the handle doesn't follow the syntax:
Appendix C: Sample source code
1. Single PDF signing
//check G2C extension is installed
if(typeof XORKEESIGN === "undefined") {
//G2C extension not installed
//provide instructions to install xorkeesign India G2C browser extension
} else {
//wrap the API calls inside try/catch to handle error scenarios
//which when encountered will be rejected in the Promise
try {
//get the xorkee handle of the signer
const signer = await XORKEESIGN.getSigner()
/*
* The HTTP request URL should be of method GET and
* the response payload should contain the raw unsigned PDF buffer
* without any encoding. HTTP response status code when not 200
* will be considered as failure.
*/
const inputPdfUrl = "https://yourdomain/get/unsigned.pdf";
//specify the dimensions of the PDF signature appearances
const width = 200;
const height = 50;
/*
* The default signature appearance will contain the text:
*
* Digitally signed by
* <subject common name in the digital certificate>
*
* Provide additional information you want to add as array of strings.
* Each item in the array will be printed line-by-line after the
* default appearance.
*
* If the length of a line exceeds the specified
* width, it will be automatically wrapped and printed in the next line.
*
* If the height of the appearance exceeds the specified height,
* the additional line items will not be visible. In this case you
* should reduce the number of line items or increase the height specified.
*/
const appearance = [
"Location: Chennai",
"Reason: Reviewed by HOD",
"Date: 25-03-2025 04:12:23",
];
/*
* Specify the page number (pageNum) and the position (x, y) in
* which the signature appearance should be placed.
*
* This is provided as an array of objects to allow the consumer
* to place the signature appearance in multiple positions.
*/
const positions = [
{ pageNum: 1, x: 10, y: 10 },
{ pageNum: 2, x: 50, y: 100 }
];
//compute the digest of the PDF to be signed
const [temporaryPdf, digest] = await XORKEESIGN.init(signer, inputPdfUrl, width, height,appearance, positions);
//sign the digest
const [signature] = await XORKEESIGN.sign(signer, [digest]);
/*
* The signed PDF can be uploaded to a HTTP POST URL.
* The raw signed PDF buffer will be sent in the request payload
* without any encoding. The website should respond with HTTP
* response status code 200 upon success.
*/
const uploadPdfUrl = "https://yourdomain/upload/signed.pdf";
/*
* Prepare the signed PDF.
* The 'temporaryPdf' and 'signature' from previous calls should
* be preserved and provided as input to this call.
*/
const signedPdf = await XORKEESIGN.finalize(temporaryPdf, signature, uploadPdfUrl);
} catch([errorCode, errorString, handle]) {
/*
* Some API resulted in an error and the Promise was rejected.
* Error message can be displayed by the host site.
* Website can allow the user to retry signing.
*/
console.log(errorString);
}
}
2. Multiple PDF signing
//check G2C extension is installed
if(typeof XORKEESIGN === "undefined") {
//G2C extension not installed
//provide instructions to install xorkeesign India G2C browser extension
} else {
//wrap the API calls inside try/catch to handle error scenarios
//which when encountered will be rejected in the Promise
try {
//get the xorkee handle of the signer
const signer = await XORKEESIGN.getSigner()
/*
* The HTTP request URL should be of method GET and
* the response payload should contain the raw unsigned PDF buffer
* without any encoding. HTTP response status code when not 200
* will be considered as failure.
*/
const inputPdfUrl = [
"https://yourdomain/getpdf?status=unsigned&docid=1",
"https://yourdomain/getpdf?status=unsigned&docid=2"
];
/*
* The dimension of the signature appearance and the positions
* in which it should be placed within the PDF can be different
* for each PDF to be signed.
* Here for the sake of clarity, we use the same dimension and
* position for all the PDF documents to be signed.
*/
const width = 200;
const height = 50;
const appearance = [
"Location: Chennai",
"Reason: Reviewed by HOD",
"Date: 25-03-2025 04:12:23",
];
const positions = [
{ pageNum: 1, x: 10, y: 10 },
{ pageNum: 2, x: 50, y: 100 }
];
/*
* The intermediate PDF (without signature) returned by the 'init' call
* should not be stored in the web page due to restrictions in the browser
* Hence the intermediate PDF should be uploaded to the website and preserved
* at the server end. The URL to store these intermediate PDF should be
* provided as an array of strings.
*/
const uploadPdfUrl = [
"https://yourdomain/uploadpdf?status=intermediate&docid=1",
"https://yourdomain/uploadpdf?status=intermediate&docid=2"
];
const digestArr = [];
//to preserve the digest of the PDF to be signed
//compute the digest of each PDF to be signed
for(let i=0; i<inputPdfUrl.length; i++) {
/*
* The PDF to be signed will be taken from 'inputPdfUrl' and the
* intermediatePdf will be stored in the 'uploadPdfUrl'.
* The returned 'digest' can be preserved in the web page itself.
*/
const [intermediatePdf, digest] = await XORKEESIGN.init(signer, inputPdfUrl[i],
width, height, appearance, positions, uploadPdfUrl[i]);
digestArr.push(digest);
}
//sign all the computed digest
const signatures = await XORKEESIGN.sign(signer, digestArr);
/*
* The "intermediatePdf" uploaded to the website in the 'init' call
* along with the "signature" received from the 'sign' call should be
* provided as input to the 'finalize' call to prepare the signed PDF.
*
* The website should have provision to retrieve the intermediate PDF
* saved in the 'init' call and also a facility to store the signed PDF.
*/
const intermediateUrl = [
"https://yourdomain/getpdf?status=intermediate&docid=1",
"https://yourdomain/getpdf?status=intermediate&docid=2"
];
const signedPdfUrl = [
//URL to upload the signed PDF
"https://yourdomain/uploadpdf?status=signed&docid=1",
"https://yourdomain/uploadpdf?status=signed&docid=2"
];
//'finalize' should be called for each intermediate PDF to embed the signature
for(let i=0; i<intermediateUrl.length; i++) {
const signedPdf = await XORKEESIGN.finalize(intermediateUrl[i],signatures[i],signedPdfUrl[i]);
}
} catch([errorCode, errorString, handle]) {
/*
* Some API resulted in an error and the Promise was rejected.
* Error message can be displayed by the host site.
* Website can allow the user to retry signing.
*/
console.log(errorString);
}
}