|
| 1 | +--- |
| 2 | +sidebar_position: 2 |
| 3 | +sidebar_label: Digital Certificates |
| 4 | +--- |
| 5 | + |
| 6 | +# What is a digital certificate? |
| 7 | + |
| 8 | +A digital certificate, also known as an SSL/TLS certificate or public key certificate, is a digital document that verifies the identity of a website, server, or other digital entity, and allows secure communication between two parties by encrypting data sent over the internet. It contains information about the identity of the certificate holder, such as their name and public key, and is issued by a trusted third-party Certificate Authority (CA). |
| 9 | + |
| 10 | +There are different types of digital certificates that can be generated with various parameters. Certificates can be password-protected, can be bundled with the keys, can rely on different cryptographic algorithms, and eventually expire. Considering these factors, it can be challenging to develop and test web applications that rely on digital certificates. |
| 11 | + |
| 12 | +On this page, you can find guides on creating digital certificate templates with parameters that match your specific needs. |
| 13 | + |
| 14 | +## Generate a key pair for a HTTPS server |
| 15 | + |
| 16 | +In this guide you'll create a template for generating a private key and self-signed certificate for a Node.js HTTPS server: |
| 17 | + |
| 18 | +1. Navigate to [Digital Certificates → Self-signed certificates](https://secutils.dev/ws/certificates__self_signed_certificates) and click **Create certificate template** button |
| 19 | +2. Configure a new certificate template with the following values: |
| 20 | + |
| 21 | +<table class="su-table"> |
| 22 | +<tbody> |
| 23 | +<tr><td><b>Name</b></td><td><pre>https-server</pre></td></tr> |
| 24 | +<tr><td><b>Key algorithm</b></td><td><pre>RSA</pre></td></tr> |
| 25 | +<tr><td><b>Signature algorithm</b></td><td><pre>SHA-256</pre></td></tr> |
| 26 | +<tr><td><b>Certificate type</b></td><td><pre>End Entity</pre></td></tr> |
| 27 | +<tr><td><b>Key usage</b></td><td><pre>Key encipherment, Digital signature</pre></td></tr> |
| 28 | +<tr><td><b>Extended key usage</b></td><td><pre>TLS Web server authentication</pre></td></tr> |
| 29 | +<tr><td><b>Common name (CN)</b></td><td><pre>localhost</pre></td></tr> |
| 30 | +</tbody> |
| 31 | +</table> |
| 32 | + |
| 33 | +3. Click on the **Save** button to save the certificate template |
| 34 | +4. Once the template is set up, it will appear in the templates grid |
| 35 | +5. Click on the template's **Generate** button and use the following values for generation: |
| 36 | + |
| 37 | +<table class="su-table"> |
| 38 | +<tbody> |
| 39 | +<tr><td><b>Format</b></td><td><pre>PKCS#12</pre></td></tr> |
| 40 | +<tr><td><b>Passphrase</b></td><td><pre>pass</pre></td></tr> |
| 41 | +</tbody> |
| 42 | +</table> |
| 43 | + |
| 44 | +6. Click on the **Generate** button to generate and download the certificate bundle |
| 45 | +7. Use the downloaded `https-server.pfx` file to configure Node.js HTTPS server: |
| 46 | + |
| 47 | +```js title="index.js" |
| 48 | +(async function main() { |
| 49 | + const https = await import('node:https'); |
| 50 | + const fs = await import('node:fs'); |
| 51 | + |
| 52 | + const httpsOptions = { |
| 53 | + // highlight-start |
| 54 | + // The name of the certificate bundle and the passphrase that was set in the generation dialog |
| 55 | + pfx: fs.readFileSync('https-server.pfx'), |
| 56 | + passphrase: 'pass' |
| 57 | + // highlight-end |
| 58 | + }; |
| 59 | + |
| 60 | + https.createServer(httpsOptions, (req, res) => { |
| 61 | + res.writeHead(200); |
| 62 | + res.end('Hello World\n'); |
| 63 | + }).listen(8000); |
| 64 | + |
| 65 | + console.log(`Listening on https://localhost:8000`); |
| 66 | +})(); |
| 67 | +``` |
| 68 | + |
| 69 | +8. Run the server with and query it with the **cURL** or similar HTTP client: |
| 70 | + |
| 71 | +```bash title="Example commands" |
| 72 | +// Start server |
| 73 | +$ node index.js |
| 74 | +Listening on https://localhost:8000 |
| 75 | + |
| 76 | +// Query the server with cURL |
| 77 | +$ curl -kv https://localhost:8000 |
| 78 | +* Trying 127.0.0.1:8000... |
| 79 | +... |
| 80 | +* Server certificate: |
| 81 | +* subject: CN=localhost; C=US; ST=California; L=San Francisco; O=CA Issuer, Inc |
| 82 | +* ... |
| 83 | +* issuer: CN=localhost; C=US; ST=California; L=San Francisco; O=CA Issuer, Inc |
| 84 | +* SSL certificate verify result: self-signed certificate (18), continuing anyway. |
| 85 | +... |
| 86 | +> GET / HTTP/1.1 |
| 87 | +> Host: localhost:8000 |
| 88 | +> User-Agent: curl/7.88.1 |
| 89 | +> ... |
| 90 | +< HTTP/1.1 200 OK |
| 91 | +< .... |
| 92 | +< |
| 93 | +Hello World |
| 94 | +``` |
| 95 | + |
| 96 | +Watch the video demo below to see all the steps mentioned earlier in action: |
| 97 | + |
| 98 | +<video controls preload="metadata" width="100%"> |
| 99 | + <source src="../video/guides/certificates_https_server.webm" type="video/webm" /> |
| 100 | + <source src="../video/guides/certificates_https_server.mp4" type="video/mp4" /> |
| 101 | +</video> |
| 102 | + |
| 103 | +## Export a private key as a JSON Web Key (JWK) |
| 104 | + |
| 105 | +In this guide, you will generate a private key in PKCS#8 format and then export it to a JSON Web Key (JWK) using a custom responder and the browser's built-in Web Crypto API: |
| 106 | + |
| 107 | +1. Navigate to [Digital Certificates → Self-signed certificates](https://secutils.dev/ws/certificates__self_signed_certificates) and click **Create certificate template** button |
| 108 | +2. Configure a new certificate template with the following values: |
| 109 | + |
| 110 | +<table class="su-table"> |
| 111 | +<tbody> |
| 112 | +<tr><td><b>Name</b></td><td><pre>jwk</pre></td></tr> |
| 113 | +<tr><td><b>Key algorithm</b></td><td><pre>ECDSA</pre></td></tr> |
| 114 | +<tr><td><b>Signature algorithm</b></td><td><pre>SHA-256</pre></td></tr> |
| 115 | +<tr><td><b>Certificate type</b></td><td><pre>End Entity</pre></td></tr> |
| 116 | +</tbody> |
| 117 | +</table> |
| 118 | + |
| 119 | +3. Click on the **Save** button to save the certificate template |
| 120 | +4. Once the template is set up, it will appear in the templates grid |
| 121 | +5. Now, navigate to [Webhooks → Responders](https://secutils.dev/ws/webhooks__responders) and click **Create responder** button |
| 122 | +6. Configure a new responder with the following values: |
| 123 | + |
| 124 | +<table class="su-table"> |
| 125 | +<tbody> |
| 126 | +<tr><td><b>Name</b></td><td><pre>subtle-crypto</pre></td></tr> |
| 127 | +<tr><td><b>Method</b></td><td><pre>GET</pre></td></tr> |
| 128 | +<tr> |
| 129 | + <td><b>Headers</b></td> |
| 130 | +<td> |
| 131 | + |
| 132 | +```http |
| 133 | +Content-Type: text/html; charset=utf-8 |
| 134 | +``` |
| 135 | +</td> |
| 136 | +</tr> |
| 137 | +<tr> |
| 138 | + <td><b>Body</b></td> |
| 139 | +<td> |
| 140 | + |
| 141 | +```html |
| 142 | +<!DOCTYPE html> |
| 143 | +<html lang="en"> |
| 144 | +<head> |
| 145 | + <title>Subtle Crypto</title> |
| 146 | + <style> |
| 147 | + h1 { text-align: center } |
| 148 | + pre { |
| 149 | + outline: 1px solid #ccc; |
| 150 | + padding: 5px; |
| 151 | + margin: auto; |
| 152 | + width: 30%; |
| 153 | + overflow: hidden; |
| 154 | + text-overflow: ellipsis; |
| 155 | + } |
| 156 | + </style> |
| 157 | + <script type="text/javascript"> |
| 158 | + (async function main() { |
| 159 | + // Call certificate/key pair "Generate" API. |
| 160 | + const response = await fetch("/api/utils/action", { |
| 161 | + method: "POST", |
| 162 | + credentials: "same-origin", |
| 163 | + headers: {"Content-Type": "application/json"}, |
| 164 | + body: JSON.stringify({ |
| 165 | + action: { |
| 166 | + type: "certificates", |
| 167 | + value: { |
| 168 | + type: "generateSelfSignedCertificate", |
| 169 | + value: { templateName: "jwk", format: "pkcs8" } |
| 170 | + } |
| 171 | + } |
| 172 | + }) |
| 173 | + }); |
| 174 | +
|
| 175 | + // Import generated PKCS#8 key as SubtleCrypto's CryptoKey. |
| 176 | + const cryptoKey = await window.crypto.subtle.importKey( |
| 177 | + "pkcs8", |
| 178 | + new Uint8Array((await response.json()).value.value.certificate), |
| 179 | + { name: "ECDSA", namedCurve: "P-384" }, |
| 180 | + true, |
| 181 | + ["sign"] |
| 182 | + ) |
| 183 | +
|
| 184 | + // Export CryptoKey as JWK and render it. |
| 185 | + document.getElementById("jwk").textContent = JSON.stringify( |
| 186 | + await window.crypto.subtle.exportKey('jwk', cryptoKey), |
| 187 | + null, |
| 188 | + 2 |
| 189 | + ); |
| 190 | + })(); |
| 191 | + </script> |
| 192 | +</head> |
| 193 | +<body> |
| 194 | +<h1>PKCS#8 ➡ JSON Web Key (JWK)</h1> |
| 195 | +<pre id="jwk">Loading...</pre> |
| 196 | +</body> |
| 197 | +</html> |
| 198 | +``` |
| 199 | +</td> |
| 200 | +</tr> |
| 201 | +</tbody> |
| 202 | +</table> |
| 203 | + |
| 204 | +7. Click on the **Save** button to save the responder |
| 205 | +8. Once the responder is set up, it will appear in the responders grid along with its unique URL |
| 206 | +9. Click on the responder's URL and observe that it renders a JSON Web Key (JWK) derived from your ECDSA key template |
| 207 | + |
| 208 | +Watch the video demo below to see all the steps mentioned earlier in action: |
| 209 | + |
| 210 | +<video controls preload="metadata" width="100%"> |
| 211 | + <source src="../video/guides/certificates_jwk_export.webm" type="video/webm" /> |
| 212 | + <source src="../video/guides/certificates_jwk_export.mp4" type="video/mp4" /> |
| 213 | +</video> |
0 commit comments