@andrewheberle/serverless-ssh-ca 0.21.0 → 0.23.0
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/README.md +55 -1
- package/dist/api/operations.d.ts +49 -0
- package/dist/api/operations.d.ts.map +1 -0
- package/dist/api/operations.js +175 -0
- package/dist/api/operations.js.map +1 -0
- package/dist/api/schema.d.ts +71 -0
- package/dist/api/schema.d.ts.map +1 -0
- package/dist/api/schema.js +107 -0
- package/dist/api/schema.js.map +1 -0
- package/dist/api/v3/index.d.ts.map +1 -1
- package/dist/api/v3/index.js +25 -212
- package/dist/api/v3/index.js.map +1 -1
- package/dist/api/v3/schema.d.ts +30 -74
- package/dist/api/v3/schema.d.ts.map +1 -1
- package/dist/api/v3/schema.js +18 -73
- package/dist/api/v3/schema.js.map +1 -1
- package/dist/api/v4/index.d.ts +8 -0
- package/dist/api/v4/index.d.ts.map +1 -0
- package/dist/api/v4/index.js +155 -0
- package/dist/api/v4/index.js.map +1 -0
- package/dist/api/v4/schema.d.ts +268 -0
- package/dist/api/v4/schema.d.ts.map +1 -0
- package/dist/api/v4/schema.js +182 -0
- package/dist/api/v4/schema.js.map +1 -0
- package/dist/certificate.d.ts +9 -6
- package/dist/certificate.d.ts.map +1 -1
- package/dist/certificate.js +55 -99
- package/dist/certificate.js.map +1 -1
- package/dist/db/index.d.ts +32 -24
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +101 -28
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations/0002_krl_version.d.ts +3 -0
- package/dist/db/migrations/0002_krl_version.d.ts.map +1 -0
- package/dist/db/migrations/0002_krl_version.js +15 -0
- package/dist/db/migrations/0002_krl_version.js.map +1 -0
- package/dist/db/migrations/index.d.ts.map +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/index.js.map +1 -1
- package/dist/db/types.d.ts +37 -0
- package/dist/db/types.d.ts.map +1 -0
- package/dist/db/types.js +13 -0
- package/dist/db/types.js.map +1 -0
- package/dist/krl.d.ts +9 -1
- package/dist/krl.d.ts.map +1 -1
- package/dist/krl.js +22 -162
- package/dist/krl.js.map +1 -1
- package/dist/proof.d.ts +36 -7
- package/dist/proof.d.ts.map +1 -1
- package/dist/proof.js +53 -21
- package/dist/proof.js.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +3 -1
- package/dist/router.js.map +1 -1
- package/dist/ssh/certificate.d.ts +93 -0
- package/dist/ssh/certificate.d.ts.map +1 -0
- package/dist/ssh/certificate.js +178 -0
- package/dist/ssh/certificate.js.map +1 -0
- package/dist/ssh/encoding.d.ts +41 -0
- package/dist/ssh/encoding.d.ts.map +1 -0
- package/dist/ssh/encoding.js +70 -0
- package/dist/ssh/encoding.js.map +1 -0
- package/dist/ssh/keys.d.ts +80 -0
- package/dist/ssh/keys.d.ts.map +1 -0
- package/dist/ssh/keys.js +249 -0
- package/dist/ssh/keys.js.map +1 -0
- package/dist/ssh/signer.d.ts +35 -0
- package/dist/ssh/signer.d.ts.map +1 -0
- package/dist/ssh/signer.js +99 -0
- package/dist/ssh/signer.js.map +1 -0
- package/dist/types.d.ts +12 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +40 -21
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +87 -54
- package/dist/utils.js.map +1 -1
- package/openapi.json +1960 -82
- package/package.json +5 -17
- package/src/api/operations.ts +211 -0
- package/src/api/schema.ts +137 -0
- package/src/api/v3/index.ts +32 -259
- package/src/api/v3/schema.ts +34 -96
- package/src/api/v4/index.ts +265 -0
- package/src/api/v4/schema.ts +235 -0
- package/src/certificate.ts +62 -123
- package/src/db/index.ts +113 -49
- package/src/db/migrations/0002_krl_version.ts +16 -0
- package/src/db/migrations/index.ts +3 -1
- package/src/db/types.ts +40 -0
- package/src/krl.ts +32 -194
- package/src/proof.ts +65 -31
- package/src/router.ts +3 -1
- package/src/ssh/certificate.ts +236 -0
- package/src/ssh/encoding.ts +81 -0
- package/src/ssh/keys.ts +294 -0
- package/src/ssh/signer.ts +129 -0
- package/src/types.ts +12 -18
- package/src/utils.ts +99 -69
package/dist/db/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
+
import { PublicKey } from "../ssh/keys.js";
|
|
1
2
|
import { logger } from "../logger.js";
|
|
2
3
|
import { D1QB } from "workers-qb";
|
|
4
|
+
import { z } from "zod";
|
|
3
5
|
import { migrateOnce } from "./migrate.js";
|
|
4
6
|
import { migrations } from "./migrations/index.js";
|
|
5
|
-
|
|
6
|
-
(function (CertificateType) {
|
|
7
|
-
CertificateType[CertificateType["User"] = 0] = "User";
|
|
8
|
-
CertificateType[CertificateType["Host"] = 1] = "Host";
|
|
9
|
-
})(CertificateType || (CertificateType = {}));
|
|
7
|
+
import { CertificateType } from "./types.js";
|
|
10
8
|
const connect = async (env) => {
|
|
11
9
|
const l = logger(env);
|
|
12
10
|
try {
|
|
@@ -43,26 +41,21 @@ export const dbCleanup = async (env) => {
|
|
|
43
41
|
}
|
|
44
42
|
};
|
|
45
43
|
export const recordCertificate = async (env, certificate, keyid, certificateType = CertificateType.User) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}).join(",");
|
|
50
|
-
const extensions = certificate.getExtensions().map((v) => {
|
|
51
|
-
// @ts-expect-error: the name property does exist
|
|
52
|
-
return v.name;
|
|
53
|
-
}).join(",");
|
|
44
|
+
// principals are recorded as distinguished names, as they were when
|
|
45
|
+
// certificates were created with sshpk
|
|
46
|
+
const principals = certificate.principals.map((p) => `${certificate.kind === "host" ? "CN" : "UID"}=${p}`).join(",");
|
|
54
47
|
const qb = await connect(env);
|
|
55
48
|
const res = await qb.insert({
|
|
56
49
|
tableName: "certificates",
|
|
57
50
|
data: {
|
|
58
|
-
serial: `${serial}`,
|
|
51
|
+
serial: `${certificate.serial}`,
|
|
59
52
|
key_id: keyid,
|
|
60
|
-
principals:
|
|
61
|
-
extensions: extensions,
|
|
62
|
-
valid_after: certificate.
|
|
63
|
-
valid_before: certificate.
|
|
53
|
+
principals: principals,
|
|
54
|
+
extensions: certificate.extensions.join(","),
|
|
55
|
+
valid_after: certificate.validAfter.toISOString(),
|
|
56
|
+
valid_before: certificate.validBefore.toISOString(),
|
|
64
57
|
certificate_type: certificateType,
|
|
65
|
-
public_key: certificate.
|
|
58
|
+
public_key: certificate.publicKey.toString()
|
|
66
59
|
},
|
|
67
60
|
}).execute();
|
|
68
61
|
if (!res.success) {
|
|
@@ -86,31 +79,53 @@ export var RevocationStatus;
|
|
|
86
79
|
RevocationStatus[RevocationStatus["NotFound"] = 0] = "NotFound";
|
|
87
80
|
RevocationStatus[RevocationStatus["Revoked"] = 1] = "Revoked";
|
|
88
81
|
RevocationStatus[RevocationStatus["Revokable"] = 2] = "Revokable";
|
|
89
|
-
RevocationStatus[RevocationStatus["Unrevokable"] = 3] = "Unrevokable";
|
|
90
82
|
})(RevocationStatus || (RevocationStatus = {}));
|
|
91
|
-
|
|
83
|
+
// whether a public key recorded in OpenSSH format is the same as another key,
|
|
84
|
+
// treating a recorded key that cannot be parsed as a different key
|
|
85
|
+
const isKey = (recorded, publicKey) => {
|
|
86
|
+
try {
|
|
87
|
+
return PublicKey.parse(recorded).equals(publicKey);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Returns whether a certificate can be revoked by the holder of a public key.
|
|
95
|
+
*
|
|
96
|
+
* The public key is compared by fingerprint, so a key with a different
|
|
97
|
+
* comment to the one the certificate was issued for still matches.
|
|
98
|
+
*
|
|
99
|
+
* @param env The CA bindings
|
|
100
|
+
* @param serial The serial of the certificate
|
|
101
|
+
* @param publicKey The public key the requester has proven possession of
|
|
102
|
+
* @param certificateType The type of certificate
|
|
103
|
+
* @returns The revocation status of the certificate
|
|
104
|
+
*/
|
|
105
|
+
export const revocationStatus = async (env, serial, publicKey, certificateType) => {
|
|
92
106
|
const qb = await connect(env);
|
|
93
107
|
const res = await qb.fetchOne({
|
|
94
108
|
tableName: "certificates",
|
|
95
109
|
fields: ["public_key", "revoked_at"],
|
|
96
110
|
where: {
|
|
97
|
-
conditions: "serial = ? AND
|
|
98
|
-
params: [`${serial}`,
|
|
111
|
+
conditions: "serial = ? AND certificate_type = ?",
|
|
112
|
+
params: [`${serial}`, certificateType]
|
|
99
113
|
}
|
|
100
114
|
}).execute();
|
|
101
|
-
|
|
115
|
+
// a certificate issued for another key is reported as not found, so
|
|
116
|
+
// requests cannot be used to discover which serials exist
|
|
117
|
+
if (res.results?.public_key == null || !isKey(res.results.public_key, publicKey)) {
|
|
102
118
|
return RevocationStatus.NotFound;
|
|
103
119
|
}
|
|
104
120
|
if (res.results.revoked_at !== null) {
|
|
105
121
|
return RevocationStatus.Revoked;
|
|
106
122
|
}
|
|
107
|
-
|
|
108
|
-
return RevocationStatus.Revokable;
|
|
109
|
-
}
|
|
110
|
-
return RevocationStatus.Unrevokable;
|
|
123
|
+
return RevocationStatus.Revokable;
|
|
111
124
|
};
|
|
112
125
|
export const getRevocationList = async (env, certificateType) => {
|
|
113
126
|
const qb = await connect(env);
|
|
127
|
+
// fetchAll cannot infer the table from its parameters, so it is given explicitly
|
|
128
|
+
// as otherwise the result is untyped once the schema has more than one table
|
|
114
129
|
const res = await qb.fetchAll({
|
|
115
130
|
tableName: "certificates",
|
|
116
131
|
fields: ["serial"],
|
|
@@ -148,4 +163,62 @@ export const revokeCertificate = async (env, serial) => {
|
|
|
148
163
|
}
|
|
149
164
|
return res.results;
|
|
150
165
|
};
|
|
166
|
+
const KrlVersionRow = z.object({
|
|
167
|
+
version: z.number().int().nonnegative(),
|
|
168
|
+
digest: z.string().nullable(),
|
|
169
|
+
});
|
|
170
|
+
// the number of times to retry when another request updates the KRL version concurrently
|
|
171
|
+
const KRL_VERSION_ATTEMPTS = 5;
|
|
172
|
+
/**
|
|
173
|
+
* Get the version of the KRL for a certificate type, incrementing it if the
|
|
174
|
+
* content of the KRL has changed since the version was last returned.
|
|
175
|
+
*
|
|
176
|
+
* The version is only ever incremented, so clients can use it to detect a
|
|
177
|
+
* newer KRL. When several requests see the same change concurrently the
|
|
178
|
+
* version is incremented once.
|
|
179
|
+
*
|
|
180
|
+
* @param env The bindings for the CA, see {@link SshCaBindings}
|
|
181
|
+
* @param certificateType The type of certificates in the KRL, see {@link CertificateType}
|
|
182
|
+
* @param digest A digest of the content of the KRL, which changes whenever the content does
|
|
183
|
+
* @returns The version to use for the KRL
|
|
184
|
+
*/
|
|
185
|
+
export const getKrlVersion = async (env, certificateType, digest) => {
|
|
186
|
+
const qb = await connect(env);
|
|
187
|
+
for (let attempt = 0; attempt < KRL_VERSION_ATTEMPTS; attempt++) {
|
|
188
|
+
const res = await qb.fetchOne({
|
|
189
|
+
tableName: "krl",
|
|
190
|
+
fields: ["version", "digest"],
|
|
191
|
+
where: {
|
|
192
|
+
conditions: "certificate_type = ?",
|
|
193
|
+
params: certificateType
|
|
194
|
+
}
|
|
195
|
+
}).execute();
|
|
196
|
+
const current = KrlVersionRow.parse(res.results);
|
|
197
|
+
if (current.digest === digest) {
|
|
198
|
+
return BigInt(current.version);
|
|
199
|
+
}
|
|
200
|
+
// only update if the version has not been changed by another request
|
|
201
|
+
const next = current.version + 1;
|
|
202
|
+
const updated = await qb.update({
|
|
203
|
+
tableName: "krl",
|
|
204
|
+
data: {
|
|
205
|
+
version: next,
|
|
206
|
+
digest: digest,
|
|
207
|
+
updated_at: (new Date).toISOString()
|
|
208
|
+
},
|
|
209
|
+
where: {
|
|
210
|
+
conditions: "certificate_type = ? AND version = ?",
|
|
211
|
+
params: [certificateType, current.version]
|
|
212
|
+
},
|
|
213
|
+
returning: ["version"]
|
|
214
|
+
}).execute();
|
|
215
|
+
if (!updated.success) {
|
|
216
|
+
throw new Error("error during query");
|
|
217
|
+
}
|
|
218
|
+
if (updated.results !== undefined && updated.results.length > 0) {
|
|
219
|
+
return BigInt(next);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
throw new Error("unable to update KRL version due to concurrent updates");
|
|
223
|
+
};
|
|
151
224
|
//# sourceMappingURL=index.js.map
|
package/dist/db/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,eAAe,EAA+D,MAAM,YAAY,CAAA;AAEzG,MAAM,OAAO,GAAG,KAAK,EAAE,GAAkB,EAAiC,EAAE;IAC3E,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;IAErB,IAAI,CAAC;QACJ,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;QAEjC,MAAM,iBAAiB,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;QAE/D,CAAC,CAAC,KAAK,CAAC,6BAA6B,EAAE,YAAY,EAAE,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;QAErI,OAAO,IAAI,IAAI,CAAiB,GAAG,CAAC,EAAE,CAAC,CAAA;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,CAAC,CAAC,KAAK,CAAC,8BAA8B,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;QACrD,MAAM,GAAG,CAAA;IACV,CAAC;AACF,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,GAAkB,EAAE,EAAE;IACrD,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,wBAAwB,CAAC,CAAA;IAErE,IAAI,GAAG,CAAC,wBAAwB,KAAK,UAAU,EAAE,CAAC;QACjD,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;QACnC,OAAM;IACP,CAAC;IAED,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;IACnC,IAAI,CAAC;QACJ,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;QAC7B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC;YAC3B,SAAS,EAAE,cAAc;YACzB,KAAK,EAAE;gBACN,UAAU,EAAE,0DAA0D;gBACtE,MAAM,EAAE,GAAG,CAAC,wBAAwB;aACpC;SACD,CAAC,CAAC,OAAO,EAAE,CAAA;QACZ,CAAC,CAAC,IAAI,CAAC,4BAA4B,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IACnE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,CAAC,CAAC,KAAK,CAAC,+BAA+B,EAAE,WAAW,EAAE,GAAG,CAAC,wBAAwB,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IAClG,CAAC;AACF,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,GAAkB,EAAE,WAA2B,EAAE,KAAa,EAAE,eAAe,GAAoB,eAAe,CAAC,IAAI,EAAE,EAAE;IAClK,oEAAoE;IACpE,uCAAuC;IACvC,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,WAAW,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACpH,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC;QAC3B,SAAS,EAAE,cAAc;QACzB,IAAI,EAAE;YACL,MAAM,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE;YAC/B,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,UAAU;YACtB,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5C,WAAW,EAAE,WAAW,CAAC,UAAU,CAAC,WAAW,EAAE;YACjD,YAAY,EAAE,WAAW,CAAC,WAAW,CAAC,WAAW,EAAE;YACnD,gBAAgB,EAAE,eAAe;YACjC,UAAU,EAAE,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;SAC5C;KACD,CAAC,CAAC,OAAO,EAAE,CAAA;IAEZ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACtC,CAAC;AACF,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,GAAkB,EAAE,MAAc,EAAoB,EAAE;IACvF,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC;QAC7B,SAAS,EAAE,cAAc;QACzB,MAAM,EAAE,CAAC,QAAQ,CAAC;QAClB,KAAK,EAAE;YACN,UAAU,EAAE,mCAAmC;YAC/C,MAAM,EAAE,GAAG,MAAM,EAAE;SACnB;KACD,CAAC,CAAC,OAAO,EAAE,CAAA;IAEZ,OAAO,GAAG,CAAC,OAAO,KAAK,SAAS,CAAA;AACjC,CAAC,CAAA;AAED,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC3B,+DAAQ,CAAA;IACR,6DAAO,CAAA;IACP,iEAAS,CAAA;AACV,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B;AAED,8EAA8E;AAC9E,mEAAmE;AACnE,MAAM,KAAK,GAAG,CAAC,QAAgB,EAAE,SAAoB,EAAW,EAAE;IACjE,IAAI,CAAC;QACJ,OAAO,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAA;IACb,CAAC;AACF,CAAC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,GAAkB,EAAE,MAAc,EAAE,SAAoB,EAAE,eAAgC,EAA6B,EAAE;IAC/J,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC;QAC7B,SAAS,EAAE,cAAc;QACzB,MAAM,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;QACpC,KAAK,EAAE;YACN,UAAU,EAAE,qCAAqC;YACjD,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,eAAe,CAAC;SACtC;KACD,CAAC,CAAC,OAAO,EAAE,CAAA;IAEZ,oEAAoE;IACpE,0DAA0D;IAC1D,IAAI,GAAG,CAAC,OAAO,EAAE,UAAU,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC;QAClF,OAAO,gBAAgB,CAAC,QAAQ,CAAA;IACjC,CAAC;IAED,IAAI,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QACrC,OAAO,gBAAgB,CAAC,OAAO,CAAA;IAChC,CAAC;IAED,OAAO,gBAAgB,CAAC,SAAS,CAAA;AAClC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,GAAkB,EAAE,eAAgC,EAAqB,EAAE;IAClH,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7B,iFAAiF;IACjF,6EAA6E;IAC7E,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAA2B;QACvD,SAAS,EAAE,cAAc;QACzB,MAAM,EAAE,CAAC,QAAQ,CAAC;QAClB,KAAK,EAAE;YACN,UAAU,EAAE,mHAAmH;YAC/H,MAAM,EAAE,eAAe;SACvB;KACD,CAAC,CAAC,OAAO,EAAE,CAAA;IAEZ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACtC,CAAC;IAED,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAA;IACV,CAAC;IAED,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAC5C,CAAC,CAAA;AAID,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,GAAkB,EAAE,MAAc,EAAiC,EAAE;IAC5G,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,MAAM,CAAqB;QAC/C,SAAS,EAAE,cAAc;QACzB,IAAI,EAAE;YACL,UAAU,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE;SACpC;QACD,KAAK,EAAE;YACN,UAAU,EAAE,YAAY;YACxB,MAAM,EAAE,GAAG,MAAM,EAAE;SACnB;QACD,SAAS,EAAE,CAAC,YAAY,CAAC;KACzB,CAAC,CAAC,OAAO,EAAE,CAAA;IAEZ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;IACtC,CAAC;IAED,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAA;IACV,CAAC;IAED,OAAO,GAAG,CAAC,OAAO,CAAA;AACnB,CAAC,CAAA;AAED,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACvC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAA;AAEF,yFAAyF;AACzF,MAAM,oBAAoB,GAAG,CAAC,CAAA;AAE9B;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,GAAkB,EAAE,eAAgC,EAAE,MAAc,EAAmB,EAAE;IAC5H,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;IAE7B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,oBAAoB,EAAE,OAAO,EAAE,EAAE,CAAC;QACjE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC;YAC7B,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;YAC7B,KAAK,EAAE;gBACN,UAAU,EAAE,sBAAsB;gBAClC,MAAM,EAAE,eAAe;aACvB;SACD,CAAC,CAAC,OAAO,EAAE,CAAA;QAEZ,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAChD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC/B,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC/B,CAAC;QAED,qEAAqE;QACrE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,CAAC,CAAA;QAChC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,MAAM,CAA6B;YAC3D,SAAS,EAAE,KAAK;YAChB,IAAI,EAAE;gBACL,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,MAAM;gBACd,UAAU,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE;aACpC;YACD,KAAK,EAAE;gBACN,UAAU,EAAE,sCAAsC;gBAClD,MAAM,EAAE,CAAC,eAAe,EAAE,OAAO,CAAC,OAAO,CAAC;aAC1C;YACD,SAAS,EAAE,CAAC,SAAS,CAAC;SACtB,CAAC,CAAC,OAAO,EAAE,CAAA;QAEZ,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;QACtC,CAAC;QAED,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAA;QACpB,CAAC;IACF,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;AAC1E,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0002_krl_version.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/0002_krl_version.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,eAAO,MAAM,SAAS,EAAE,SAavB,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const migration = {
|
|
2
|
+
name: "0002_krl_version",
|
|
3
|
+
statements: [
|
|
4
|
+
`CREATE TABLE IF NOT EXISTS krl (
|
|
5
|
+
certificate_type INTEGER PRIMARY KEY,
|
|
6
|
+
version INTEGER NOT NULL,
|
|
7
|
+
digest TEXT,
|
|
8
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
|
|
9
|
+
)`,
|
|
10
|
+
// KRLs were previously always version 1 and have no digest, so the
|
|
11
|
+
// first KRL generated after this migration is version 2
|
|
12
|
+
"INSERT OR IGNORE INTO krl (certificate_type, version, digest) VALUES (0, 1, NULL), (1, 1, NULL)",
|
|
13
|
+
]
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=0002_krl_version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0002_krl_version.js","sourceRoot":"","sources":["../../../src/db/migrations/0002_krl_version.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAc;IACnC,IAAI,EAAE,kBAAkB;IACxB,UAAU,EAAE;QACX;;;;;IAKE;QACF,mEAAmE;QACnE,wDAAwD;QACxD,iGAAiG;KACjG;CACD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/db/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAI9C,eAAO,MAAM,UAAU,EAAE,SAAS,EAGjC,CAAA"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { migration as initialSchema0001 } from "./0001_initial_schema.js";
|
|
2
|
+
import { migration as krlVersion0002 } from "./0002_krl_version.js";
|
|
2
3
|
export const migrations = [
|
|
3
|
-
initialSchema0001
|
|
4
|
+
initialSchema0001,
|
|
5
|
+
krlVersion0002,
|
|
4
6
|
];
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/db/migrations/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/db/migrations/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,SAAS,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEnE,MAAM,CAAC,MAAM,UAAU,GAAgB;IACtC,iBAAiB;IACjB,cAAc;CACd,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database types used by workers-qb to type queries.
|
|
3
|
+
*
|
|
4
|
+
* These must match the schema created by the migrations in `./migrations`, so
|
|
5
|
+
* update them with any change to the database.
|
|
6
|
+
*/
|
|
7
|
+
/** The type of certificate, as stored in the `certificate_type` column */
|
|
8
|
+
export declare enum CertificateType {
|
|
9
|
+
User = 0,
|
|
10
|
+
Host = 1
|
|
11
|
+
}
|
|
12
|
+
/** A row in the `certificates` table */
|
|
13
|
+
export type CertificateRecord = {
|
|
14
|
+
id: number;
|
|
15
|
+
serial: string;
|
|
16
|
+
key_id: string;
|
|
17
|
+
principals: string;
|
|
18
|
+
extensions: string | null;
|
|
19
|
+
valid_after: Date;
|
|
20
|
+
valid_before: Date;
|
|
21
|
+
revoked_at: Date | null;
|
|
22
|
+
certificate_type: CertificateType;
|
|
23
|
+
public_key: string | null;
|
|
24
|
+
};
|
|
25
|
+
/** A row in the `krl` table, holding the current version of the KRL for a {@link CertificateType} */
|
|
26
|
+
export type KrlRecord = {
|
|
27
|
+
certificate_type: CertificateType;
|
|
28
|
+
version: number;
|
|
29
|
+
digest: string | null;
|
|
30
|
+
updated_at: Date;
|
|
31
|
+
};
|
|
32
|
+
/** The tables in the database, used to type queries made with workers-qb */
|
|
33
|
+
export type DatabaseSchema = {
|
|
34
|
+
certificates: CertificateRecord;
|
|
35
|
+
krl: KrlRecord;
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/db/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0EAA0E;AAC1E,oBAAY,eAAe;IAC1B,IAAI,IAAA;IACJ,IAAI,IAAA;CACJ;AAED,wCAAwC;AACxC,MAAM,MAAM,iBAAiB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,WAAW,EAAE,IAAI,CAAA;IACjB,YAAY,EAAE,IAAI,CAAA;IAClB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAA;IACvB,gBAAgB,EAAE,eAAe,CAAA;IACjC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB,CAAA;AAED,qGAAqG;AACrG,MAAM,MAAM,SAAS,GAAG;IACvB,gBAAgB,EAAE,eAAe,CAAA;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,IAAI,CAAA;CAChB,CAAA;AAED,4EAA4E;AAC5E,MAAM,MAAM,cAAc,GAAG;IAC5B,YAAY,EAAE,iBAAiB,CAAA;IAC/B,GAAG,EAAE,SAAS,CAAA;CACd,CAAA"}
|
package/dist/db/types.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database types used by workers-qb to type queries.
|
|
3
|
+
*
|
|
4
|
+
* These must match the schema created by the migrations in `./migrations`, so
|
|
5
|
+
* update them with any change to the database.
|
|
6
|
+
*/
|
|
7
|
+
/** The type of certificate, as stored in the `certificate_type` column */
|
|
8
|
+
export var CertificateType;
|
|
9
|
+
(function (CertificateType) {
|
|
10
|
+
CertificateType[CertificateType["User"] = 0] = "User";
|
|
11
|
+
CertificateType[CertificateType["Host"] = 1] = "Host";
|
|
12
|
+
})(CertificateType || (CertificateType = {}));
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/db/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0EAA0E;AAC1E,MAAM,CAAN,IAAY,eAGX;AAHD,WAAY,eAAe;IAC1B,qDAAI,CAAA;IACJ,qDAAI,CAAA;AACL,CAAC,EAHW,eAAe,KAAf,eAAe,QAG1B"}
|
package/dist/krl.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PrivateKey } from "
|
|
1
|
+
import type { PrivateKey } from "./ssh/keys.js";
|
|
2
2
|
export declare class KRLBuilder {
|
|
3
3
|
private readonly _caKey;
|
|
4
4
|
private readonly _serials;
|
|
@@ -19,6 +19,14 @@ export declare class KRLBuilder {
|
|
|
19
19
|
* This must not be called after generate() has been called
|
|
20
20
|
*/
|
|
21
21
|
addKeyIds(keyIds: string[]): this;
|
|
22
|
+
/**
|
|
23
|
+
* Return a hex encoded SHA-256 digest of the content of the KRL.
|
|
24
|
+
*
|
|
25
|
+
* The digest covers the CA public key and the revoked serials and key IDs,
|
|
26
|
+
* but not the order they were added in or the header, so it only changes
|
|
27
|
+
* when the set of revoked certificates or the CA does.
|
|
28
|
+
*/
|
|
29
|
+
digest(): Promise<string>;
|
|
22
30
|
/**
|
|
23
31
|
* Generate the binary KRL
|
|
24
32
|
*
|
package/dist/krl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"krl.d.ts","sourceRoot":"","sources":["../src/krl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"krl.d.ts","sourceRoot":"","sources":["../src/krl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAsF/C,qBAAa,UAAU;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,IAAI,CAA2B;IAEvC,YAAY,KAAK,EAAE,UAAU,EAE5B;IAED;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAMlC;IAED;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAMhC;IAED;;;;;;OAMG;IACG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAc9B;IAED;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,GAAE,MAAW,EAAE,OAAO,SAAK,GAAG,WAAW,CAgE3D;IAED;;;;;;;;OAQG;IACG,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAqDjC;CACJ"}
|
package/dist/krl.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createSigner } from "./ssh/signer.js";
|
|
2
2
|
// ── Constants ────────────────────────────────────────────────────────────────
|
|
3
3
|
const KRL_MAGIC = 0x5353484b524c0a00n; // "SSHKRL\n\0"
|
|
4
4
|
const KRL_FORMAT_VERSION = 1;
|
|
@@ -47,160 +47,11 @@ function concat(...parts) {
|
|
|
47
47
|
function encodeSection(sectionType, data) {
|
|
48
48
|
return concat(new Uint8Array([sectionType]), encodeString(data));
|
|
49
49
|
}
|
|
50
|
-
// ── CA public-key extraction ─────────────────────────────────────────────────
|
|
51
|
-
/**
|
|
52
|
-
* Extract the SSH wire-format public key bytes from an sshpk PrivateKey.
|
|
53
|
-
*
|
|
54
|
-
* sshpk's "ssh" format produces a string like:
|
|
55
|
-
* ssh-ed25519 AAAA...base64... [comment]
|
|
56
|
-
*
|
|
57
|
-
* The base64 blob *is* the SSH wire encoding of the public key, so we just
|
|
58
|
-
* decode it. This works for both Ed25519 and ECDSA keys.
|
|
59
|
-
*/
|
|
60
|
-
function caKeyWireBytes(caKey) {
|
|
61
|
-
const sshString = caKey.toPublic().toString("ssh");
|
|
62
|
-
// Format: "<type> <base64> [<comment>]" — we want the second token.
|
|
63
|
-
const base64 = sshString.trim().split(/\s+/)[1];
|
|
64
|
-
if (!base64) {
|
|
65
|
-
throw new Error("Unexpected sshpk 'ssh' format output: " + sshString);
|
|
66
|
-
}
|
|
67
|
-
const binary = atob(base64);
|
|
68
|
-
const bytes = new Uint8Array(binary.length);
|
|
69
|
-
for (let i = 0; i < binary.length; i++) {
|
|
70
|
-
bytes[i] = binary.charCodeAt(i);
|
|
71
|
-
}
|
|
72
|
-
return bytes;
|
|
73
|
-
}
|
|
74
50
|
// ── Constants ────────────────────────────────────────────────────────────────
|
|
75
51
|
const SSHSIG_MAGIC = new TextEncoder().encode("SSHSIG");
|
|
76
52
|
const SIG_VERSION = 1;
|
|
77
53
|
const NAMESPACE = "krl@com.github.serverless-ssh-ca.andrewheberle";
|
|
78
54
|
const HASH_ALGORITHM = "sha512";
|
|
79
|
-
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
80
|
-
/**
|
|
81
|
-
* Get the raw bytes of a named part of an sshpk key.
|
|
82
|
-
*/
|
|
83
|
-
function keyPart(key, name) {
|
|
84
|
-
const part = key.parts.find((p) => p.name === name);
|
|
85
|
-
if (part === undefined) {
|
|
86
|
-
throw new Error(`Missing ${name} part in ${key.type} key`);
|
|
87
|
-
}
|
|
88
|
-
return part.data;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Base64url-encode bytes without padding, as used for JWK values.
|
|
92
|
-
*/
|
|
93
|
-
function base64url(bytes) {
|
|
94
|
-
let binary = "";
|
|
95
|
-
for (const byte of bytes) {
|
|
96
|
-
binary += String.fromCharCode(byte);
|
|
97
|
-
}
|
|
98
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Import an sshpk PrivateKey into a WebCrypto CryptoKey.
|
|
102
|
-
* Supports Ed25519 and ECDSA (P-256 / P-384 / P-521).
|
|
103
|
-
*/
|
|
104
|
-
async function importPrivateKey(caKey) {
|
|
105
|
-
const type = caKey.type; // "ed25519" | "ecdsa" | etc.
|
|
106
|
-
const curve = caKey.curve;
|
|
107
|
-
if (type === "ed25519") {
|
|
108
|
-
// import from the raw key parts as a JWK rather than via sshpk's PKCS#8
|
|
109
|
-
// output, which drops a leading zero byte from the seed (about 1 key in
|
|
110
|
-
// 512) and is then rejected by WebCrypto
|
|
111
|
-
const seed = keyPart(caKey, "k");
|
|
112
|
-
const publicKey = keyPart(caKey, "A");
|
|
113
|
-
if (seed.length !== 32 || publicKey.length !== 32) {
|
|
114
|
-
throw new Error(`Unexpected Ed25519 key part lengths: k=${seed.length} A=${publicKey.length}`);
|
|
115
|
-
}
|
|
116
|
-
const cryptoKey = await crypto.subtle.importKey("jwk", { kty: "OKP", crv: "Ed25519", d: base64url(seed), x: base64url(publicKey) }, { name: "Ed25519" }, false, ["sign"]);
|
|
117
|
-
return {
|
|
118
|
-
cryptoKey,
|
|
119
|
-
sigAlgo: "ssh-ed25519",
|
|
120
|
-
webCryptoAlgo: { name: "Ed25519" },
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
else if (type === "ecdsa") {
|
|
124
|
-
let namedCurve;
|
|
125
|
-
let sigAlgo;
|
|
126
|
-
let hash;
|
|
127
|
-
let size; // bytes in each coordinate and the private key
|
|
128
|
-
if (curve === "nistp256") {
|
|
129
|
-
namedCurve = "P-256";
|
|
130
|
-
sigAlgo = "ecdsa-sha2-nistp256";
|
|
131
|
-
hash = "SHA-256";
|
|
132
|
-
size = 32;
|
|
133
|
-
}
|
|
134
|
-
else if (curve === "nistp384") {
|
|
135
|
-
namedCurve = "P-384";
|
|
136
|
-
sigAlgo = "ecdsa-sha2-nistp384";
|
|
137
|
-
hash = "SHA-384";
|
|
138
|
-
size = 48;
|
|
139
|
-
}
|
|
140
|
-
else if (curve === "nistp521") {
|
|
141
|
-
namedCurve = "P-521";
|
|
142
|
-
sigAlgo = "ecdsa-sha2-nistp521";
|
|
143
|
-
hash = "SHA-512";
|
|
144
|
-
size = 66;
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
throw new Error(`Unsupported ECDSA curve: ${curve}`);
|
|
148
|
-
}
|
|
149
|
-
// import from the raw key parts as a JWK rather than via sshpk's PKCS#8
|
|
150
|
-
// output, which drops leading zero bytes from the private key so it is
|
|
151
|
-
// shorter than RFC 5915 requires (about half of P-521 keys)
|
|
152
|
-
const point = keyPart(caKey, "Q");
|
|
153
|
-
if (point.length !== 1 + size * 2 || point[0] !== 0x04) {
|
|
154
|
-
throw new Error(`Unexpected ECDSA public key encoding for ${curve}`);
|
|
155
|
-
}
|
|
156
|
-
// d is an SSH mpint, so may be short or have a leading sign byte
|
|
157
|
-
const d = toFixedWidth(keyPart(caKey, "d"), size);
|
|
158
|
-
const cryptoKey = await crypto.subtle.importKey("jwk", {
|
|
159
|
-
kty: "EC",
|
|
160
|
-
crv: namedCurve,
|
|
161
|
-
d: base64url(d),
|
|
162
|
-
x: base64url(point.subarray(1, 1 + size)),
|
|
163
|
-
y: base64url(point.subarray(1 + size)),
|
|
164
|
-
}, { name: "ECDSA", namedCurve }, false, ["sign"]);
|
|
165
|
-
return {
|
|
166
|
-
cryptoKey,
|
|
167
|
-
sigAlgo,
|
|
168
|
-
webCryptoAlgo: { name: "ECDSA", hash: { name: hash } },
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
throw new Error(`Unsupported key type: ${type}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Convert a WebCrypto ECDSA signature (IEEE P1363: raw r||s) to the SSH wire
|
|
177
|
-
* encoding: string(algo) + string(mpint(r) + mpint(s)).
|
|
178
|
-
*
|
|
179
|
-
* SSH mpints are big-endian, with a leading 0x00 byte if the high bit is set.
|
|
180
|
-
*/
|
|
181
|
-
function p1363ToSshEcdsaSig(p1363, sigAlgo) {
|
|
182
|
-
const half = p1363.length / 2;
|
|
183
|
-
const r = p1363.slice(0, half);
|
|
184
|
-
const s = p1363.slice(half);
|
|
185
|
-
function encodeMpint(n) {
|
|
186
|
-
// Strip leading zero bytes, then re-pad if high bit set.
|
|
187
|
-
let start = 0;
|
|
188
|
-
while (start < n.length - 1 && n[start] === 0)
|
|
189
|
-
start++;
|
|
190
|
-
const trimmed = n.slice(start);
|
|
191
|
-
const padded = trimmed[0] & 0x80 ? concat(new Uint8Array([0x00]), trimmed) : trimmed;
|
|
192
|
-
return encodeString(padded);
|
|
193
|
-
}
|
|
194
|
-
const innerSig = concat(encodeMpint(r), encodeMpint(s));
|
|
195
|
-
return concat(encodeString(sigAlgo), encodeString(innerSig));
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Wrap an Ed25519 WebCrypto signature into SSH wire encoding:
|
|
199
|
-
* string(algo) + string(sig_bytes)
|
|
200
|
-
*/
|
|
201
|
-
function wrapEd25519Sig(sig) {
|
|
202
|
-
return concat(encodeString("ssh-ed25519"), encodeString(sig));
|
|
203
|
-
}
|
|
204
55
|
/**
|
|
205
56
|
* Base64-encode bytes and wrap in SSH signature armor at 76 chars per line.
|
|
206
57
|
*/
|
|
@@ -251,6 +102,20 @@ export class KRLBuilder {
|
|
|
251
102
|
this._keyIds.push(...keyIds);
|
|
252
103
|
return this;
|
|
253
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Return a hex encoded SHA-256 digest of the content of the KRL.
|
|
107
|
+
*
|
|
108
|
+
* The digest covers the CA public key and the revoked serials and key IDs,
|
|
109
|
+
* but not the order they were added in or the header, so it only changes
|
|
110
|
+
* when the set of revoked certificates or the CA does.
|
|
111
|
+
*/
|
|
112
|
+
async digest() {
|
|
113
|
+
const serials = [...this._serials].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
114
|
+
const keyIds = [...this._keyIds].sort();
|
|
115
|
+
const content = concat(encodeString(this._caKey.publicKey.blob), encodeUint32(serials.length), ...serials.map(encodeUint64), encodeUint32(keyIds.length), ...keyIds.map((id) => encodeString(id)));
|
|
116
|
+
const hash = new Uint8Array(await crypto.subtle.digest("SHA-256", content));
|
|
117
|
+
return Array.from(hash, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
118
|
+
}
|
|
254
119
|
/**
|
|
255
120
|
* Generate the binary KRL
|
|
256
121
|
*
|
|
@@ -285,7 +150,7 @@ export class KRLBuilder {
|
|
|
285
150
|
// string reserved
|
|
286
151
|
// <one or more cert sub-sections>
|
|
287
152
|
//
|
|
288
|
-
const certSectionData = concat(encodeString(
|
|
153
|
+
const certSectionData = concat(encodeString(this._caKey.publicKey.blob), // ca_key
|
|
289
154
|
encodeString(""), // reserved
|
|
290
155
|
...certSubSections);
|
|
291
156
|
const certificatesSection = encodeSection(KRL_SECTION_CERTIFICATES, certSectionData);
|
|
@@ -311,7 +176,7 @@ export class KRLBuilder {
|
|
|
311
176
|
else {
|
|
312
177
|
krl = this._krl;
|
|
313
178
|
}
|
|
314
|
-
const
|
|
179
|
+
const signer = await createSigner(this._caKey);
|
|
315
180
|
// 1. Hash the KRL bytes with SHA-512.
|
|
316
181
|
const krlHash = new Uint8Array(await crypto.subtle.digest("SHA-512", krl));
|
|
317
182
|
// 2. Build the signed data blob.
|
|
@@ -323,13 +188,9 @@ export class KRLBuilder {
|
|
|
323
188
|
// string H(message)
|
|
324
189
|
const signedData = concat(SSHSIG_MAGIC, encodeString(NAMESPACE), encodeString(""), // reserved
|
|
325
190
|
encodeString(HASH_ALGORITHM), encodeString(krlHash));
|
|
326
|
-
// 3. Sign the blob.
|
|
327
|
-
const
|
|
328
|
-
// 4.
|
|
329
|
-
const sshSig = sigAlgo === "ssh-ed25519"
|
|
330
|
-
? wrapEd25519Sig(rawSig)
|
|
331
|
-
: p1363ToSshEcdsaSig(rawSig, sigAlgo);
|
|
332
|
-
// 5. Assemble the outer SSHSIG blob.
|
|
191
|
+
// 3. Sign the blob, which returns the signature in SSH wire format.
|
|
192
|
+
const sshSig = await signer.sign(signedData);
|
|
193
|
+
// 4. Assemble the outer SSHSIG blob.
|
|
333
194
|
//
|
|
334
195
|
// byte[6] "SSHSIG"
|
|
335
196
|
// uint32 SIG_VERSION (1)
|
|
@@ -338,10 +199,9 @@ export class KRLBuilder {
|
|
|
338
199
|
// string reserved (empty)
|
|
339
200
|
// string hash_algorithm
|
|
340
201
|
// string signature
|
|
341
|
-
const
|
|
342
|
-
const sigBlob = concat(SSHSIG_MAGIC, encodeUint32(SIG_VERSION), encodeString(publicKeyWire), encodeString(NAMESPACE), encodeString(""), // reserved
|
|
202
|
+
const sigBlob = concat(SSHSIG_MAGIC, encodeUint32(SIG_VERSION), encodeString(signer.publicKey), encodeString(NAMESPACE), encodeString(""), // reserved
|
|
343
203
|
encodeString(HASH_ALGORITHM), encodeString(sshSig));
|
|
344
|
-
//
|
|
204
|
+
// 5. Armor and return.
|
|
345
205
|
return armorSignature(sigBlob);
|
|
346
206
|
}
|
|
347
207
|
}
|
package/dist/krl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"krl.js","sourceRoot":"","sources":["../src/krl.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"krl.js","sourceRoot":"","sources":["../src/krl.ts"],"names":[],"mappings":"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"}
|