Build a PKCS#10 certificate signing request with subject alternative names, RSA, ECDSA or Ed25519. Signed and verified in the page before you send it to a CA.
Initializing in your browser…
Generate SSL/TLS certificates for local development, with hostnames placed in the Subject Alternative Name where browsers look. Exports PKCS#8, PKCS#1 and PKCS#12, with fingerprints and install config.
Generate an SSH key pair in the OpenSSH format ssh-keygen writes: Ed25519, ECDSA or RSA, with the fingerprint and randomart it prints.
Read the certificate chain a server sends and say whether it is complete, in order and in date, and build the OpenSSL commands that fetch it.
A German shop needs a certificate covering shop.example.de, the bare domain and the www host, and the legal organisation name has an umlaut and an eszett in it.
Typed into the form
Common Name shop.example.de Organization Münchener Straßenbahn GmbH Locality München Country DE Alternative names example.de, www.example.de Key ECDSA P-256
openssl req -in shop.example.de.csr -noout -text -verify
Certificate request self-signature verify OK
Certificate Request:
Data:
Version: 1 (0x0)
Subject: CN=shop.example.de, O=Münchener Straßenbahn GmbH, L=München, C=DE
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:shop.example.de, DNS:example.de, DNS:www.example.de
Signature Algorithm: ecdsa-with-SHA256
and the string types, from openssl asn1parse:
22:d=5 hl=2 l= 15 prim: PRINTABLESTRING :shop.example.de
48:d=5 hl=2 l= 28 prim: UTF8STRING :Münchener Straßenbahn GmbH
87:d=5 hl=2 l= 8 prim: UTF8STRING :München
106:d=5 hl=2 l= 2 prim: PRINTABLESTRING :DEThree things in that output are the ones tools get wrong.
The SAN carries all three names including the common name. Browsers have not read the common name since RFC 2818 was superseded, and CA/Browser Forum Baseline Requirements 7.1.4.2.1 requires the extension, so a request without one is refused or quietly rewritten. It travels in the extensionRequest attribute, OID 1.2.840.113549.1.9.14.
The organisation is a UTF8STRING of 28 bytes while the common name beside it is a PRINTABLESTRING. That is not a stylistic choice: X.680 gives PrintableString a fixed alphabet of 74 characters, and "Münchener Straßenbahn GmbH" is not in it. Note the 28 against 26 characters, because ü and ß are two bytes each in UTF-8. Putting those bytes under a PrintableString tag produces a value that violates its own type; writing them as truncated code units instead produces a length that disagrees with the content, and openssl then refuses the file outright with "nested asn1 error". The country stays a PrintableString, which is what RFC 5280 requires of it.
The first line is the one that matters most. -verify checks the signature over the request using only the public key inside it, which is the proof the CA is actually asking for. This request is 363 DER bytes, and the page runs that same check with Web Crypto before it shows you anything, so the tick on screen is a check that ran. The ECDSA signature had to be re-encoded on the way in: Web Crypto returns r and s concatenated at fixed width (IEEE P1363) and X.509 wants a SEQUENCE of two INTEGERs, and when that step is missing openssl says only "error while verifying CSR self-signature" without saying why.
Build a PKCS#10 certificate signing request in your browser, with subject alternative names, a choice of RSA, ECDSA or Ed25519, and correct ASN.1 string types for non-ASCII subject values. The request is signed and then verified in the page before you see it, and the private key never leaves the tab.
A PKCS#10 certification request is a subject, a public key, a set of requested extensions, and a signature made with the matching private key. The signature is the point of the whole thing: it is what proves to the certificate authority that whoever sent the request holds the key. This tool builds the ASN.1 itself and signs it through the Web Crypto API, then verifies its own signature the way a CA will before showing you anything, so the green tick above the output is a check that ran rather than a claim. The equivalent command is openssl req -in yours.csr -noout -text -verify, and the page prints it next to the result so you can run it yourself.
The request always carries a subjectAltName. CA/Browser Forum Baseline Requirements section 7.1.4.2.1 requires it and browsers have ignored the common name since RFC 2818 was superseded, so a request without one is refused or silently rewritten by most CAs. The common name is added to the SAN list automatically, and further names are typed in separated by commas, spaces or newlines. Each is written as the right kind of GeneralName rather than all as DNS entries: a host name becomes dNSName, an IPv4 or IPv6 address becomes iPAddress with the address as four or sixteen octets, an address with an @ becomes rfc822Name, and anything with a scheme becomes uniformResourceIdentifier. The names travel in the extensionRequest attribute, OID 1.2.840.113549.1.9.14, which is where RFC 2985 section 5.4.2 puts requested extensions.
Subject values are written in the correct ASN.1 string type, and the page shows you which type each one got. X.680 gives PrintableString a fixed alphabet of 74 characters; a value outside it has to be a UTF8String, and RFC 5280 section 4.1.2.4 says so for a DirectoryString. Getting this wrong is not cosmetic: writing the bytes of an accented name inside a PrintableString tag produces a value that violates its own type, and writing them as truncated code units produces a length that disagrees with the content, which is a file no reader can load at all. The country attribute is the exception and is always a PrintableString of exactly two characters, checked against the 249 officially assigned ISO 3166-1 alpha-2 codes rather than merely counted, so UK, EU and ZZ are refused where GB, LU and TV are not.
Seven key types are offered: RSA at 2048, 3072 and 4096 bits, ECDSA over P-256, P-384 and P-521, and Ed25519, with a note on each saying who accepts it. Any the browser cannot generate are shown greyed out rather than failing when clicked. Keys come from crypto.subtle.generateKey, so the private key is drawn from the platform's own generator and generation does not block the page: a 4096-bit key is made without the tab stalling. One detail worth knowing about, because it silently breaks requests built by hand: Web Crypto returns an ECDSA signature as IEEE P1363, r and s concatenated at fixed width, while X.509 wants a SEQUENCE of two INTEGERs, and openssl reports the difference only as "error while verifying CSR self-signature". The conversion is done here and the project tests check every key type against openssl req -verify.
The private key is offered as PKCS#8 (BEGIN PRIVATE KEY), which is what modern servers and every language runtime want, and the public key as a SubjectPublicKeyInfo. Before the request is generated the page checks what a CA will object to and says so: a common name over the 64-character limit RFC 5280 sets, an unassigned country code, a value that is not a host name, an organizational unit (prohibited in publicly trusted certificates since September 2022), an email address in the subject, and an IP address a public CA will only issue for if it is publicly verifiable. Errors stop the build; warnings and notes do not, because a private CA has different rules and the tool should not pretend otherwise. When the certificate comes back you can paste it in, and the tool compares its public key against the request's to tell you whether the private key on this page will actually install it. Everything runs locally and nothing is uploaded.
Enter www.example.com as the common name, add example.com and api.example.com to the alternative names, pick a country and generate. The SAN carries all three, the common name included, which is what a CA needs to issue a certificate that covers the bare domain as well as the www host.
Choose ECDSA P-256. The request is signed with ecdsa-with-SHA256 and the key is a fraction of the size of an RSA one at comparable strength. The signature is re-encoded from the raw form Web Crypto returns into the SEQUENCE of two INTEGERs X.509 requires, which is the step that silently breaks hand-built ECDSA requests.
Type an organisation name with an umlaut or in Japanese. The value is written as a UTF8String rather than forced into a PrintableString, the page tells you that is what it did, and openssl reads the name back exactly as typed.
Add every host the certificate must serve. All of them go into the SAN, which is the only place a browser looks.
Generate an ECDSA P-256 request instead of RSA 2048 for a smaller key and a faster handshake, with the request checked against openssl before you send it.
An organisation name with accents, or in Greek, Cyrillic or Japanese, is encoded as a UTF8String so the CA reads it back as typed.
Paste the certificate the CA returned and check its public key against the request, so you find a mismatch before the maintenance window rather than during it.
Yes, on every request, and the common name is added to the list automatically. CA/Browser Forum Baseline Requirements 7.1.4.2.1 requires the extension and browsers ignore the common name entirely, so a request without a SAN is refused or rewritten by most CAs.
RSA at 2048, 3072 and 4096 bits, ECDSA over P-256, P-384 and P-521, and Ed25519. Anything your browser cannot generate is shown greyed out rather than failing when you click it. Public CAs do not yet issue Ed25519 certificates, which the page says next to the option.
The key is generated in your browser by crypto.subtle.generateKey and stays in the tab. Nothing is uploaded. That said, a key that is generated in a browser is only as private as the machine it is generated on.
Yes. Values outside the 74-character PrintableString alphabet are written as UTF8Strings, which is what RFC 5280 section 4.1.2.4 requires, and the page shows you which type each value received. Japanese, Greek, Cyrillic and emoji all round trip through openssl unchanged.
Run openssl req -in yours.csr -noout -text -verify. The -verify flag checks the self-signature, which is the same check the page runs before showing you the result, and -text prints the subject and the SAN list.
Almost always the signature encoding. Web Crypto returns an ECDSA signature as IEEE P1363, r and s concatenated at fixed width, while X.509 requires a SEQUENCE of two INTEGERs. openssl reports only "error while verifying CSR self-signature" and does not say why. This tool converts between the two forms.
PKCS#8, the BEGIN PRIVATE KEY form, which nginx, Apache, Java, Go, Python and Node all read directly. If you need the older PKCS#1 or SEC1 form, convert it with the PEM/DER converter or openssl.
The CA/Browser Forum prohibited the OU attribute in publicly trusted certificates from September 2022, so a public CA will strip or reject it. It is still useful for a private CA, so the tool notes it rather than blocking it.
This runs as client-side JavaScript. Keys, tokens, payloads, and other inputs never leave your device.