@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.
Files changed (98) hide show
  1. package/README.md +55 -1
  2. package/dist/api/operations.d.ts +49 -0
  3. package/dist/api/operations.d.ts.map +1 -0
  4. package/dist/api/operations.js +175 -0
  5. package/dist/api/operations.js.map +1 -0
  6. package/dist/api/schema.d.ts +71 -0
  7. package/dist/api/schema.d.ts.map +1 -0
  8. package/dist/api/schema.js +107 -0
  9. package/dist/api/schema.js.map +1 -0
  10. package/dist/api/v3/index.d.ts.map +1 -1
  11. package/dist/api/v3/index.js +25 -212
  12. package/dist/api/v3/index.js.map +1 -1
  13. package/dist/api/v3/schema.d.ts +30 -74
  14. package/dist/api/v3/schema.d.ts.map +1 -1
  15. package/dist/api/v3/schema.js +18 -73
  16. package/dist/api/v3/schema.js.map +1 -1
  17. package/dist/api/v4/index.d.ts +8 -0
  18. package/dist/api/v4/index.d.ts.map +1 -0
  19. package/dist/api/v4/index.js +155 -0
  20. package/dist/api/v4/index.js.map +1 -0
  21. package/dist/api/v4/schema.d.ts +268 -0
  22. package/dist/api/v4/schema.d.ts.map +1 -0
  23. package/dist/api/v4/schema.js +182 -0
  24. package/dist/api/v4/schema.js.map +1 -0
  25. package/dist/certificate.d.ts +9 -6
  26. package/dist/certificate.d.ts.map +1 -1
  27. package/dist/certificate.js +55 -99
  28. package/dist/certificate.js.map +1 -1
  29. package/dist/db/index.d.ts +32 -24
  30. package/dist/db/index.d.ts.map +1 -1
  31. package/dist/db/index.js +101 -28
  32. package/dist/db/index.js.map +1 -1
  33. package/dist/db/migrations/0002_krl_version.d.ts +3 -0
  34. package/dist/db/migrations/0002_krl_version.d.ts.map +1 -0
  35. package/dist/db/migrations/0002_krl_version.js +15 -0
  36. package/dist/db/migrations/0002_krl_version.js.map +1 -0
  37. package/dist/db/migrations/index.d.ts.map +1 -1
  38. package/dist/db/migrations/index.js +3 -1
  39. package/dist/db/migrations/index.js.map +1 -1
  40. package/dist/db/types.d.ts +37 -0
  41. package/dist/db/types.d.ts.map +1 -0
  42. package/dist/db/types.js +13 -0
  43. package/dist/db/types.js.map +1 -0
  44. package/dist/krl.d.ts +9 -1
  45. package/dist/krl.d.ts.map +1 -1
  46. package/dist/krl.js +22 -162
  47. package/dist/krl.js.map +1 -1
  48. package/dist/proof.d.ts +36 -7
  49. package/dist/proof.d.ts.map +1 -1
  50. package/dist/proof.js +53 -21
  51. package/dist/proof.js.map +1 -1
  52. package/dist/router.d.ts.map +1 -1
  53. package/dist/router.js +3 -1
  54. package/dist/router.js.map +1 -1
  55. package/dist/ssh/certificate.d.ts +93 -0
  56. package/dist/ssh/certificate.d.ts.map +1 -0
  57. package/dist/ssh/certificate.js +178 -0
  58. package/dist/ssh/certificate.js.map +1 -0
  59. package/dist/ssh/encoding.d.ts +41 -0
  60. package/dist/ssh/encoding.d.ts.map +1 -0
  61. package/dist/ssh/encoding.js +70 -0
  62. package/dist/ssh/encoding.js.map +1 -0
  63. package/dist/ssh/keys.d.ts +80 -0
  64. package/dist/ssh/keys.d.ts.map +1 -0
  65. package/dist/ssh/keys.js +249 -0
  66. package/dist/ssh/keys.js.map +1 -0
  67. package/dist/ssh/signer.d.ts +35 -0
  68. package/dist/ssh/signer.d.ts.map +1 -0
  69. package/dist/ssh/signer.js +99 -0
  70. package/dist/ssh/signer.js.map +1 -0
  71. package/dist/types.d.ts +12 -17
  72. package/dist/types.d.ts.map +1 -1
  73. package/dist/utils.d.ts +40 -21
  74. package/dist/utils.d.ts.map +1 -1
  75. package/dist/utils.js +87 -54
  76. package/dist/utils.js.map +1 -1
  77. package/openapi.json +1960 -82
  78. package/package.json +5 -17
  79. package/src/api/operations.ts +211 -0
  80. package/src/api/schema.ts +137 -0
  81. package/src/api/v3/index.ts +32 -259
  82. package/src/api/v3/schema.ts +34 -96
  83. package/src/api/v4/index.ts +265 -0
  84. package/src/api/v4/schema.ts +235 -0
  85. package/src/certificate.ts +62 -123
  86. package/src/db/index.ts +113 -49
  87. package/src/db/migrations/0002_krl_version.ts +16 -0
  88. package/src/db/migrations/index.ts +3 -1
  89. package/src/db/types.ts +40 -0
  90. package/src/krl.ts +32 -194
  91. package/src/proof.ts +65 -31
  92. package/src/router.ts +3 -1
  93. package/src/ssh/certificate.ts +236 -0
  94. package/src/ssh/encoding.ts +81 -0
  95. package/src/ssh/keys.ts +294 -0
  96. package/src/ssh/signer.ts +129 -0
  97. package/src/types.ts +12 -18
  98. package/src/utils.ts +99 -69
package/dist/proof.d.ts CHANGED
@@ -1,7 +1,22 @@
1
- import type { Fingerprint, Key } from "sshpk";
1
+ import { PublicKey } from "./ssh/keys.js";
2
2
  import { Sig } from "./sshsig/sig.js";
3
3
  import { Logger } from "@andrewheberle/ts-slog";
4
4
  export declare const Namespace = "proof-of-possession@com.github.serverless-ssh-ca.andrewheberle";
5
+ /**
6
+ * The namespace used for proofs of possession that are bound to a request,
7
+ * kept separate from {@link Namespace} so a proof made for one form can never
8
+ * be accepted as the other.
9
+ */
10
+ export declare const RequestNamespace = "request-proof-of-possession@com.github.serverless-ssh-ca.andrewheberle";
11
+ /**
12
+ * Returns the request a proof of possession is bound to, which is appended to
13
+ * the signed data as `${timestamp}.${fingerprint}.${binding}`.
14
+ *
15
+ * @param method The HTTP method of the request, for example "DELETE"
16
+ * @param path The path of the request with any parameters filled in, for example "/api/v4/user/certificates/123"
17
+ * @returns The request binding, for example "DELETE /api/v4/user/certificates/123"
18
+ */
19
+ export declare const requestBinding: (method: string, path: string) => string;
5
20
  export declare class PossessionParseError extends Error {
6
21
  constructor(message: string, cause?: unknown);
7
22
  }
@@ -21,9 +36,10 @@ export declare class PossessionParseError extends Error {
21
36
  */
22
37
  export declare class ProofOfPossession {
23
38
  readonly timestamp: number;
24
- readonly fingerprint: Fingerprint;
39
+ /** The SHA256 fingerprint of the key, for example "SHA256:79mq0wtpQMTvS4+Of8VzLN0qmYWNUyTXYmqKwhEgSLs" */
40
+ readonly fingerprint: string;
25
41
  readonly signature: Sig;
26
- readonly signaturePubkey: Key;
42
+ readonly signaturePubkey: PublicKey;
27
43
  readonly logger: Logger;
28
44
  private readonly data;
29
45
  constructor(proof: string, options?: {
@@ -36,19 +52,32 @@ export declare class ProofOfPossession {
36
52
  * @returns true if signature is valid, false otherwise
37
53
  */
38
54
  verify(namespace?: string): Promise<boolean>;
55
+ /**
56
+ * Verifies the proof was made for a specific request, so it cannot be
57
+ * replayed against another endpoint or with other path parameters (such
58
+ * as a different certificate serial).
59
+ *
60
+ * The signed data is `${timestamp}.${fingerprint}.${METHOD} ${path}` using
61
+ * the {@link RequestNamespace} namespace.
62
+ *
63
+ * @param method The HTTP method of the request
64
+ * @param path The path of the request with any parameters filled in
65
+ * @returns true if signature is valid for the request, false otherwise
66
+ */
67
+ verifyRequest(method: string, path: string): Promise<boolean>;
39
68
  /**
40
69
  *
41
70
  * @param keys array of keys to verify finterprint against
42
71
  * @returns true if the proof of possession fingerprint matches any of the provided keys, false otherwise
43
72
  */
44
- matches(key: Key): boolean;
45
- matches(...keys: Key[]): boolean;
73
+ matches(key: PublicKey): boolean;
74
+ matches(...keys: PublicKey[]): boolean;
46
75
  }
47
76
  export declare class PossessionMatchError extends Error {
48
77
  constructor(message: string, cause?: unknown);
49
78
  }
50
79
  export declare class RenewalProofOfPossession extends ProofOfPossession {
51
- matches(key: Key): never;
52
- matches(...keys: Key[]): boolean;
80
+ matches(key: PublicKey): never;
81
+ matches(...keys: PublicKey[]): boolean;
53
82
  }
54
83
  //# sourceMappingURL=proof.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../src/proof.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAG7C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AACrC,OAAO,EAAS,MAAM,EAAY,MAAM,wBAAwB,CAAA;AAKhE,eAAO,MAAM,SAAS,mEAAmE,CAAA;AAEzF,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAO3C;CACD;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAiB;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAA;IACvB,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAE9B,YAAY,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAkEpF;IAED;;;OAGG;IACG,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEjD;IAED;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAA;IAC1B,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAA;CAuBhC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAO3C;CACD;AAED,qBAAa,wBAAyB,SAAQ,iBAAiB;IACrD,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,KAAK,CAAA;IACxB,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAA;CAwBzC"}
1
+ {"version":3,"file":"proof.d.ts","sourceRoot":"","sources":["../src/proof.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,SAAS,EAAE,MAAM,eAAe,CAAA;AAGxD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AACrC,OAAO,EAAS,MAAM,EAAY,MAAM,wBAAwB,CAAA;AAKhE,eAAO,MAAM,SAAS,mEAAmE,CAAA;AAEzF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,2EAA2E,CAAA;AAExG;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,WAAY,MAAM,QAAQ,MAAM,KAAG,MAE7D,CAAA;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAO3C;CACD;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAiB;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,0GAA0G;IAC1G,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAA;IACvB,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAE9B,YAAY,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAiEpF;IAED;;;OAGG;IACG,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEjD;IAED;;;;;;;;;;;OAWG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAElE;IAED;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAA;IAChC,OAAO,CAAC,GAAG,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;CAuBtC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC9C,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAO3C;CACD;AAED,qBAAa,wBAAyB,SAAQ,iBAAiB;IACrD,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,KAAK,CAAA;IAC9B,OAAO,CAAC,GAAG,IAAI,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;CAwB/C"}
package/dist/proof.js CHANGED
@@ -1,11 +1,28 @@
1
1
  import { ms } from "itty-time";
2
- import sshpk from "sshpk";
2
+ import { KeyParseError, PublicKey } from "./ssh/keys.js";
3
3
  import { verify } from "./sshsig/index.js";
4
4
  import { parse } from "./sshsig/sig_parser.js";
5
5
  import { group, Logger, LogLevel } from "@andrewheberle/ts-slog";
6
- // sshpk is CommonJS and Node's ESM loader cannot detect most of its named exports, so values are taken from the default import
7
- const { FingerprintFormatError, parseFingerprint, parseKey } = sshpk;
6
+ // a SHA256 fingerprint as shown by ssh-keygen -l, which is unpadded base64
7
+ const FingerprintFormat = /^SHA256:[A-Za-z0-9+/]{43}$/;
8
8
  export const Namespace = "proof-of-possession@com.github.serverless-ssh-ca.andrewheberle";
9
+ /**
10
+ * The namespace used for proofs of possession that are bound to a request,
11
+ * kept separate from {@link Namespace} so a proof made for one form can never
12
+ * be accepted as the other.
13
+ */
14
+ export const RequestNamespace = "request-proof-of-possession@com.github.serverless-ssh-ca.andrewheberle";
15
+ /**
16
+ * Returns the request a proof of possession is bound to, which is appended to
17
+ * the signed data as `${timestamp}.${fingerprint}.${binding}`.
18
+ *
19
+ * @param method The HTTP method of the request, for example "DELETE"
20
+ * @param path The path of the request with any parameters filled in, for example "/api/v4/user/certificates/123"
21
+ * @returns The request binding, for example "DELETE /api/v4/user/certificates/123"
22
+ */
23
+ export const requestBinding = (method, path) => {
24
+ return `${method.toUpperCase()} ${path}`;
25
+ };
9
26
  export class PossessionParseError extends Error {
10
27
  constructor(message, cause) {
11
28
  super(message);
@@ -31,6 +48,7 @@ export class PossessionParseError extends Error {
31
48
  */
32
49
  export class ProofOfPossession {
33
50
  timestamp;
51
+ /** The SHA256 fingerprint of the key, for example "SHA256:79mq0wtpQMTvS4+Of8VzLN0qmYWNUyTXYmqKwhEgSLs" */
34
52
  fingerprint;
35
53
  signature;
36
54
  signaturePubkey;
@@ -58,10 +76,9 @@ export class ProofOfPossession {
58
76
  throw new PossessionParseError("timestamp was from the future");
59
77
  }
60
78
  try {
61
- // parse fingerprint
62
- const fingerprint = parseFingerprint(fingerprintString);
63
- if (fingerprint === undefined) {
64
- throw new PossessionParseError("fingerprint did not parse");
79
+ // check fingerprint
80
+ if (!FingerprintFormat.test(fingerprintString)) {
81
+ throw new PossessionParseError("proof of possession fingerprint was an invalid format");
65
82
  }
66
83
  // convert siganture from base64
67
84
  const signature = Buffer.from(signatureBase64, "base64").toString();
@@ -73,19 +90,19 @@ export class ProofOfPossession {
73
90
  catch (err) {
74
91
  throw new PossessionParseError("proof of possession signature could not be parsed", err);
75
92
  }
76
- this.fingerprint = fingerprint;
93
+ this.fingerprint = fingerprintString;
77
94
  this.data = `${timestamp}.${fingerprintString}`;
78
- this.signaturePubkey = parseKey(this.signature.publickey.toString());
95
+ this.signaturePubkey = PublicKey.parse(this.signature.publickey.toString());
79
96
  // ensure the provided fingerprint matches the signature public key
80
- if (!this.fingerprint.matches(this.signaturePubkey)) {
97
+ if (this.fingerprint !== this.signaturePubkey.fingerprint()) {
81
98
  throw new PossessionParseError("proof of possession fingerprint does not match signature public key");
82
99
  }
83
- this.logger.debug("constructor completed", ...group("this", "timestamp", this.timestamp, "fingerprint", this.fingerprint.toString("base64"), "signaturePubkey.fingerprint()", this.signaturePubkey.fingerprint().toString("base64")));
100
+ this.logger.debug("constructor completed", ...group("this", "timestamp", this.timestamp, "fingerprint", this.fingerprint, "signaturePubkey.fingerprint()", this.signaturePubkey.fingerprint()));
84
101
  }
85
102
  catch (err) {
86
103
  switch (true) {
87
- case (err instanceof FingerprintFormatError):
88
- throw new PossessionParseError("proof of possession fingerprint was an invalid format", err);
104
+ case (err instanceof KeyParseError):
105
+ throw new PossessionParseError(`proof of possession signature key could not be used: ${err.message}`, err);
89
106
  default:
90
107
  throw err;
91
108
  }
@@ -98,17 +115,32 @@ export class ProofOfPossession {
98
115
  async verify(namespace) {
99
116
  return await verify(this.signature, this.data, { namespace: namespace || Namespace });
100
117
  }
118
+ /**
119
+ * Verifies the proof was made for a specific request, so it cannot be
120
+ * replayed against another endpoint or with other path parameters (such
121
+ * as a different certificate serial).
122
+ *
123
+ * The signed data is `${timestamp}.${fingerprint}.${METHOD} ${path}` using
124
+ * the {@link RequestNamespace} namespace.
125
+ *
126
+ * @param method The HTTP method of the request
127
+ * @param path The path of the request with any parameters filled in
128
+ * @returns true if signature is valid for the request, false otherwise
129
+ */
130
+ async verifyRequest(method, path) {
131
+ return await verify(this.signature, `${this.data}.${requestBinding(method, path)}`, { namespace: RequestNamespace });
132
+ }
101
133
  matches(...keys) {
102
134
  this.logger.debug("matches() called", "in", "ProofOfPossession", "keys", keys.length);
103
135
  try {
104
136
  for (const key of keys) {
105
137
  // confirm proof of possession fingerprint matches keys
106
- this.logger.debug("this.fingerprint.matches()", "in", "ProofOfPossession", "fingerprint", this.fingerprint.toString("base64"), "key", key.toString("ssh"));
107
- if (!this.fingerprint.matches(key))
138
+ this.logger.debug("comparing fingerprint", "in", "ProofOfPossession", "fingerprint", this.fingerprint, "key", key.toString());
139
+ if (this.fingerprint !== key.fingerprint())
108
140
  return false;
109
141
  // also confirm key used to sign proof of possession matches
110
- this.logger.debug("this.signaturePubkey.fingerprint().matches()", "in", "ProofOfPossession", "signaturePubkey", this.signaturePubkey.fingerprint().toString("base64"), "key", key.toString("ssh"));
111
- if (!this.signaturePubkey.fingerprint().matches(key))
142
+ this.logger.debug("comparing signature public key", "in", "ProofOfPossession", "signaturePubkey", this.signaturePubkey.fingerprint(), "key", key.toString());
143
+ if (!this.signaturePubkey.equals(key))
112
144
  return false;
113
145
  }
114
146
  this.logger.debug("matches() completed", "in", "ProofOfPossession", "keys", keys.length);
@@ -137,11 +169,11 @@ export class RenewalProofOfPossession extends ProofOfPossession {
137
169
  }
138
170
  try {
139
171
  for (const key of keys) {
140
- this.logger.debug("this.fingerprint.matches()", "in", "RenewalProofOfPossession", "fingerprint", this.fingerprint.toString("base64"), "key", key.toString("ssh"));
141
- if (!this.fingerprint.matches(key))
172
+ this.logger.debug("comparing fingerprint", "in", "RenewalProofOfPossession", "fingerprint", this.fingerprint, "key", key.toString());
173
+ if (this.fingerprint !== key.fingerprint())
142
174
  return false;
143
- this.logger.debug("this.signaturePubkey.fingerprint().matches()", "in", "RenewalProofOfPossession", "signaturePubkey", this.signaturePubkey.fingerprint().toString("base64"), "key", key.toString("ssh"));
144
- if (!this.signaturePubkey.fingerprint().matches(key))
175
+ this.logger.debug("comparing signature public key", "in", "RenewalProofOfPossession", "signaturePubkey", this.signaturePubkey.fingerprint(), "key", key.toString());
176
+ if (!this.signaturePubkey.equals(key))
145
177
  return false;
146
178
  }
147
179
  this.logger.debug("matches() completed", "in", "RenewalProofOfPossession", "keys", keys.length);
package/dist/proof.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"proof.js","sourceRoot":"","sources":["../src/proof.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"proof.js","sourceRoot":"","sources":["../src/proof.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,MAAM,CAAA;AAIzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,CAAA;AAE7D,eAAO,MAAM,SAAS,QAAS,aAAa,mHA+B3C,CAAA"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,MAAM,CAAA;AAKzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,CAAA;AAE7D,eAAO,MAAM,SAAS,QAAS,aAAa,mHAgC3C,CAAA"}
package/dist/router.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { fromHono } from "chanfana";
2
2
  import { Hono } from "hono";
3
3
  import { createApi as apiv3 } from "./api/v3/index.js";
4
+ import { BasePath as v4BasePath, createApi as apiv4 } from "./api/v4/index.js";
4
5
  import { HTTPException } from "hono/http-exception";
5
6
  import { logger } from "./logger.js";
6
7
  export const createApp = (env) => {
@@ -17,7 +18,7 @@ export const createApp = (env) => {
17
18
  schema: {
18
19
  info: {
19
20
  title: "Serverless SSH CA API",
20
- version: "3.0.0"
21
+ version: "4.0.0"
21
22
  },
22
23
  }
23
24
  });
@@ -27,6 +28,7 @@ export const createApp = (env) => {
27
28
  bearerFormat: 'JWT',
28
29
  });
29
30
  app.route("/api/v3", apiv3(env));
31
+ app.route(v4BasePath, apiv4(env));
30
32
  return app;
31
33
  };
32
34
  //# sourceMappingURL=router.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAA;AACzC,OAAO,EAAE,SAAS,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAKpC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAkB,EAAE,EAAE;IAC5C,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAA;IAEvB,qBAAqB;IACrB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QACpB,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,WAAW,EAAE,CAAA;QAC5B,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,8BAA8B,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;QAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;IACtG,CAAC,CAAC,CAAA;IAEF,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE;QAC7B,MAAM,EAAE;YACP,IAAI,EAAE;gBACL,KAAK,EAAE,uBAAuB;gBAC9B,OAAO,EAAE,OAAO;aAChB;SACD;KACD,CAAC,CAAA;IAEC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,UAAU,EAAE;QAC1D,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,YAAY,EAAE,KAAK;KACtB,CAAC,CAAA;IAEF,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;IAEhC,OAAO,GAAG,CAAA;AACd,CAAC,CAAA"}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACnC,OAAO,EAAE,IAAI,EAAgB,MAAM,MAAM,CAAA;AACzC,OAAO,EAAE,SAAS,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,QAAQ,IAAI,UAAU,EAAE,SAAS,IAAI,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAKpC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAkB,EAAE,EAAE;IAC5C,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAA;IAEvB,qBAAqB;IACrB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QACpB,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,WAAW,EAAE,CAAA;QAC5B,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,8BAA8B,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;QAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;IACtG,CAAC,CAAC,CAAA;IAEF,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE;QAC7B,MAAM,EAAE;YACP,IAAI,EAAE;gBACL,KAAK,EAAE,uBAAuB;gBAC9B,OAAO,EAAE,OAAO;aAChB;SACD;KACD,CAAC,CAAA;IAEC,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,UAAU,EAAE;QAC1D,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,YAAY,EAAE,KAAK;KACtB,CAAC,CAAA;IAEF,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;IAChC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;IAEjC,OAAO,GAAG,CAAA;AACd,CAAC,CAAA"}
@@ -0,0 +1,93 @@
1
+ import { PublicKey } from "./keys.js";
2
+ import { type Signer } from "./signer.js";
3
+ /**
4
+ * Encoding, decoding and signing of OpenSSH certificates as described in
5
+ * PROTOCOL.certkeys from OpenSSH
6
+ */
7
+ /** Whether a certificate is for a user or a host */
8
+ export type CertificateKind = "user" | "host";
9
+ /** The fields of a certificate that are set by the CA */
10
+ export type CertificateFields = {
11
+ /** Whether the certificate is for a user or a host */
12
+ kind: CertificateKind;
13
+ /** The public key being certified */
14
+ publicKey: PublicKey;
15
+ /** The serial number of the certificate */
16
+ serial: bigint;
17
+ /** The key ID of the certificate, which is logged by sshd when it is used */
18
+ keyId: string;
19
+ /** The users or hosts the certificate is valid for */
20
+ principals: string[];
21
+ /** The time from which the certificate is valid, to the second */
22
+ validAfter: Date;
23
+ /** The time until which the certificate is valid, to the second */
24
+ validBefore: Date;
25
+ /** The names of the extensions to include, which have no data */
26
+ extensions: string[];
27
+ };
28
+ /**
29
+ * Thrown when a certificate cannot be parsed
30
+ */
31
+ export declare class CertificateParseError extends Error {
32
+ constructor(message: string, cause?: unknown);
33
+ }
34
+ /**
35
+ * A signed OpenSSH certificate
36
+ */
37
+ export declare class SshCertificate {
38
+ /** The wire encoding of the certificate */
39
+ readonly bytes: Uint8Array;
40
+ /** The certificate type, for example "ssh-ed25519-cert-v01@openssh.com" */
41
+ readonly type: string;
42
+ readonly kind: CertificateKind;
43
+ /** The public key being certified */
44
+ readonly publicKey: PublicKey;
45
+ readonly serial: bigint;
46
+ readonly keyId: string;
47
+ readonly principals: string[];
48
+ readonly validAfter: Date;
49
+ readonly validBefore: Date;
50
+ /** The names of the extensions on the certificate */
51
+ readonly extensions: string[];
52
+ /** The wire encoding of the public key of the CA that signed the certificate */
53
+ readonly signatureKey: Uint8Array;
54
+ /** The signature of the CA in the SSH wire format */
55
+ readonly signature: Uint8Array;
56
+ /**
57
+ * Decodes a certificate from its wire encoding. This does not verify the
58
+ * signature on the certificate.
59
+ *
60
+ * @param bytes The wire encoding of the certificate
61
+ * @throws {@link CertificateParseError} when the certificate cannot be decoded or its type is not supported
62
+ */
63
+ constructor(bytes: Uint8Array);
64
+ /**
65
+ * Parses a certificate in OpenSSH format, `${type} ${base64}[ ${comment}]`,
66
+ * as found in `-cert.pub` files. This does not verify the signature on the
67
+ * certificate.
68
+ *
69
+ * @param text The certificate
70
+ * @throws {@link CertificateParseError} when the certificate cannot be parsed or its type is not supported
71
+ */
72
+ static parse(text: string): SshCertificate;
73
+ /**
74
+ * Returns whether the certificate was signed by a CA key
75
+ *
76
+ * @param ca The public key of the CA
77
+ */
78
+ isSignedBy(ca: PublicKey): Promise<boolean>;
79
+ /**
80
+ * Returns the certificate in OpenSSH format, as used for `-cert.pub` files
81
+ */
82
+ toString(): string;
83
+ }
84
+ /**
85
+ * Creates and signs an OpenSSH certificate
86
+ *
87
+ * @param fields The fields of the certificate
88
+ * @param signer The CA key to sign the certificate with
89
+ * @returns The signed certificate
90
+ * @throws Error when the type of the public key being certified is not supported
91
+ */
92
+ export declare const signCertificate: (fields: CertificateFields, signer: Signer) => Promise<SshCertificate>;
93
+ //# sourceMappingURL=certificate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificate.d.ts","sourceRoot":"","sources":["../../src/ssh/certificate.ts"],"names":[],"mappings":"AAUA,OAAO,EAAiB,SAAS,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAEjD;;;GAGG;AAEH,oDAAoD;AACpD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,CAAA;AAO7C,yDAAyD;AACzD,MAAM,MAAM,iBAAiB,GAAG;IAC/B,sDAAsD;IACtD,IAAI,EAAE,eAAe,CAAA;IACrB,qCAAqC;IACrC,SAAS,EAAE,SAAS,CAAA;IACpB,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAA;IACd,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,kEAAkE;IAClE,UAAU,EAAE,IAAI,CAAA;IAChB,mEAAmE;IACnE,WAAW,EAAE,IAAI,CAAA;IACjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,EAAE,CAAA;CACpB,CAAA;AA+BD;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC/C,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAM3C;CACD;AAED;;GAEG;AACH,qBAAa,cAAc;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;IAC9B,qCAAqC;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAA;IAC7B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAA;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAA;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAA;IACjC,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAA;IAE9B;;;;;;OAMG;IACH,YAAY,KAAK,EAAE,UAAU,EA+B5B;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAmBzC;IAED;;;;OAIG;IACG,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAShD;IAED;;OAEG;IACH,QAAQ,IAAI,MAAM,CAEjB;CACD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,WAAkB,iBAAiB,UAAU,MAAM,KAAG,OAAO,CAAC,cAAc,CAuBvG,CAAA"}
@@ -0,0 +1,178 @@
1
+ import * as P from "micro-packed";
2
+ import { decodePublicKey, PublicKeyFieldCounts, SSHBytes, SSHOptions, SSHText, SSHTextList, } from "./encoding.js";
3
+ import { base64 } from "@scure/base";
4
+ import { KeyParseError, PublicKey } from "./keys.js";
5
+ import { verify } from "./signer.js";
6
+ const CertificateKinds = {
7
+ user: 1,
8
+ host: 2,
9
+ };
10
+ // the fields of a certificate that follow its type, which are given the
11
+ // number of fields in the public key of the certificate
12
+ const fields = (keyFields) => ({
13
+ nonce: SSHBytes,
14
+ key: P.array(keyFields, SSHBytes),
15
+ serial: P.U64BE,
16
+ kind: P.U32BE,
17
+ keyId: SSHText,
18
+ principals: SSHTextList,
19
+ validAfter: P.U64BE,
20
+ validBefore: P.U64BE,
21
+ criticalOptions: SSHOptions,
22
+ extensions: SSHOptions,
23
+ reserved: SSHBytes,
24
+ signatureKey: SSHBytes,
25
+ });
26
+ const certificateType = (keyType) => `${keyType}-cert-v01@openssh.com`;
27
+ // a certificate without and with its signature, tagged by the certificate type
28
+ const ToBeSigned = P.tag(SSHText, Object.fromEntries(Object.entries(PublicKeyFieldCounts).map(([keyType, count]) => [certificateType(keyType), P.struct(fields(count))])));
29
+ const Certificate = P.tag(SSHText, Object.fromEntries(Object.entries(PublicKeyFieldCounts).map(([keyType, count]) => [certificateType(keyType), P.struct({ ...fields(count), signature: SSHBytes })])));
30
+ const toSeconds = (date) => BigInt(Math.floor(date.getTime() / 1000));
31
+ /**
32
+ * Thrown when a certificate cannot be parsed
33
+ */
34
+ export class CertificateParseError extends Error {
35
+ constructor(message, cause) {
36
+ super(message);
37
+ this.name = "CertificateParseError";
38
+ this.cause = cause;
39
+ Object.setPrototypeOf(this, CertificateParseError.prototype);
40
+ }
41
+ }
42
+ /**
43
+ * A signed OpenSSH certificate
44
+ */
45
+ export class SshCertificate {
46
+ /** The wire encoding of the certificate */
47
+ bytes;
48
+ /** The certificate type, for example "ssh-ed25519-cert-v01@openssh.com" */
49
+ type;
50
+ kind;
51
+ /** The public key being certified */
52
+ publicKey;
53
+ serial;
54
+ keyId;
55
+ principals;
56
+ validAfter;
57
+ validBefore;
58
+ /** The names of the extensions on the certificate */
59
+ extensions;
60
+ /** The wire encoding of the public key of the CA that signed the certificate */
61
+ signatureKey;
62
+ /** The signature of the CA in the SSH wire format */
63
+ signature;
64
+ /**
65
+ * Decodes a certificate from its wire encoding. This does not verify the
66
+ * signature on the certificate.
67
+ *
68
+ * @param bytes The wire encoding of the certificate
69
+ * @throws {@link CertificateParseError} when the certificate cannot be decoded or its type is not supported
70
+ */
71
+ constructor(bytes) {
72
+ let decoded;
73
+ try {
74
+ decoded = Certificate.decode(bytes);
75
+ }
76
+ catch (err) {
77
+ throw new CertificateParseError("certificate could not be decoded", err);
78
+ }
79
+ const { TAG, data } = decoded;
80
+ const kind = Object.keys(CertificateKinds).find((k) => CertificateKinds[k] === data.kind);
81
+ if (kind === undefined) {
82
+ throw new CertificateParseError(`unknown certificate kind: ${data.kind}`);
83
+ }
84
+ const publicKeyType = TAG.replace(/-cert-v01@openssh\.com$/, "");
85
+ try {
86
+ this.publicKey = new PublicKey(P.struct({ type: SSHText, key: P.array(data.key.length, SSHBytes) }).encode({ type: publicKeyType, key: data.key }));
87
+ }
88
+ catch (err) {
89
+ throw new CertificateParseError(err instanceof KeyParseError ? err.message : "certificate public key could not be decoded", err);
90
+ }
91
+ this.bytes = bytes;
92
+ this.type = TAG;
93
+ this.kind = kind;
94
+ this.serial = data.serial;
95
+ this.keyId = data.keyId;
96
+ this.principals = data.principals;
97
+ this.validAfter = new Date(Number(data.validAfter) * 1000);
98
+ this.validBefore = new Date(Number(data.validBefore) * 1000);
99
+ this.extensions = data.extensions.map((e) => e.name);
100
+ this.signatureKey = data.signatureKey;
101
+ this.signature = data.signature;
102
+ }
103
+ /**
104
+ * Parses a certificate in OpenSSH format, `${type} ${base64}[ ${comment}]`,
105
+ * as found in `-cert.pub` files. This does not verify the signature on the
106
+ * certificate.
107
+ *
108
+ * @param text The certificate
109
+ * @throws {@link CertificateParseError} when the certificate cannot be parsed or its type is not supported
110
+ */
111
+ static parse(text) {
112
+ const [type, data] = text.trim().split(/\s+/);
113
+ if (type === undefined || type === "" || data === undefined) {
114
+ throw new CertificateParseError("certificate was not in OpenSSH format");
115
+ }
116
+ let bytes;
117
+ try {
118
+ bytes = base64.decode(data);
119
+ }
120
+ catch (err) {
121
+ throw new CertificateParseError("certificate was not valid base64", err);
122
+ }
123
+ const certificate = new SshCertificate(bytes);
124
+ if (certificate.type !== type) {
125
+ throw new CertificateParseError(`certificate type ${type} did not match encoded type ${certificate.type}`);
126
+ }
127
+ return certificate;
128
+ }
129
+ /**
130
+ * Returns whether the certificate was signed by a CA key
131
+ *
132
+ * @param ca The public key of the CA
133
+ */
134
+ async isSignedBy(ca) {
135
+ if (!ca.equals(new PublicKey(this.signatureKey))) {
136
+ return false;
137
+ }
138
+ // the signature is the last field, so everything before it is signed
139
+ const signed = this.bytes.subarray(0, this.bytes.length - 4 - this.signature.length);
140
+ return await verify(ca, this.signature, new Uint8Array(signed));
141
+ }
142
+ /**
143
+ * Returns the certificate in OpenSSH format, as used for `-cert.pub` files
144
+ */
145
+ toString() {
146
+ return `${this.type} ${base64.encode(this.bytes)}`;
147
+ }
148
+ }
149
+ /**
150
+ * Creates and signs an OpenSSH certificate
151
+ *
152
+ * @param fields The fields of the certificate
153
+ * @param signer The CA key to sign the certificate with
154
+ * @returns The signed certificate
155
+ * @throws Error when the type of the public key being certified is not supported
156
+ */
157
+ export const signCertificate = async (fields, signer) => {
158
+ const { type, fields: key } = decodePublicKey(fields.publicKey.blob);
159
+ const value = {
160
+ nonce: crypto.getRandomValues(new Uint8Array(32)),
161
+ key,
162
+ serial: fields.serial,
163
+ kind: CertificateKinds[fields.kind],
164
+ keyId: fields.keyId,
165
+ principals: fields.principals,
166
+ validAfter: toSeconds(fields.validAfter),
167
+ validBefore: toSeconds(fields.validBefore),
168
+ criticalOptions: [],
169
+ // options must be in lexical order and may each appear only once
170
+ extensions: [...new Set(fields.extensions)].sort().map((name) => ({ name, data: new Uint8Array(0) })),
171
+ reserved: new Uint8Array(0),
172
+ signatureKey: signer.publicKey,
173
+ };
174
+ const tbs = ToBeSigned.encode({ TAG: certificateType(type), data: value });
175
+ const signature = await signer.sign(new Uint8Array(tbs));
176
+ return new SshCertificate(Certificate.encode({ TAG: certificateType(type), data: { ...value, signature } }));
177
+ };
178
+ //# sourceMappingURL=certificate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certificate.js","sourceRoot":"","sources":["../../src/ssh/certificate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import * as P from "micro-packed";
2
+ /**
3
+ * Coders for the SSH wire format (RFC 4251 section 5)
4
+ */
5
+ /** A string of bytes, prefixed by its length as a uint32 */
6
+ export declare const SSHBytes: P.CoderType<P.Bytes>;
7
+ /** A UTF-8 string, prefixed by its length as a uint32 */
8
+ export declare const SSHText: P.CoderType<string>;
9
+ /** A list of strings packed into a string, as used for certificate principals */
10
+ export declare const SSHTextList: P.CoderType<string[]>;
11
+ /**
12
+ * A list of named options packed into a string, as used for certificate
13
+ * critical options and extensions
14
+ */
15
+ export declare const SSHOptions: P.CoderType<P.StructInput<{
16
+ name: string;
17
+ data: P.Bytes;
18
+ }>[]>;
19
+ /**
20
+ * An mpint holding an unsigned integer, decoded to and encoded from its
21
+ * big-endian bytes without leading zeros.
22
+ *
23
+ * An mpint has no leading zero bytes, other than one to keep the value
24
+ * positive when the high bit of the first byte is set.
25
+ */
26
+ export declare const SSHUnsignedMpint: P.CoderType<Uint8Array<ArrayBufferLike>>;
27
+ /** The number of fields that follow the type in the wire encoding of a public key of each type */
28
+ export declare const PublicKeyFieldCounts: Readonly<Record<string, number>>;
29
+ /**
30
+ * Splits the wire encoding of a public key into its type and the encoded
31
+ * fields that follow it
32
+ *
33
+ * @param blob The wire encoding of the public key
34
+ * @returns The key type and its fields
35
+ * @throws Error when the key type is not supported or the encoding is invalid
36
+ */
37
+ export declare const decodePublicKey: (blob: Uint8Array) => {
38
+ type: string;
39
+ fields: Uint8Array[];
40
+ };
41
+ //# sourceMappingURL=encoding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../../src/ssh/encoding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AAEjC;;GAEG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,QAAQ,sBAAmB,CAAA;AAExC,yDAAyD;AACzD,eAAO,MAAM,OAAO,qBAAoB,CAAA;AAExC,iFAAiF;AACjF,eAAO,MAAM,WAAW,uBAA4C,CAAA;AAEpE;;;GAGG;AACH,eAAO,MAAM,UAAU;;;KAGnB,CAAA;AAEJ;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,0CAoB3B,CAAA;AAEF,kGAAkG;AAClG,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMjE,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,SAAU,UAAU,KAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAUtF,CAAA"}