This document explains how to integrate your system with RS-Imzo using API Key authentication for signing and verifying electronic documents.
The RS-Imzo integration allows third-party systems to:
Once the frontend retrieves the PKCS#7 signature, the backend uses the RS-Imzo APIs that enables applications to perform signature verification, signature merging, and authentication using PKCS#7 standard signatures.
$base_url=https://api.rs-imzo.uz/api/v1/backend
| Method | Endpoint | Description |
|---|---|---|
POST | /pkcs7/verify | Verify PKCS#7 signature |
POST | /pkcs7/merge | Merge two PKCS#7's into one |
POST | /auth | Authenticate and extract user's data |
All endpoints require the following headers:
| Header | Description |
|---|---|
X-API-KEY | Your organizationβs unique API key |
Content-Type | Always application/x-www-form-urlencoded |
Example:
X-API-KEY: your-api-key
Content-Type: application/x-www-form-urlencoded
| Field | Type | Description |
|---|---|---|
pkcs7 | string | Base64-encoded PKCS#7 signature |
detachedData | string | (Optional) Detached data, if available |
| Field | Type | Description |
|---|---|---|
data | string | The data that is signed by user (always base64) |
detached | boolean | It is an indicator that the pkcs7 is used as attached or detached |
signers | List<Signer> | Signers inside the PKCS#7 |
certificate | Object | It is an object the defines info of user, the issuer, the validness of the signature and etc.. |
digest | string | It is a signed content in md5 format |
signed_time | date | The time that the date signed on |
verified | boolean | The indication of the signature is verified or not |
issuer | Object | This is an object that defines the issuer of a signature |
serial | string | It is unique idetnifier for user's signature given by issuer |
subject | Object | The object that defines user's uid, country, personal info |
validity | Object | The object the determines the activation and expiration time for signature |
C | string | This determines the country of subject or issuer |
CN | string | Full name of signature owner |
O | string | Organization name |
1.3.6.1.4.1.64375.1.2 | string | PINPP of signature owner |
1.3.6.1.4.1.64375.1.1 | string | TIN of organization |
not_after | date | Determines the validness of a signature until this time |
not_before | date | Determines the validness of a signature before this time |
To verify a PKCS#7 signature:
curl -X POST "${base_url}/pkcs7/verify" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "X-API-Key: AIzaSyDaGmWKa4JsXZ-HjGw7ISLn_3namBGewQe" \
-d "pkcs7=MIICkQYJKoZIhvcNAQcCoIICgjCCAoYCAQExDzANBglghkgB..." \
-d "detachedData=''"
This method checks whether the PKCS#7 is valid and if so it gives the parsed pkcs7 in object formatted as ParsePkcs7.
{
"data": "nrtwegwjwenw",
"detached": true,
"signers": [
{
"certificate": {
"extensions": [
{
"oid": "",
"value": ""
}
],
"inbase64": "",
"issuer": {
"C": "",
"CN": "",
"O": "",
"L": ""
},
"serial": "",
"signature_algorithm": "",
"subject": {
"1.3.6.1.4.1.64375.1.2": "",
"1.3.6.1.4.1.64375.1.1": "",
"C": "",
"L": "",
"CN": "",
"O": "",
"documentIdentifier": ""
},
"subject_public_key_info": {
"algorithm": "",
"public_key": ""
},
"validity": {
"not_after": "",
"not_before": ""
},
"version": 1
},
"digest": "3369cd520c8e556502b9bc0ac34ca69cafee96f2f4a8371a63d4dd7d3a458d05",
"signed_time": "2022-09-27 11:17:53",
"verified": true
}
]
}
To merge 2 PKCS#7 signatures:
curl -X POST "${base_url}/pkcs7/merge" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "X-API-Key: AIzaSyDaGmWKa4JsXZ-HjGw7ISLn_3namBGewQe" \
-d "pkcs7=MIICkQYJKoZIhvcNAQcCoIICgjCCAoYCAQExDzANBglgh...|MIIFaAYJKoZIhvcNAQcCoIIFWTCCBVUCAQExDz..." \
-d "detachedData=''"
This method merges 2 pkcs7 signatures and gives the result object formatted as String.
MIICkQYJKoZIhvcNAQcCoIICgjCCAoYC...base64-encoded merged data...
To authenticate a user by their PKCS#7 signature:
curl -X POST "${base_url}/auth" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "X-API-Key: AIzaSyDaGmWKa4JsXZ-HjGw7ISLn_3namBGewQe" \
-d "pkcs7=MIICkQYJKoZIhvcNAQcCoIICgjCCAoYCAQExDzANBglghkgB..." \
-d "detachedData=''"
This method checks whether the PKCS#7 is valid and if so it gives the parsed pkcs7 in object formatted as ParsePkcs7.
{
"data": "nrtwegwjwenw",
"detached": true,
"signers": [
{
"certificate": {
"extensions": [
{
"oid": "",
"value": ""
}
],
"inbase64": "",
"issuer": {
"C": "",
"CN": "",
"O": "",
"L": ""
},
"serial": "",
"signature_algorithm": "",
"subject": {
"1.3.6.1.4.1.64375.1.2": "",
"1.3.6.1.4.1.64375.1.1": "",
"C": "",
"L": "",
"CN": "",
"O": "",
"documentIdentifier": ""
},
"subject_public_key_info": {
"algorithm": "",
"public_key": ""
},
"validity": {
"not_after": "",
"not_before": ""
},
"version": 1
},
"digest": "3369cd520c8e556502b9bc0ac34ca69cafee96f2f4a8371a63d4dd7d3a458d05",
"signed_time": "2022-09-27 11:17:53",
"verified": true
}
]
}
Below is an example of how to use RS-Imzoβs API endpoints in Java style using Springβs RestTemplate.
@Service
@Slf4j
public class RSImzoClient {
private final RestTemplate restTemplate;
public RSImzoClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
private static final String BASE_URL = "https://api.rs-imzo.uz/api/v1/backend";
private static final String API_KEY = "your-api-key";
private static final Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, (JsonDeserializer<Date>) (json, type, context) ->
new Date(json.getAsJsonPrimitive().getAsLong() * 1000))
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.setFieldNamingStrategy(FieldNamingPolicy.IDENTITY)
.create();
private String post(String url, Pkcs7Req req) {
try {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("X-API-Key", API_KEY);
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
String body = "pkcs7=" + req.getPkcs7() + "&detachedData=" + req.getDetachedData();
HttpEntity<String> entity = new HttpEntity<>(body, httpHeaders);
ResponseEntity<String> response = restTemplate.exchange(
BASE_URL + url,
HttpMethod.POST,
entity,
String.class
);
if (response.getStatusCode().isError()) {
throw new RuntimeException("Error: " + response.getBody());
}
return response.getBody();
} catch (Exception e) {
log.error("Error calling {}: {}", url, e.getMessage(), e);
throw new RuntimeException("Error during API call: " + e.getMessage(), e);
}
}
public ParsePkcs7 verifyPkcs7(Pkcs7Req req) {
String response = post("/pkcs7/verify", req);
return gson.fromJson(response, ParsePkcs7.class);
}
public String mergePkcs7(Pkcs7Req req) {
return post("/pkcs7/merge", req);
}
public ParsePkcs7 auth(Pkcs7Req req) {
String response = post("/auth", req);
return gson.fromJson(response, ParsePkcs7.class);
}
}
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("X-API-Key", API_KEY);
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
@Data
public class Pkcs7Req {
@SerializedName("pkcs7")
private String pkcs7;
@SerializedName("detachedData")
private String detachedData;
}
@Data
public class ParsePkcs7 {
@SerializedName("data")
private String data;
@SerializedName("detached")
private Boolean detached;
@SerializedName("signers")
private List<Signer> signers;
}
@Data
public class Signer {
@SerializedName("certificate")
private Certificate certificate;
@SerializedName("digest")
private String digest;
@SerializedName("signed_time")
private Date signedTime;
@SerializedName("verified")
private Boolean verified;
}
@Data
public class Certificate {
@SerializedName("extensions")
private List<Extension> extensions;
@SerializedName("inbase64")
private String inbase64;
@SerializedName("issuer")
private Issuer issuer;
@SerializedName("serial")
private String serial;
@SerializedName("signature_algorithm")
private String signatureAlgorithm;
@SerializedName("subject")
private Subject subject;
@SerializedName("subject_public_key_info")
private SubjectPublicKeyInfo subjectPublicKeyInfo;
@SerializedName("validity")
private Validity validity;
@SerializedName("version")
private Integer version;
}
@Data
public class Extension {
@SerializedName("oid")
private String oid;
@SerializedName("value")
private Object value;
}
@Data
public class Validity {
@SerializedName("not_after")
private Date activationDate;
@SerializedName("not_before")
private Date expirationDate;
}
@Data
public class SubjectPublicKeyInfo {
@SerializedName("algorithm")
private String algorithm;
@SerializedName("public_key")
private String publicKey;
}
@Data
public class Issuer {
@SerializedName("C")
private String country;
@SerializedName("CN")
private String companyRoot;
@SerializedName("O")
private String companyName;
@SerializedName("L")
private String address;
}
@Data
public class Subject {
@SerializedName("1.3.6.1.4.1.64375.1.2")
private String pinp;
@SerializedName("1.3.6.1.4.1.64375.1.1")
private String tin;
@SerializedName("C")
private String country;
@SerializedName("L")
private String address;
@SerializedName("CN")
private String fullName;
@SerializedName("O")
private String organizationName;
@SerializedName("documentIdentifier")
private String documentIdentifier;
}
verify, merge, auth) independently.Pkcs7Req req = new Pkcs7Req();
req.setPkcs7("MIIBase64Example...");
req.setDetachedData("optional-data");
ParsePkcs7 result = rsImzoClient.verifyPkcs7(req);
String oldPkcs7 = "MIICkQYJKoZIhvcNAQcCoIICgjCCAoYCAQExDz...";
String newPkcs7 = "MIIFaAYJKoZIhvcNAQcCoIIFWTCCBVUCAQExDz...";
Pkcs7Req req = new Pkcs7Req();
req.setPkcs7(oldPkcs7 + "|" + newPkcs7);
req.setDetachedData("optional-data");
String mergedPkcs7 = rsImzoClient.mergePkcs7(req, headers);
Pkcs7Req req = new Pkcs7Req();
req.setPkcs7("MIIBase64Example...");
req.setDetachedData("optional-data");
ParsePkcs7 result = rsImzoClient.auth(req);
X-API-KEY from RS-Imzo admin.RSImzoClient service.verify, merge, and auth APIs in your application.| Component | Purpose | Authentication |
|---|---|---|
| Frontend | Validates domain registration | Authorization: Bearer <PUBLIC_KEY> |
| Backend | Verifies, merges or authenticates PKCS#7 signatures | X-API-Key: <API_KEY> |
ββββββββββββββββββββββββββ ββββββββββββββββββββββββββ ββββββββββββββββββββββββββ ββββββββββββββββββββββββββ
β Integrating Frontend β βββββββββββββΊ β RS-Imzo Frontend SDK β ββββββΊ β RS-Imzo Backend β ββββββΊ β Integrating Backend β
ββββββββββββββββββββββββββ ββββββββββββββββββββββββββ ββββββββββββββββββββββββββ ββββββββββββββββββββββββββ
β β β β
β (1) Request PKCS#7 with β β β
β Authorization: Bearer <PUBLIC_KEY>β β β
βββββββββββββββββββββββββββββββββββββββββΊβ β β
β β (2) Validate domain + publicKey β β
β ββββββββββββββββββββββββββββββββββΊ β β
β (3) Return PKCS#7 or Unauthorized β β β
ββββββββββββββββββββββββββββββββββββββββββ β β
β β β β
β (4) Send PKCS#7 to backend β β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββΊβ
β β β β
β β β (6) Request PKCS#7 or β
| | | merged PKCS#7 with |
β | | X-API-Key: <API_KEY> |
β β ββββββββββββββββββββββββββββββββββ
β β β β
β β β β
β β β (7) Return parsedPkcs7 or β
β β β Unauthorized β
β β βββββββββββββββββββββββββββββββββΊβ
β β β |
β β | |
β (9) Return verify/merge/auth β β β
β result β β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
apiKey matches the organization that owns the public key.