(attrs, options)
| 294 | * @returns {Promise<Certificate | null>} |
| 295 | */ |
| 296 | export async function generateWebTransportCertificate(attrs, options) { |
| 297 | try { |
| 298 | const keyPair = await crypto.subtle.generateKey( |
| 299 | { |
| 300 | name: 'ECDSA', |
| 301 | namedCurve: 'P-256' |
| 302 | }, |
| 303 | true, |
| 304 | ['sign', 'verify'] |
| 305 | ) |
| 306 | |
| 307 | const cert = pki.createCertificate() |
| 308 | |
| 309 | cert.serialNumber = toPositiveHex( |
| 310 | forge.util.bytesToHex(forge.random.getBytesSync(9)) |
| 311 | ) // the serial number can be decimal or hex (if preceded by 0x) |
| 312 | cert.validity.notBefore = new Date() |
| 313 | cert.validity.notAfter = new Date() |
| 314 | cert.validity.notAfter.setDate( |
| 315 | cert.validity.notBefore.getDate() + (options.days || 14) |
| 316 | ) // per spec only 14 days allowed |
| 317 | |
| 318 | cert.setSubject(attrs) |
| 319 | cert.setIssuer(attrs) |
| 320 | |
| 321 | const privateKey = crypto.subtle.exportKey('pkcs8', keyPair.privateKey) |
| 322 | const publicKey = (cert.publicKey = await crypto.subtle.exportKey( |
| 323 | 'spki', |
| 324 | keyPair.publicKey |
| 325 | )) |
| 326 | |
| 327 | cert.setExtensions( |
| 328 | options.extensions || [ |
| 329 | { |
| 330 | name: 'basicConstraints', |
| 331 | cA: true |
| 332 | }, |
| 333 | { |
| 334 | name: 'keyUsage', |
| 335 | keyCertSign: true, |
| 336 | digitalSignature: true, |
| 337 | nonRepudiation: true, |
| 338 | keyEncipherment: true, |
| 339 | dataEncipherment: true |
| 340 | }, |
| 341 | { |
| 342 | name: 'subjectAltName', |
| 343 | altNames: [ |
| 344 | { |
| 345 | type: 6, // URI |
| 346 | value: 'http://example.org/webid#me' |
| 347 | } |
| 348 | ] |
| 349 | } |
| 350 | ] |
| 351 | ) |
| 352 | |
| 353 | // to signing |
no test coverage detected