@gjsify/crypto 0.3.12 → 0.3.14
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.
- package/lib/esm/asn1.js +576 -450
- package/lib/esm/bigint-math.js +37 -28
- package/lib/esm/cipher.js +1252 -1229
- package/lib/esm/constants.js +12 -13
- package/lib/esm/crypto-utils.js +54 -36
- package/lib/esm/dh.js +408 -368
- package/lib/esm/ecdh.js +403 -321
- package/lib/esm/ecdsa.js +138 -111
- package/lib/esm/hash.js +100 -89
- package/lib/esm/hkdf.js +65 -47
- package/lib/esm/hmac.js +95 -90
- package/lib/esm/index.js +75 -148
- package/lib/esm/key-object.js +348 -307
- package/lib/esm/mgf1.js +30 -24
- package/lib/esm/pbkdf2.js +66 -59
- package/lib/esm/public-encrypt.js +203 -156
- package/lib/esm/random.js +137 -124
- package/lib/esm/rsa-oaep.js +94 -87
- package/lib/esm/rsa-pss.js +95 -88
- package/lib/esm/scrypt.js +116 -115
- package/lib/esm/sign.js +267 -237
- package/lib/esm/timing-safe-equal.js +16 -11
- package/lib/esm/x509.js +215 -206
- package/package.json +7 -7
package/lib/esm/x509.js
CHANGED
|
@@ -1,214 +1,223 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { parseX509, parseX509Der, encodeSubjectPublicKeyInfo, derToPem } from "./asn1.js";
|
|
1
|
+
import { derToPem, encodeSubjectPublicKeyInfo, parseX509, parseX509Der } from "./asn1.js";
|
|
3
2
|
import { KeyObject } from "./key-object.js";
|
|
4
3
|
import { createHash } from "./index.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
4
|
+
import { Buffer } from "node:buffer";
|
|
5
|
+
|
|
6
|
+
//#region src/x509.ts
|
|
7
|
+
/**
|
|
8
|
+
* X509Certificate encapsulates an X.509 certificate and provides
|
|
9
|
+
* read-only access to its information.
|
|
10
|
+
*/
|
|
11
|
+
var X509Certificate = class {
|
|
12
|
+
_components;
|
|
13
|
+
_pem;
|
|
14
|
+
constructor(buf) {
|
|
15
|
+
if (typeof buf === "string") {
|
|
16
|
+
this._pem = buf;
|
|
17
|
+
this._components = parseX509(buf);
|
|
18
|
+
} else {
|
|
19
|
+
const bufData = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);
|
|
20
|
+
const str = bufData.toString("utf8");
|
|
21
|
+
if (str.includes("-----BEGIN CERTIFICATE-----")) {
|
|
22
|
+
this._pem = str;
|
|
23
|
+
this._components = parseX509(str);
|
|
24
|
+
} else {
|
|
25
|
+
this._components = parseX509Der(new Uint8Array(bufData.buffer, bufData.byteOffset, bufData.byteLength));
|
|
26
|
+
this._pem = derToPem(this._components.raw, "CERTIFICATE");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** The DER encoded certificate data. */
|
|
31
|
+
get raw() {
|
|
32
|
+
return Buffer.from(this._components.raw);
|
|
33
|
+
}
|
|
34
|
+
/** The serial number of the certificate as a hex string. */
|
|
35
|
+
get serialNumber() {
|
|
36
|
+
return this._components.serialNumber.toString(16).toUpperCase();
|
|
37
|
+
}
|
|
38
|
+
/** The subject of the certificate. */
|
|
39
|
+
get subject() {
|
|
40
|
+
return this._components.subject;
|
|
41
|
+
}
|
|
42
|
+
/** The issuer of the certificate. */
|
|
43
|
+
get issuer() {
|
|
44
|
+
return this._components.issuer;
|
|
45
|
+
}
|
|
46
|
+
/** The start date of the certificate validity period. */
|
|
47
|
+
get validFrom() {
|
|
48
|
+
return this._components.validFrom.toUTCString();
|
|
49
|
+
}
|
|
50
|
+
/** The end date of the certificate validity period. */
|
|
51
|
+
get validTo() {
|
|
52
|
+
return this._components.validTo.toUTCString();
|
|
53
|
+
}
|
|
54
|
+
/** SHA-1 fingerprint of the certificate. */
|
|
55
|
+
get fingerprint() {
|
|
56
|
+
const hash = createHash("sha1").update(this._components.raw).digest();
|
|
57
|
+
return formatFingerprint(hash);
|
|
58
|
+
}
|
|
59
|
+
/** SHA-256 fingerprint of the certificate. */
|
|
60
|
+
get fingerprint256() {
|
|
61
|
+
const hash = createHash("sha256").update(this._components.raw).digest();
|
|
62
|
+
return formatFingerprint(hash);
|
|
63
|
+
}
|
|
64
|
+
/** SHA-512 fingerprint of the certificate. */
|
|
65
|
+
get fingerprint512() {
|
|
66
|
+
const hash = createHash("sha512").update(this._components.raw).digest();
|
|
67
|
+
return formatFingerprint(hash);
|
|
68
|
+
}
|
|
69
|
+
/** The public key of the certificate as a KeyObject. */
|
|
70
|
+
get publicKey() {
|
|
71
|
+
if (!this._components.publicKey) {
|
|
72
|
+
throw new Error("Certificate does not contain a supported public key type");
|
|
73
|
+
}
|
|
74
|
+
const der = encodeSubjectPublicKeyInfo(this._components.publicKey);
|
|
75
|
+
const pem = derToPem(der, "PUBLIC KEY");
|
|
76
|
+
return new KeyObject("public", {
|
|
77
|
+
parsed: {
|
|
78
|
+
type: "rsa-public",
|
|
79
|
+
components: this._components.publicKey
|
|
80
|
+
},
|
|
81
|
+
pem
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/** The Subject Alternative Name extension, if present. */
|
|
85
|
+
get subjectAltName() {
|
|
86
|
+
if (!this._components.subjectAltName || this._components.subjectAltName.length === 0) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
return this._components.subjectAltName.join(", ");
|
|
90
|
+
}
|
|
91
|
+
/** The key usage extension (stub — returns undefined). */
|
|
92
|
+
get keyUsage() {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
/** Information access extension (stub — returns undefined). */
|
|
96
|
+
get infoAccess() {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
/** Whether this certificate is a CA certificate. */
|
|
100
|
+
get ca() {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Check whether the certificate matches the given hostname.
|
|
105
|
+
*/
|
|
106
|
+
checkHost(name) {
|
|
107
|
+
const cnMatch = this._components.subject.match(/CN=([^,]+)/);
|
|
108
|
+
if (cnMatch) {
|
|
109
|
+
const cn = cnMatch[1].trim();
|
|
110
|
+
if (matchHostname(cn, name)) return cn;
|
|
111
|
+
}
|
|
112
|
+
if (this._components.subjectAltName) {
|
|
113
|
+
for (const san of this._components.subjectAltName) {
|
|
114
|
+
if (san.startsWith("DNS:")) {
|
|
115
|
+
const dnsName = san.substring(4);
|
|
116
|
+
if (matchHostname(dnsName, name)) return dnsName;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check whether the certificate matches the given email address.
|
|
124
|
+
*/
|
|
125
|
+
checkEmail(email) {
|
|
126
|
+
const emailLower = email.toLowerCase();
|
|
127
|
+
const emailMatch = this._components.subject.match(/emailAddress=([^,]+)/);
|
|
128
|
+
if (emailMatch && emailMatch[1].toLowerCase() === emailLower) {
|
|
129
|
+
return emailMatch[1];
|
|
130
|
+
}
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check whether the certificate matches the given IP address.
|
|
135
|
+
*/
|
|
136
|
+
checkIP(ip) {
|
|
137
|
+
if (this._components.subjectAltName) {
|
|
138
|
+
for (const san of this._components.subjectAltName) {
|
|
139
|
+
if (san.startsWith("IP Address:") && san.substring(11) === ip) {
|
|
140
|
+
return ip;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Verify the certificate signature using the given public key.
|
|
148
|
+
*/
|
|
149
|
+
verify(_publicKey) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check whether this certificate was issued by the given issuer certificate.
|
|
154
|
+
*/
|
|
155
|
+
checkIssued(otherCert) {
|
|
156
|
+
return this.issuer === otherCert.subject;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Returns a legacy certificate object for compatibility.
|
|
160
|
+
*/
|
|
161
|
+
toLegacyObject() {
|
|
162
|
+
return {
|
|
163
|
+
subject: parseDNToObject(this._components.subject),
|
|
164
|
+
issuer: parseDNToObject(this._components.issuer),
|
|
165
|
+
valid_from: this.validFrom,
|
|
166
|
+
valid_to: this.validTo,
|
|
167
|
+
serialNumber: this.serialNumber,
|
|
168
|
+
fingerprint: this.fingerprint,
|
|
169
|
+
fingerprint256: this.fingerprint256
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Returns the PEM-encoded certificate.
|
|
174
|
+
*/
|
|
175
|
+
toString() {
|
|
176
|
+
return this._pem;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Returns the PEM-encoded certificate in JSON context.
|
|
180
|
+
*/
|
|
181
|
+
toJSON() {
|
|
182
|
+
return this._pem;
|
|
183
|
+
}
|
|
184
|
+
get [Symbol.toStringTag]() {
|
|
185
|
+
return "X509Certificate";
|
|
186
|
+
}
|
|
187
|
+
};
|
|
179
188
|
function formatFingerprint(hash) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
189
|
+
const hex = hash.toString("hex").toUpperCase();
|
|
190
|
+
const parts = [];
|
|
191
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
192
|
+
parts.push(hex.substring(i, i + 2));
|
|
193
|
+
}
|
|
194
|
+
return parts.join(":");
|
|
186
195
|
}
|
|
187
196
|
function matchHostname(pattern, hostname) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
const patternLower = pattern.toLowerCase();
|
|
198
|
+
const hostLower = hostname.toLowerCase();
|
|
199
|
+
if (patternLower === hostLower) return true;
|
|
200
|
+
if (patternLower.startsWith("*.")) {
|
|
201
|
+
const suffix = patternLower.substring(2);
|
|
202
|
+
const hostParts = hostLower.split(".");
|
|
203
|
+
if (hostParts.length >= 2) {
|
|
204
|
+
const hostSuffix = hostParts.slice(1).join(".");
|
|
205
|
+
return hostSuffix === suffix;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return false;
|
|
200
209
|
}
|
|
201
210
|
function parseDNToObject(dn) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
+
const result = {};
|
|
212
|
+
const parts = dn.split(", ");
|
|
213
|
+
for (const part of parts) {
|
|
214
|
+
const eqIdx = part.indexOf("=");
|
|
215
|
+
if (eqIdx > 0) {
|
|
216
|
+
result[part.substring(0, eqIdx)] = part.substring(eqIdx + 1);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return result;
|
|
211
220
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
};
|
|
221
|
+
|
|
222
|
+
//#endregion
|
|
223
|
+
export { X509Certificate };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/crypto",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.14",
|
|
4
4
|
"description": "Node.js crypto module for Gjs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -30,16 +30,16 @@
|
|
|
30
30
|
"crypto"
|
|
31
31
|
],
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@gjsify/cli": "^0.3.
|
|
34
|
-
"@gjsify/unit": "^0.3.
|
|
33
|
+
"@gjsify/cli": "^0.3.14",
|
|
34
|
+
"@gjsify/unit": "^0.3.14",
|
|
35
35
|
"@types/diffie-hellman": "^5.0.3",
|
|
36
36
|
"@types/node": "^25.6.0",
|
|
37
37
|
"typescript": "^6.0.3"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@girs/glib-2.0": "
|
|
41
|
-
"@gjsify/buffer": "^0.3.
|
|
42
|
-
"@gjsify/stream": "^0.3.
|
|
43
|
-
"@gjsify/utils": "^0.3.
|
|
40
|
+
"@girs/glib-2.0": "2.88.0-4.0.0-rc.9",
|
|
41
|
+
"@gjsify/buffer": "^0.3.14",
|
|
42
|
+
"@gjsify/stream": "^0.3.14",
|
|
43
|
+
"@gjsify/utils": "^0.3.14"
|
|
44
44
|
}
|
|
45
45
|
}
|