1'use strict'; 2const asn1 = require('asn1.js'); 3const crypto = require('crypto'); 4const fs = require('fs'); 5const rfc5280 = require('asn1.js-rfc5280'); 6const BN = asn1.bignum; 7 8const id_at_commonName = [ 2, 5, 4, 3 ]; 9const rsaEncryption = [1, 2, 840, 113549, 1, 1, 1]; 10const sha256WithRSAEncryption = [1, 2, 840, 113549, 1, 1, 11]; 11const digest = 'SHA256'; 12 13const private_key = fs.readFileSync('./0-dns-key.pem'); 14// public key file can be generated from the private key with 15// openssl rsa -in 0-dns-key.pem -RSAPublicKey_out -outform der 16// -out 0-dns-rsapub.der 17const public_key = fs.readFileSync('./0-dns-rsapub.der'); 18 19const now = Date.now(); 20const days = 3650; 21 22const Null_ = asn1.define('Null_', function() { 23 this.null_(); 24}); 25const null_ = Null_.encode('der'); 26 27const PrintStr = asn1.define('PrintStr', function() { 28 this.printstr(); 29}); 30const issuer = PrintStr.encode('ca.example.com', 'der'); 31const subject = PrintStr.encode('evil.example.com', 'der'); 32 33const tbs = { 34 version: 'v3', 35 serialNumber: new BN('01', 16), 36 signature: { algorithm: sha256WithRSAEncryption, parameters: null_}, 37 issuer: { type: 'rdnSequence', 38 value: [ [{type: id_at_commonName, value: issuer}] ] }, 39 validity: 40 { notBefore: { type: 'utcTime', value: now }, 41 notAfter: { type: 'utcTime', value: now + days * 86400000} }, 42 subject: { type: 'rdnSequence', 43 value: [ [{type: id_at_commonName, value: subject}] ] }, 44 subjectPublicKeyInfo: 45 { algorithm: { algorithm: rsaEncryption, parameters: null_}, 46 subjectPublicKey: { unused: 0, data: public_key} }, 47 extensions: 48 [ { extnID: 'subjectAlternativeName', 49 critical: false, 50 // subjectAltName which contains '\0' character to check CVE-2009-2408 51 extnValue: [ 52 { type: 'dNSName', value: 'good.example.org\u0000.evil.example.com' }, 53 { type: 'dNSName', value: 'just-another.example.com' }, 54 { type: 'iPAddress', value: Buffer.from('08080808', 'hex') }, 55 { type: 'iPAddress', value: Buffer.from('08080404', 'hex') }, 56 { type: 'dNSName', value: 'last.example.com' } ] } 57 ] 58}; 59 60const tbs_der = rfc5280.TBSCertificate.encode(tbs, 'der'); 61 62const sign = crypto.createSign(digest); 63sign.update(tbs_der); 64const signature = sign.sign(private_key); 65 66const cert = { 67 tbsCertificate: tbs, 68 signatureAlgorithm: { algorithm: sha256WithRSAEncryption, parameters: null_ }, 69 signature: 70 { unused: 0, 71 data: signature } 72}; 73const pem = rfc5280.Certificate.encode(cert, 'pem', {label: 'CERTIFICATE'}); 74 75fs.writeFileSync('./0-dns-cert.pem', pem + '\n'); 76