@e-sig/core 0.4.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 (52) hide show
  1. package/CONSUMING.md +97 -0
  2. package/LICENSE +21 -0
  3. package/README.md +298 -0
  4. package/dist/adapters.d.ts +79 -0
  5. package/dist/adapters.d.ts.map +1 -0
  6. package/dist/adapters.js +10 -0
  7. package/dist/adapters.js.map +1 -0
  8. package/dist/cert-issuer.d.ts +47 -0
  9. package/dist/cert-issuer.d.ts.map +1 -0
  10. package/dist/cert-issuer.js +132 -0
  11. package/dist/cert-issuer.js.map +1 -0
  12. package/dist/cert-lifecycle.d.ts +16 -0
  13. package/dist/cert-lifecycle.d.ts.map +1 -0
  14. package/dist/cert-lifecycle.js +30 -0
  15. package/dist/cert-lifecycle.js.map +1 -0
  16. package/dist/index.d.ts +11 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +21 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/pem-signer.d.ts +42 -0
  21. package/dist/pem-signer.d.ts.map +1 -0
  22. package/dist/pem-signer.js +276 -0
  23. package/dist/pem-signer.js.map +1 -0
  24. package/dist/render-pdf.d.ts +33 -0
  25. package/dist/render-pdf.d.ts.map +1 -0
  26. package/dist/render-pdf.js +86 -0
  27. package/dist/render-pdf.js.map +1 -0
  28. package/dist/sign-document.d.ts +54 -0
  29. package/dist/sign-document.d.ts.map +1 -0
  30. package/dist/sign-document.js +93 -0
  31. package/dist/sign-document.js.map +1 -0
  32. package/dist/sign-pdf.d.ts +46 -0
  33. package/dist/sign-pdf.d.ts.map +1 -0
  34. package/dist/sign-pdf.js +60 -0
  35. package/dist/sign-pdf.js.map +1 -0
  36. package/dist/signature-block.d.ts +23 -0
  37. package/dist/signature-block.d.ts.map +1 -0
  38. package/dist/signature-block.js +63 -0
  39. package/dist/signature-block.js.map +1 -0
  40. package/dist/timestamp.d.ts +59 -0
  41. package/dist/timestamp.d.ts.map +1 -0
  42. package/dist/timestamp.js +278 -0
  43. package/dist/timestamp.js.map +1 -0
  44. package/dist/types.d.ts +44 -0
  45. package/dist/types.d.ts.map +1 -0
  46. package/dist/types.js +10 -0
  47. package/dist/types.js.map +1 -0
  48. package/dist/verify-pdf.d.ts +33 -0
  49. package/dist/verify-pdf.d.ts.map +1 -0
  50. package/dist/verify-pdf.js +338 -0
  51. package/dist/verify-pdf.js.map +1 -0
  52. package/package.json +92 -0
@@ -0,0 +1,278 @@
1
+ // src/lib/integrations/esig/core/timestamp.ts
2
+ //
3
+ // RFC 3161 Time-Stamp Protocol (TSP) primitives — pure node-forge, dep-free.
4
+ //
5
+ // Implements the minimum needed to upgrade a CAdES-B signature to CAdES-T by
6
+ // embedding an RFC 3161 TimeStampToken (TST) as an UNSIGNED attribute
7
+ // (id-aa-timeStampToken, OID 1.2.840.113549.1.9.16.2.14) inside the PKCS#7
8
+ // SignerInfo. The timestamp is computed over the SignerInfo signatureValue
9
+ // (encryptedDigest) per RFC 3161 §2.4.1.
10
+ //
11
+ // The actual network POST to the TSA is injected by the caller (see
12
+ // TsaTransport in ./types) so this package never performs egress itself — the
13
+ // TSA only ever receives a SHA-256 hash, never any PHI.
14
+ import forge from "node-forge";
15
+ const asn1 = forge.asn1;
16
+ /** OID for the id-aa-timeStampToken unsigned attribute (RFC 3161). */
17
+ export const OID_TIMESTAMP_TOKEN = "1.2.840.113549.1.9.16.2.14";
18
+ const OID_SHA256 = "2.16.840.1.101.3.4.2.1";
19
+ const OID_TST_INFO = "1.2.840.113549.1.9.16.1.4"; // id-ct-TSTInfo
20
+ const OID_SIGNED_DATA = "1.2.840.113549.1.7.2"; // id-signedData
21
+ const OID_COMMON_NAME = "2.5.4.3"; // id-at-commonName
22
+ /** Convert a forge binary string (DER) to a Uint8Array. */
23
+ export function derStringToUint8(der) {
24
+ const out = new Uint8Array(der.length);
25
+ for (let i = 0; i < der.length; i++)
26
+ out[i] = der.charCodeAt(i) & 0xff;
27
+ return out;
28
+ }
29
+ /** Convert a Uint8Array to a forge binary string (DER). */
30
+ export function uint8ToDerString(bytes) {
31
+ let s = "";
32
+ // Chunk to avoid String.fromCharCode argument-count limits on large inputs.
33
+ const CHUNK = 0x8000;
34
+ for (let i = 0; i < bytes.length; i += CHUNK) {
35
+ s += String.fromCharCode.apply(null, bytes.subarray(i, i + CHUNK));
36
+ }
37
+ return s;
38
+ }
39
+ /**
40
+ * Build an RFC 3161 TimeStampReq (DER, forge binary string) over the given
41
+ * signatureValue bytes.
42
+ *
43
+ * TimeStampReq ::= SEQUENCE {
44
+ * version INTEGER { v1(1) },
45
+ * messageImprint MessageImprint,
46
+ * reqPolicy TSAPolicyId OPTIONAL, -- omitted
47
+ * nonce INTEGER OPTIONAL,
48
+ * certReq BOOLEAN DEFAULT FALSE }
49
+ *
50
+ * MessageImprint ::= SEQUENCE {
51
+ * hashAlgorithm AlgorithmIdentifier,
52
+ * hashedMessage OCTET STRING }
53
+ *
54
+ * The messageImprint hash input is the RAW signatureValue bytes (a forge
55
+ * binary string), hashed with SHA-256.
56
+ */
57
+ export function buildTimeStampReq(sigValueBinary) {
58
+ const md = forge.md.sha256.create();
59
+ md.update(sigValueBinary);
60
+ const hashed = md.digest().getBytes(); // forge binary string
61
+ // AlgorithmIdentifier ::= SEQUENCE { OID sha256, NULL }
62
+ const hashAlgorithm = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
63
+ asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OID, false, asn1.oidToDer(OID_SHA256).getBytes()),
64
+ asn1.create(asn1.Class.UNIVERSAL, asn1.Type.NULL, false, ""),
65
+ ]);
66
+ // MessageImprint ::= SEQUENCE { hashAlgorithm, hashedMessage OCTET STRING }
67
+ const messageImprint = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
68
+ hashAlgorithm,
69
+ asn1.create(asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, hashed),
70
+ ]);
71
+ // version INTEGER (1)
72
+ const version = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, asn1.integerToDer(1).getBytes());
73
+ // nonce INTEGER (16 random bytes; prepend 0x00 if the high bit is set so the
74
+ // value is interpreted as a positive integer).
75
+ let nonceBytes = forge.random.getBytesSync(16);
76
+ if ((nonceBytes.charCodeAt(0) & 0x80) !== 0) {
77
+ nonceBytes = "\x00" + nonceBytes;
78
+ }
79
+ const nonce = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.INTEGER, false, nonceBytes);
80
+ // certReq BOOLEAN TRUE
81
+ const certReq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.BOOLEAN, false, String.fromCharCode(0xff));
82
+ const req = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, [
83
+ version,
84
+ messageImprint,
85
+ nonce,
86
+ certReq,
87
+ ]);
88
+ return asn1.toDer(req).getBytes();
89
+ }
90
+ /**
91
+ * Parse an RFC 3161 TimeStampResp (DER forge binary string) and return the
92
+ * embedded TimeStampToken as a forge ASN.1 object.
93
+ *
94
+ * TimeStampResp ::= SEQUENCE {
95
+ * status PKIStatusInfo,
96
+ * timeStampToken TimeStampToken OPTIONAL }
97
+ *
98
+ * PKIStatusInfo ::= SEQUENCE {
99
+ * status PKIStatus (INTEGER),
100
+ * statusString PKIFreeText OPTIONAL,
101
+ * failInfo PKIFailureInfo OPTIONAL }
102
+ *
103
+ * Accepts status 0 (granted) or 1 (grantedWithMods); throws otherwise, with the
104
+ * integer status and (if present) failInfo bits.
105
+ */
106
+ export function parseTimeStampResp(respBinary) {
107
+ const resp = asn1.fromDer(respBinary);
108
+ if (!Array.isArray(resp.value) || resp.value.length < 1) {
109
+ throw new Error("RFC3161: malformed TimeStampResp (no PKIStatusInfo)");
110
+ }
111
+ const statusInfo = resp.value[0];
112
+ if (!Array.isArray(statusInfo.value) || statusInfo.value.length < 1) {
113
+ throw new Error("RFC3161: malformed PKIStatusInfo");
114
+ }
115
+ const statusNode = statusInfo.value[0];
116
+ const status = derIntToNumber(statusNode.value);
117
+ if (status !== 0 && status !== 1) {
118
+ // Best-effort failInfo (BIT STRING) for diagnostics.
119
+ let failInfo = "";
120
+ for (const child of statusInfo.value) {
121
+ if (child.type === asn1.Type.BITSTRING && typeof child.value === "string") {
122
+ failInfo = ` failInfo=0x${forge.util.bytesToHex(child.value)}`;
123
+ break;
124
+ }
125
+ }
126
+ throw new Error(`RFC3161: TSA rejected request (PKIStatus=${status})${failInfo}`);
127
+ }
128
+ const token = resp.value[1];
129
+ if (!token) {
130
+ throw new Error("RFC3161: TimeStampResp granted but no timeStampToken present");
131
+ }
132
+ return { token };
133
+ }
134
+ /**
135
+ * Parse a TimeStampToken (a CMS SignedData ContentInfo whose eContentType is
136
+ * id-ct-TSTInfo) and extract best-effort metadata. Only
137
+ * `messageImprintHashHex` is treated as load-bearing (used by the verifier's
138
+ * §2.4.2 binding check); the rest are returned as undefined on any parse miss
139
+ * rather than throwing.
140
+ */
141
+ export function parseTstInfo(tokenAsn1) {
142
+ const result = {};
143
+ try {
144
+ if (!Array.isArray(tokenAsn1.value))
145
+ return result;
146
+ // ContentInfo ::= SEQUENCE { contentType OID, content [0] EXPLICIT SignedData }
147
+ let signedData;
148
+ for (const child of tokenAsn1.value) {
149
+ if (child.type === asn1.Type.OID &&
150
+ safeOid(child.value) === OID_SIGNED_DATA) {
151
+ continue;
152
+ }
153
+ if (child.tagClass === asn1.Class.CONTEXT_SPECIFIC && Array.isArray(child.value)) {
154
+ signedData = child.value[0];
155
+ }
156
+ }
157
+ if (!signedData || !Array.isArray(signedData.value))
158
+ return result;
159
+ // SignedData -> EncapsulatedContentInfo ::= SEQUENCE {
160
+ // eContentType OID (== id-ct-TSTInfo),
161
+ // eContent [0] EXPLICIT OCTET STRING OPTIONAL }
162
+ let tstInfoBytes;
163
+ for (const sdChild of signedData.value) {
164
+ if (sdChild.type !== asn1.Type.SEQUENCE || !Array.isArray(sdChild.value))
165
+ continue;
166
+ const seq = sdChild.value;
167
+ const first = seq[0];
168
+ if (first &&
169
+ first.type === asn1.Type.OID &&
170
+ safeOid(first.value) === OID_TST_INFO) {
171
+ const explicit = seq[1];
172
+ if (explicit && Array.isArray(explicit.value)) {
173
+ const oct = explicit.value[0];
174
+ if (oct && oct.type === asn1.Type.OCTETSTRING) {
175
+ if (typeof oct.value === "string") {
176
+ tstInfoBytes = oct.value;
177
+ }
178
+ else if (Array.isArray(oct.value) && oct.value.length > 0) {
179
+ // Constructed/definite OCTET STRING wrapper.
180
+ tstInfoBytes = oct.value[0].value;
181
+ }
182
+ }
183
+ }
184
+ break;
185
+ }
186
+ }
187
+ if (!tstInfoBytes)
188
+ return result;
189
+ // TSTInfo ::= SEQUENCE {
190
+ // version INTEGER, policy OID, messageImprint MessageImprint,
191
+ // serialNumber INTEGER, genTime GeneralizedTime, ... }
192
+ const tstInfo = asn1.fromDer(tstInfoBytes);
193
+ if (!Array.isArray(tstInfo.value))
194
+ return result;
195
+ const fields = tstInfo.value;
196
+ // messageImprint is the first SEQUENCE child; its last element is the
197
+ // hashedMessage OCTET STRING.
198
+ for (const f of fields) {
199
+ if (f.type === asn1.Type.SEQUENCE && Array.isArray(f.value)) {
200
+ const mi = f.value;
201
+ const hashed = mi[mi.length - 1];
202
+ if (hashed && hashed.type === asn1.Type.OCTETSTRING && typeof hashed.value === "string") {
203
+ result.messageImprintHashHex = forge.util.bytesToHex(hashed.value);
204
+ break;
205
+ }
206
+ }
207
+ }
208
+ // genTime GeneralizedTime.
209
+ for (const f of fields) {
210
+ if (f.type === asn1.Type.GENERALIZEDTIME && typeof f.value === "string") {
211
+ result.genTime = f.value;
212
+ }
213
+ }
214
+ // serialNumber heuristic: among the INTEGER fields (version + serialNumber),
215
+ // serialNumber is the larger-byte one.
216
+ let bestSerial;
217
+ let bestLen = 0;
218
+ for (const f of fields) {
219
+ if (f.type === asn1.Type.INTEGER && typeof f.value === "string" && f.value.length > bestLen) {
220
+ bestLen = f.value.length;
221
+ bestSerial = f.value;
222
+ }
223
+ }
224
+ if (bestSerial)
225
+ result.serialHex = forge.util.bytesToHex(bestSerial);
226
+ // TSA common name: best-effort from the signer certificate(s).
227
+ result.tsaCommonName = extractFirstCommonName(signedData);
228
+ }
229
+ catch {
230
+ // Best-effort: swallow parse errors, returning whatever we have.
231
+ }
232
+ return result;
233
+ }
234
+ /** Best-effort scan for the first commonName (OID 2.5.4.3) string value. */
235
+ function extractFirstCommonName(node) {
236
+ let found;
237
+ const walk = (n) => {
238
+ if (found)
239
+ return;
240
+ if (!Array.isArray(n.value))
241
+ return;
242
+ const children = n.value;
243
+ for (let i = 0; i < children.length; i++) {
244
+ const c = children[i];
245
+ if (c.type === asn1.Type.OID &&
246
+ typeof c.value === "string" &&
247
+ safeOid(c.value) === OID_COMMON_NAME &&
248
+ i + 1 < children.length) {
249
+ const v = children[i + 1];
250
+ if (typeof v.value === "string" && v.value.length > 0) {
251
+ found = v.value;
252
+ return;
253
+ }
254
+ }
255
+ }
256
+ for (const c of children)
257
+ walk(c);
258
+ };
259
+ walk(node);
260
+ return found;
261
+ }
262
+ function safeOid(der) {
263
+ try {
264
+ return asn1.derToOid(der);
265
+ }
266
+ catch {
267
+ return "";
268
+ }
269
+ }
270
+ /** Decode a DER INTEGER content (forge binary string) to a JS number. */
271
+ function derIntToNumber(bytes) {
272
+ let n = 0;
273
+ for (let i = 0; i < bytes.length; i++) {
274
+ n = n * 256 + (bytes.charCodeAt(i) & 0xff);
275
+ }
276
+ return n;
277
+ }
278
+ //# sourceMappingURL=timestamp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timestamp.js","sourceRoot":"","sources":["../src/timestamp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export interface Signer {
2
+ /** Display name shown to humans (PDF visible signature block + cert binding). */
3
+ name: string;
4
+ /** Email — embedded in PKCS#7 contactInfo. ASCII recommended. */
5
+ email: string;
6
+ }
7
+ export interface SigningCertPem {
8
+ /** PEM-encoded RSA private key. */
9
+ keyPem: string;
10
+ /** PEM-encoded X.509 certificate. */
11
+ certPem: string;
12
+ /** SHA-256 hex digest of the DER-encoded cert (for audit attribution). */
13
+ fingerprint: string;
14
+ }
15
+ export interface SignedPdfMetadata {
16
+ /** Why the doc was signed — embedded in PDF signature dictionary. */
17
+ reason: string;
18
+ /** Geographic or URL context — embedded in PDF signature dictionary. */
19
+ location: string;
20
+ /** Signer's primary contact — embedded in PDF signature dictionary. */
21
+ contactInfo: string;
22
+ /** Signer's display name — embedded in PDF signature dictionary. */
23
+ name: string;
24
+ /** When the signature was applied. Defaults to now. */
25
+ signingTime?: Date;
26
+ }
27
+ /**
28
+ * Caller-injected RFC 3161 timestamp transport.
29
+ *
30
+ * The consumer supplies the network POST so this package stays dependency-free
31
+ * and performs no egress itself. `fetch` receives the DER-encoded TimeStampReq
32
+ * bytes and MUST return the raw DER-encoded TimeStampResp bytes. The TSA only
33
+ * ever sees a SHA-256 hash — never PHI.
34
+ */
35
+ export interface TsaTransport {
36
+ /** POST the TimeStampReq DER to the TSA and return the TimeStampResp DER. */
37
+ fetch: (reqDerBytes: Uint8Array) => Promise<Uint8Array>;
38
+ /**
39
+ * When true, a TSA failure aborts signing (throws). When false/omitted, a
40
+ * failure degrades gracefully to a plain CAdES-B signature.
41
+ */
42
+ required?: boolean;
43
+ }
44
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,MAAM;IACrB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,CAAC,EAAE,IAAI,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,KAAK,EAAE,CAAC,WAAW,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACxD;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB"}
package/dist/types.js ADDED
@@ -0,0 +1,10 @@
1
+ // src/lib/integrations/esig/core/types.ts
2
+ //
3
+ // Phase 21 — public types for the portable e-sig core.
4
+ //
5
+ // The `core/` module is project-agnostic: pure crypto + rendering + PDF
6
+ // structural verification. Database, Storage, and Auth concerns live in
7
+ // `adapters/` (the current Supabase implementation) or in whatever you
8
+ // supply when porting to another project.
9
+ export {};
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,uDAAuD;AACvD,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,uEAAuE;AACvE,0CAA0C"}
@@ -0,0 +1,33 @@
1
+ export interface VerifyResult {
2
+ ok: boolean;
3
+ byteRange?: [number, number, number, number];
4
+ pkcs7ActualSize?: number;
5
+ pkcs7BudgetSize?: number;
6
+ signerCommonName?: string;
7
+ signerOrganization?: string;
8
+ /**
9
+ * True when SHA-256 over the ByteRange-covered bytes equals the messageDigest
10
+ * signed attribute (the document has not been altered under the signature).
11
+ */
12
+ digestValid?: boolean;
13
+ /**
14
+ * True when the RSA signature over the signed attributes verifies against the
15
+ * embedded signer certificate's public key.
16
+ */
17
+ signatureValid?: boolean;
18
+ /** True if an RFC 3161 TimeStampToken (CAdES-T) is embedded. */
19
+ timestamped: boolean;
20
+ /** ISO genTime of the timestamp, if parseable. */
21
+ timestampTime?: string;
22
+ /** Common name of the TSA signer cert, if parseable. */
23
+ tsaCommonName?: string;
24
+ failures: string[];
25
+ }
26
+ export declare function verifyPdfStructure(signed: Buffer): VerifyResult;
27
+ /**
28
+ * Preferred name for {@link verifyPdfStructure}. Performs full cryptographic
29
+ * verification (structure + digest + signature); `ok:true` means the signature
30
+ * is valid over the exact document bytes.
31
+ */
32
+ export declare const verifyPdfSignature: typeof verifyPdfStructure;
33
+ //# sourceMappingURL=verify-pdf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-pdf.d.ts","sourceRoot":"","sources":["../src/verify-pdf.ts"],"names":[],"mappings":"AAyCA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gEAAgE;IAChE,WAAW,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CA4E/D;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,2BAAqB,CAAC"}