From 0e807004815cb6243357926b2ba00b065e4d49c6 Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Wed, 18 Sep 2024 17:56:53 +0200 Subject: [PATCH] fix(ts_node): Fixed issues in HTTPS certificate generation for TapNodeTools --- changelog.md | 6 ++++ package.json | 1 + pnpm-lock.yaml | 25 +++++++++++++ test/test.node.ts | 2 +- ts/00_commitinfo_data.ts | 2 +- ts_node/classes.tapnodetools.ts | 62 ++++++++++++++------------------- ts_node/plugins.ts | 3 +- 7 files changed, 63 insertions(+), 38 deletions(-) diff --git a/changelog.md b/changelog.md index 42eff00..dfff62e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # Changelog +## 2024-09-18 - 5.1.4 - fix(ts_node) +Fixed issues in HTTPS certificate generation for TapNodeTools + +- Updated 'createHttpsCert' method in 'TapNodeTools' to use 'smartcrypto' for generating RSA key pair and self-signed certificate. +- Corrected certificate and private key PEM encoding. + ## 2024-09-18 - 5.1.3 - fix(ts_node/classes.tapnodetools.ts) Refactored methods and improved type annotations in TapNodeTools class. diff --git a/package.json b/package.json index f582e1b..b22a98f 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "dependencies": { "@open-wc/testing": "^4.0.0", "@push.rocks/consolecolor": "^2.0.2", + "@push.rocks/smartcrypto": "^2.0.4", "@push.rocks/smartdelay": "^3.0.5", "@push.rocks/smartenv": "^5.0.12", "@push.rocks/smartexpect": "^1.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a91dc92..b493d8a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@push.rocks/consolecolor': specifier: ^2.0.2 version: 2.0.2 + '@push.rocks/smartcrypto': + specifier: ^2.0.4 + version: 2.0.4 '@push.rocks/smartdelay': specifier: ^3.0.5 version: 3.0.5 @@ -361,6 +364,9 @@ packages: '@push.rocks/smartcli@4.0.11': resolution: {integrity: sha512-KDWfUqWBoUZsOEtsDx36d6qc8GG7Zo5E+HHamYY68KVDO8BMu6jbBucoUUPDksczLEmbXKLmroBP1mn/xozQOA==} + '@push.rocks/smartcrypto@2.0.4': + resolution: {integrity: sha512-1+/5bsjyataf5uUkUNnnVXGRAt+gHVk1KDzozjTqgqJxHvQk1d9fVDohL6CxUhUucTPtu5VR5xNBiV8YCDuGyw==} + '@push.rocks/smartdelay@3.0.5': resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==} @@ -754,6 +760,9 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + '@types/node-forge@1.3.11': + resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} + '@types/node@22.5.5': resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==} @@ -2186,6 +2195,10 @@ packages: encoding: optional: true + node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + normalize-newline@4.1.0: resolution: {integrity: sha512-ff4jKqMI8Xl50/4Mms/9jPobzAV/UK+kXG2XJ/7AqOmxIx8mqfqTIHYxuAnEgJ2AQeBbLnlbmZ5+38Y9A0w/YA==} engines: {node: '>=12'} @@ -3449,6 +3462,12 @@ snapshots: '@push.rocks/smartrx': 3.0.7 yargs-parser: 21.1.1 + '@push.rocks/smartcrypto@2.0.4': + dependencies: + '@push.rocks/smartpromise': 4.0.4 + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + '@push.rocks/smartdelay@3.0.5': dependencies: '@push.rocks/smartpromise': 4.0.4 @@ -4124,6 +4143,10 @@ snapshots: '@types/ms@0.7.34': {} + '@types/node-forge@1.3.11': + dependencies: + '@types/node': 22.5.5 + '@types/node@22.5.5': dependencies: undici-types: 6.19.8 @@ -5868,6 +5891,8 @@ snapshots: dependencies: whatwg-url: 5.0.0 + node-forge@1.3.1: {} + normalize-newline@4.1.0: dependencies: replace-buffer: 1.2.1 diff --git a/test/test.node.ts b/test/test.node.ts index bf9ce55..94a7559 100644 --- a/test/test.node.ts +++ b/test/test.node.ts @@ -11,7 +11,7 @@ tap.test('should create a https cert', async () => { const { key, cert } = await tapNodeTools.createHttpsCert('localhost'); console.log(key); console.log(cert); - expect(key).toInclude('-----BEGIN PRIVATE KEY-----'); + expect(key).toInclude('-----BEGIN RSA PRIVATE KEY-----'); expect(cert).toInclude('-----BEGIN CERTIFICATE-----'); }); diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index a882690..709a6b5 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@push.rocks/tapbundle', - version: '5.1.3', + version: '5.1.4', description: 'A test automation library bundling utilities and tools for TAP (Test Anything Protocol) based testing, specifically tailored for tapbuffer.' } diff --git a/ts_node/classes.tapnodetools.ts b/ts_node/classes.tapnodetools.ts index 33315ee..c9003fb 100644 --- a/ts_node/classes.tapnodetools.ts +++ b/ts_node/classes.tapnodetools.ts @@ -1,5 +1,4 @@ import * as plugins from './plugins.js'; -import { createSign } from 'crypto'; class TapNodeTools { private smartshellInstance: plugins.smartshell.Smartshell; @@ -19,47 +18,40 @@ class TapNodeTools { public async createHttpsCert( commonName: string = 'localhost' ): Promise<{ key: string; cert: string }> { - // Generate RSA key pair - const { publicKey, privateKey } = plugins.crypto.generateKeyPairSync('rsa', { - modulusLength: 2048, - publicExponent: 65537, - }); + // Generate a key pair + const keys = plugins.smartcrypto.nodeForge.pki.rsa.generateKeyPair(2048); // Create a self-signed certificate - const cert = this.generateSelfSignedCert(publicKey, privateKey, commonName); + const cert = plugins.smartcrypto.nodeForge.pki.createCertificate(); + cert.publicKey = keys.publicKey; + cert.serialNumber = '01'; + cert.validity.notBefore = new Date(); + cert.validity.notAfter = new Date(); + cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); - // Export the private key and return the cert and key - const keyContent = privateKey.export({ - type: 'pkcs8', - format: 'pem', - }); + const attrs = [ + { name: 'commonName', value: commonName }, + { name: 'countryName', value: 'US' }, + { shortName: 'ST', value: 'California' }, + { name: 'localityName', value: 'San Francisco' }, + { name: 'organizationName', value: 'My Company' }, + { shortName: 'OU', value: 'Dev' }, + ]; + cert.setSubject(attrs); + cert.setIssuer(attrs); + + // Sign the certificate with its own private key (self-signed) + cert.sign(keys.privateKey, plugins.smartcrypto.nodeForge.md.sha256.create()); + + // PEM encode the private key and certificate + const pemKey = plugins.smartcrypto.nodeForge.pki.privateKeyToPem(keys.privateKey); + const pemCert = plugins.smartcrypto.nodeForge.pki.certificateToPem(cert); return { - key: keyContent as string, - cert: cert, + key: pemKey, + cert: pemCert, }; } - - private generateSelfSignedCert(publicKey, privateKey, commonName: string): string { - const sign = createSign('SHA256'); - const certData = { - subject: `/CN=${commonName}`, - publicKey: publicKey.export({ type: 'spki', format: 'pem' }), - }; - - sign.update(JSON.stringify(certData)); - sign.end(); - - const signature = sign.sign(privateKey, 'base64'); - - return ( - '-----BEGIN CERTIFICATE-----\n' + - Buffer.from(certData.publicKey).toString('base64') + - '\n' + - signature + - '\n-----END CERTIFICATE-----\n' - ); - } } export const tapNodeTools = new TapNodeTools(); diff --git a/ts_node/plugins.ts b/ts_node/plugins.ts index dcdc188..3cc9e4c 100644 --- a/ts_node/plugins.ts +++ b/ts_node/plugins.ts @@ -5,6 +5,7 @@ import * as fs from 'fs'; export { crypto,fs }; // @push.rocks scope +import * as smartcrypto from '@push.rocks/smartcrypto'; import * as smartshell from '@push.rocks/smartshell'; -export { smartshell }; +export { smartcrypto, smartshell };