X.509 Certificate & CSR Tool API
Decode PEM or DER certificates, CSRs, keys, PKCS#7 and CRLs, check that a key matches its certificate, convert PEM↔DER, generate keys and CSRs.
action=decode (default): paste one or more PEM blocks in pem (or send a DER file / der_base64). Certificates come back with subject and issuer (UTF-8, Vietnamese names included), serial, validity and days remaining, SANs, key algorithm and size, signature algorithm, DV / OV / EV policy, basic constraints, key usage and extended key usage, key identifiers, OCSP / CA issuer / CRL URLs, SCT presence and SHA-256 / SHA-1 fingerprints. CSRs show the subject, requested SANs and extensions and whether their self-signature is valid; public and private keys (PKCS#8, PKCS#1, SEC1) show their type and size; PKCS#7 bundles (.p7b) list their certificates in PEM; CRLs list revoked serials. In a PEM bundle the chain order is checked (each certificate signed by the next one) and host tests a host name against the first certificate.
action=match tells whether a certificate, a CSR and a private key share the same public key (by SPKI SHA-256), the classic check before installing a certificate. action=convert returns each block as base64 DER and as PEM. action=generate creates an EC (P-256, P-384) or RSA (2048, 3072, 4096) key pair with WebCrypto and, when you give cn / subject / san, a signed CSR ready for a certificate authority; self_signed=true also issues a self-signed certificate for days (development, internal services). private_key (unencrypted PKCS#8 PEM) builds the CSR from your existing key instead.
Nothing is stored or logged: keys and certificates are processed in memory. Generating production keys on your own machine (openssl) is still the safest choice. Encrypted keys and PKCS#12 (.pfx) files are not supported.
Parameters
| Name | In | Type | Required | Default | |
|---|---|---|---|---|---|
action | body|query | string | no | decode | decode, match, convert or generate. |
pem | body | string | no | One or more PEM blocks (or base64 DER). Required except for generate. | |
file | body | file | no | A DER or PEM file instead of pem (multipart, raw body or der_base64). | |
host | body|query | string | no | decode / match: host name to test against the first certificate (wildcards handled). | |
at | body|query | string | no | decode: ISO date used for days_remaining / valid_now (default now). | |
key_type | body | string | no | ec | generate: ec or rsa. |
curve | body | string | no | P-256 | generate (EC): P-256 or P-384. |
bits | body | number | no | 2048 | generate (RSA): 2048, 3072 or 4096. |
cn | body | string | no | generate: common name (also o, ou, l, st, c, email, or a subject string such as /C=VN/O=ABC/CN=abc.vn). | |
san | body | array | no | generate: DNS names / IPs / e-mails for the SAN (default: the CN when it is a domain). | |
self_signed | body | boolean | no | false | generate: also issue a self-signed certificate. |
days | body | number | no | 365 | generate: validity of the self-signed certificate (1–3650 days). |
private_key | body | string | no | generate: existing unencrypted PKCS#8 PEM key to build the CSR with (no new key). |
Example
curl -X POST "https://apibox.io.vn/v1/x509" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"pem":"-----BEGIN CERTIFICATE-----\nMIICATCCAaegAwIBAgIQZ7JpDsbujH4Q+IqANm/6tDAKBggqhkjOPQQDAjA+MQsw\nCQYDVQQGEwJWTjEaMBgGA1UECgwRQ8O0bmcgdHkgVsOtIEThu6UxEzARBgNVBAMM\nCmV4YW1wbGUudm4wHhcNMjYxMTExMDMyMDUzWhcNMjcxMTExMDMyMDUzWjA+MQsw\nCQYDVQQGEwJWTjEaMBgGA1UECgwRQ8O0bmcgdHkgVsOtIEThu6UxEzARBgNVBAMM\nCmV4YW1wbGUudm4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARqqfLzQSw0vsTJ\nSybOOJ2tX5rVFJCJRh6Wcvb6K1D89M+GEuKtt6JKGDqNLGZ32GW6baSUnQs56CGI\nNgssWh4Vo4GGMIGDMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWAMB0GA1Ud\nJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUxdzC6thtbmfWlE+S\nOdJPhYgCErcwJQYDVR0RBB4wHIIKZXhhbXBsZS52boIOd3d3LmV4YW1wbGUudm4w\nCgYIKoZIzj0EAwIDSAAwRQIgAMtCLzFiC2E5JsJ+S6xrFZ23s4FRvkCfBkPQZB7+\n3SoCIQC9mrlvlIb9Rc3aDzs/GMNhn1L6UeveiH1AQNDciaZ8Uw==\n-----END CERTIFICATE-----\n"}'const res = await fetch('https://apibox.io.vn/v1/x509', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"pem": "-----BEGIN CERTIFICATE-----\nMIICATCCAaegAwIBAgIQZ7JpDsbujH4Q+IqANm/6tDAKBggqhkjOPQQDAjA+MQsw\nCQYDVQQGEwJWTjEaMBgGA1UECgwRQ8O0bmcgdHkgVsOtIEThu6UxEzARBgNVBAMM\nCmV4YW1wbGUudm4wHhcNMjYxMTExMDMyMDUzWhcNMjcxMTExMDMyMDUzWjA+MQsw\nCQYDVQQGEwJWTjEaMBgGA1UECgwRQ8O0bmcgdHkgVsOtIEThu6UxEzARBgNVBAMM\nCmV4YW1wbGUudm4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARqqfLzQSw0vsTJ\nSybOOJ2tX5rVFJCJRh6Wcvb6K1D89M+GEuKtt6JKGDqNLGZ32GW6baSUnQs56CGI\nNgssWh4Vo4GGMIGDMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWAMB0GA1Ud\nJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUxdzC6thtbmfWlE+S\nOdJPhYgCErcwJQYDVR0RBB4wHIIKZXhhbXBsZS52boIOd3d3LmV4YW1wbGUudm4w\nCgYIKoZIzj0EAwIDSAAwRQIgAMtCLzFiC2E5JsJ+S6xrFZ23s4FRvkCfBkPQZB7+\n3SoCIQC9mrlvlIb9Rc3aDzs/GMNhn1L6UeveiH1AQNDciaZ8Uw==\n-----END CERTIFICATE-----\n"
}),
});
const data = await res.json();
console.log(data);import requests
res = requests.post(
"https://apibox.io.vn/v1/x509",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"pem": "-----BEGIN CERTIFICATE-----\nMIICATCCAaegAwIBAgIQZ7JpDsbujH4Q+IqANm/6tDAKBggqhkjOPQQDAjA+MQsw\nCQYDVQQGEwJWTjEaMBgGA1UECgwRQ8O0bmcgdHkgVsOtIEThu6UxEzARBgNVBAMM\nCmV4YW1wbGUudm4wHhcNMjYxMTExMDMyMDUzWhcNMjcxMTExMDMyMDUzWjA+MQsw\nCQYDVQQGEwJWTjEaMBgGA1UECgwRQ8O0bmcgdHkgVsOtIEThu6UxEzARBgNVBAMM\nCmV4YW1wbGUudm4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARqqfLzQSw0vsTJ\nSybOOJ2tX5rVFJCJRh6Wcvb6K1D89M+GEuKtt6JKGDqNLGZ32GW6baSUnQs56CGI\nNgssWh4Vo4GGMIGDMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWAMB0GA1Ud\nJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUxdzC6thtbmfWlE+S\nOdJPhYgCErcwJQYDVR0RBB4wHIIKZXhhbXBsZS52boIOd3d3LmV4YW1wbGUudm4w\nCgYIKoZIzj0EAwIDSAAwRQIgAMtCLzFiC2E5JsJ+S6xrFZ23s4FRvkCfBkPQZB7+\n3SoCIQC9mrlvlIb9Rc3aDzs/GMNhn1L6UeveiH1AQNDciaZ8Uw==\n-----END CERTIFICATE-----\n"},
timeout=30,
)
print(res.json())<?php
$ch = curl_init('https://apibox.io.vn/v1/x509');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"pem":"-----BEGIN CERTIFICATE-----\\nMIICATCCAaegAwIBAgIQZ7JpDsbujH4Q+IqANm/6tDAKBggqhkjOPQQDAjA+MQsw\\nCQYDVQQGEwJWTjEaMBgGA1UECgwRQ8O0bmcgdHkgVsOtIEThu6UxEzARBgNVBAMM\\nCmV4YW1wbGUudm4wHhcNMjYxMTExMDMyMDUzWhcNMjcxMTExMDMyMDUzWjA+MQsw\\nCQYDVQQGEwJWTjEaMBgGA1UECgwRQ8O0bmcgdHkgVsOtIEThu6UxEzARBgNVBAMM\\nCmV4YW1wbGUudm4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARqqfLzQSw0vsTJ\\nSybOOJ2tX5rVFJCJRh6Wcvb6K1D89M+GEuKtt6JKGDqNLGZ32GW6baSUnQs56CGI\\nNgssWh4Vo4GGMIGDMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWAMB0GA1Ud\\nJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUxdzC6thtbmfWlE+S\\nOdJPhYgCErcwJQYDVR0RBB4wHIIKZXhhbXBsZS52boIOd3d3LmV4YW1wbGUudm4w\\nCgYIKoZIzj0EAwIDSAAwRQIgAMtCLzFiC2E5JsJ+S6xrFZ23s4FRvkCfBkPQZB7+\\n3SoCIQC9mrlvlIb9Rc3aDzs/GMNhn1L6UeveiH1AQNDciaZ8Uw==\\n-----END CERTIFICATE-----\\n"}',
]);
$response = curl_exec($ch);
print_r(json_decode($response, true));Response
{
"count": 1,
"items": [
{
"type": "certificate",
"der_bytes": 517,
"subject": "C=VN, O=Công ty Ví Dụ, CN=example.vn",
"subject_fields": {
"C": "VN",
"O": "Công ty Ví Dụ",
"CN": "example.vn"
},
"issuer": "C=VN, O=Công ty Ví Dụ, CN=example.vn",
"serial_number": "67:B2:69:0E:C6:EE:8C:7E:10:F8:8A:80:36:6F:FA:B4",
"version": 3,
"not_before": "2026-11-11T03:20:53Z",
"not_after": "2027-11-11T03:20:53Z",
"days_remaining": 364,
"valid_now": true,
"validity_days": 365,
"san": {
"dns": [
"example.vn",
"www.example.vn"
],
"ip": [],
"email": [],
"uri": []
},
"public_key": {
"algorithm": "EC",
"curve": "P-256",
"size": 256
},
"signature_algorithm": "ecdsa-with-SHA256",
"is_ca": false,
"self_signed": true,
"validation_level": null,
"extensions": {
"basic_constraints": {
"ca": false,
"path_length": null,
"critical": true
},
"key_usage": [
"digitalSignature"
],
"extended_key_usage": [
"serverAuth",
"clientAuth"
],
"subject_key_id": "C5:DC:C2:EA:D8:6D:6E:67:D6:94:4F:92:39:D2:4F:85:88:02:12:B7"
},
"fingerprints": {
"sha256": "95:73:C4:36:B0:18:EF:21:42:FD:CA:52:58:B7:81:75:7B:EE:A4:F1:5B:AA:83:34:20:0E:B2:C4:A9:7F:D5:06",
"sha1": "46:26:CA:A3:3B:35:F8:89:B6:81:F5:F9:E3:A1:3B:E5:BE:F7:FF:EB"
},
"spki_sha256": "cf57c6d726bb97a98ad7dc4b4595e423cc6b9a432eda486a9ec2286a2f3556d9"
}
],
"key_match": [
{
"spki_sha256": "cf57c6d726bb97a98ad7dc4b4595e423cc6b9a432eda486a9ec2286a2f3556d9",
"blocks": [
0
],
"types": [
"certificate"
]
}
]
}
Use cases
- Read the expiry date, SANs and issuer of a .crt or .pem file
- Check that a private key matches the certificate before installing it
- Generate a CSR with SANs to buy an SSL certificate
- Create a self-signed certificate for a test server
FAQ
Is my private key stored?
No. It is processed in memory for that request only and never logged. For production keys, prefer generating and matching them locally with openssl.
Which formats are accepted?
PEM blocks (CERTIFICATE, CERTIFICATE REQUEST, PUBLIC KEY, PRIVATE KEY, RSA / EC PRIVATE KEY, PKCS7, X509 CRL) and raw DER files. PKCS#12 / .pfx and encrypted keys are not supported.
Does decode verify the certificate is trusted?
No: it decodes and checks signatures between the certificates you send. Use ssl-check to test what a live server presents.
Related APIs
Hash Generator
Compute MD5, SHA-1, SHA-256, SHA-384, SHA-512 and CRC32 of text or files in one call, as hex or base64, with optional HMAC signing.
B64Encode / Decode
Encode or decode text as Base64, Base64URL, hex, URL encoding, HTML entities, Unicode escapes, ROT13 or binary with one simple API call.
***Password Generator
Generate cryptographically secure random passwords (4–256 chars, up to 100 at once) or check a password’s strength, entropy and estimated crack time.