fix(ts_node): Fixed issues in HTTPS certificate generation for TapNodeTools

This commit is contained in:
Philipp Kunz 2024-09-18 17:56:53 +02:00
parent 22ec504b0f
commit 0e80700481
7 changed files with 63 additions and 38 deletions

View File

@ -1,5 +1,11 @@
# Changelog # 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) ## 2024-09-18 - 5.1.3 - fix(ts_node/classes.tapnodetools.ts)
Refactored methods and improved type annotations in TapNodeTools class. Refactored methods and improved type annotations in TapNodeTools class.

View File

@ -26,6 +26,7 @@
"dependencies": { "dependencies": {
"@open-wc/testing": "^4.0.0", "@open-wc/testing": "^4.0.0",
"@push.rocks/consolecolor": "^2.0.2", "@push.rocks/consolecolor": "^2.0.2",
"@push.rocks/smartcrypto": "^2.0.4",
"@push.rocks/smartdelay": "^3.0.5", "@push.rocks/smartdelay": "^3.0.5",
"@push.rocks/smartenv": "^5.0.12", "@push.rocks/smartenv": "^5.0.12",
"@push.rocks/smartexpect": "^1.2.1", "@push.rocks/smartexpect": "^1.2.1",

25
pnpm-lock.yaml generated
View File

@ -14,6 +14,9 @@ importers:
'@push.rocks/consolecolor': '@push.rocks/consolecolor':
specifier: ^2.0.2 specifier: ^2.0.2
version: 2.0.2 version: 2.0.2
'@push.rocks/smartcrypto':
specifier: ^2.0.4
version: 2.0.4
'@push.rocks/smartdelay': '@push.rocks/smartdelay':
specifier: ^3.0.5 specifier: ^3.0.5
version: 3.0.5 version: 3.0.5
@ -361,6 +364,9 @@ packages:
'@push.rocks/smartcli@4.0.11': '@push.rocks/smartcli@4.0.11':
resolution: {integrity: sha512-KDWfUqWBoUZsOEtsDx36d6qc8GG7Zo5E+HHamYY68KVDO8BMu6jbBucoUUPDksczLEmbXKLmroBP1mn/xozQOA==} resolution: {integrity: sha512-KDWfUqWBoUZsOEtsDx36d6qc8GG7Zo5E+HHamYY68KVDO8BMu6jbBucoUUPDksczLEmbXKLmroBP1mn/xozQOA==}
'@push.rocks/smartcrypto@2.0.4':
resolution: {integrity: sha512-1+/5bsjyataf5uUkUNnnVXGRAt+gHVk1KDzozjTqgqJxHvQk1d9fVDohL6CxUhUucTPtu5VR5xNBiV8YCDuGyw==}
'@push.rocks/smartdelay@3.0.5': '@push.rocks/smartdelay@3.0.5':
resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==} resolution: {integrity: sha512-mUuI7kj2f7ztjpic96FvRIlf2RsKBa5arw81AHNsndbxO6asRcxuWL8dTVxouEIK8YsBUlj0AsrCkHhMbLQdHw==}
@ -754,6 +760,9 @@ packages:
'@types/ms@0.7.34': '@types/ms@0.7.34':
resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
'@types/node-forge@1.3.11':
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
'@types/node@22.5.5': '@types/node@22.5.5':
resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==} resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==}
@ -2186,6 +2195,10 @@ packages:
encoding: encoding:
optional: true optional: true
node-forge@1.3.1:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'}
normalize-newline@4.1.0: normalize-newline@4.1.0:
resolution: {integrity: sha512-ff4jKqMI8Xl50/4Mms/9jPobzAV/UK+kXG2XJ/7AqOmxIx8mqfqTIHYxuAnEgJ2AQeBbLnlbmZ5+38Y9A0w/YA==} resolution: {integrity: sha512-ff4jKqMI8Xl50/4Mms/9jPobzAV/UK+kXG2XJ/7AqOmxIx8mqfqTIHYxuAnEgJ2AQeBbLnlbmZ5+38Y9A0w/YA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -3449,6 +3462,12 @@ snapshots:
'@push.rocks/smartrx': 3.0.7 '@push.rocks/smartrx': 3.0.7
yargs-parser: 21.1.1 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': '@push.rocks/smartdelay@3.0.5':
dependencies: dependencies:
'@push.rocks/smartpromise': 4.0.4 '@push.rocks/smartpromise': 4.0.4
@ -4124,6 +4143,10 @@ snapshots:
'@types/ms@0.7.34': {} '@types/ms@0.7.34': {}
'@types/node-forge@1.3.11':
dependencies:
'@types/node': 22.5.5
'@types/node@22.5.5': '@types/node@22.5.5':
dependencies: dependencies:
undici-types: 6.19.8 undici-types: 6.19.8
@ -5868,6 +5891,8 @@ snapshots:
dependencies: dependencies:
whatwg-url: 5.0.0 whatwg-url: 5.0.0
node-forge@1.3.1: {}
normalize-newline@4.1.0: normalize-newline@4.1.0:
dependencies: dependencies:
replace-buffer: 1.2.1 replace-buffer: 1.2.1

View File

@ -11,7 +11,7 @@ tap.test('should create a https cert', async () => {
const { key, cert } = await tapNodeTools.createHttpsCert('localhost'); const { key, cert } = await tapNodeTools.createHttpsCert('localhost');
console.log(key); console.log(key);
console.log(cert); console.log(cert);
expect(key).toInclude('-----BEGIN PRIVATE KEY-----'); expect(key).toInclude('-----BEGIN RSA PRIVATE KEY-----');
expect(cert).toInclude('-----BEGIN CERTIFICATE-----'); expect(cert).toInclude('-----BEGIN CERTIFICATE-----');
}); });

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/tapbundle', 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.' description: 'A test automation library bundling utilities and tools for TAP (Test Anything Protocol) based testing, specifically tailored for tapbuffer.'
} }

View File

@ -1,5 +1,4 @@
import * as plugins from './plugins.js'; import * as plugins from './plugins.js';
import { createSign } from 'crypto';
class TapNodeTools { class TapNodeTools {
private smartshellInstance: plugins.smartshell.Smartshell; private smartshellInstance: plugins.smartshell.Smartshell;
@ -19,47 +18,40 @@ class TapNodeTools {
public async createHttpsCert( public async createHttpsCert(
commonName: string = 'localhost' commonName: string = 'localhost'
): Promise<{ key: string; cert: string }> { ): Promise<{ key: string; cert: string }> {
// Generate RSA key pair // Generate a key pair
const { publicKey, privateKey } = plugins.crypto.generateKeyPairSync('rsa', { const keys = plugins.smartcrypto.nodeForge.pki.rsa.generateKeyPair(2048);
modulusLength: 2048,
publicExponent: 65537,
});
// Create a self-signed certificate // 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 attrs = [
const keyContent = privateKey.export({ { name: 'commonName', value: commonName },
type: 'pkcs8', { name: 'countryName', value: 'US' },
format: 'pem', { 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 { return {
key: keyContent as string, key: pemKey,
cert: cert, 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(); export const tapNodeTools = new TapNodeTools();

View File

@ -5,6 +5,7 @@ import * as fs from 'fs';
export { crypto,fs }; export { crypto,fs };
// @push.rocks scope // @push.rocks scope
import * as smartcrypto from '@push.rocks/smartcrypto';
import * as smartshell from '@push.rocks/smartshell'; import * as smartshell from '@push.rocks/smartshell';
export { smartshell }; export { smartcrypto, smartshell };