@raytio/core 11.5.0 → 11.7.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 +1708 -217
- package/dist/accessApplication/api/legacy/convertRelationships.d.ts +3 -5
- package/dist/accessApplication/api/legacy/convertRelationships.js +3 -3
- package/dist/crypto/cognitoAttributes.d.ts +3 -0
- package/dist/crypto/cognitoAttributes.js +15 -4
- package/dist/crypto/getAADecryptor.d.ts +1 -1
- package/dist/crypto/getAADecryptor.js +1 -3
- package/dist/crypto/index.d.ts +3 -0
- package/dist/crypto/index.js +6 -0
- package/dist/crypto/kdf/argon2.d.ts +67 -0
- package/dist/crypto/kdf/argon2.js +99 -0
- package/dist/crypto/kdf/index.d.ts +43 -0
- package/dist/crypto/kdf/index.js +106 -0
- package/dist/crypto/kdf/pbkdf2.d.ts +16 -0
- package/dist/crypto/kdf/pbkdf2.js +45 -0
- package/dist/crypto/kdf/twoSecretKdf.d.ts +37 -0
- package/dist/crypto/kdf/twoSecretKdf.js +66 -0
- package/dist/crypto/kdf/types.d.ts +65 -0
- package/dist/crypto/kdf/types.js +50 -0
- package/dist/crypto/kdf/utils.d.ts +59 -0
- package/dist/crypto/kdf/utils.js +110 -0
- package/dist/crypto/localSecret/format.d.ts +48 -0
- package/dist/crypto/localSecret/format.js +157 -0
- package/dist/crypto/localSecret/generator.d.ts +23 -0
- package/dist/crypto/localSecret/generator.js +53 -0
- package/dist/crypto/localSecret/index.d.ts +12 -0
- package/dist/crypto/localSecret/index.js +46 -0
- package/dist/crypto/localSecret/storage.d.ts +53 -0
- package/dist/crypto/localSecret/storage.js +207 -0
- package/dist/crypto/localSecret/types.d.ts +68 -0
- package/dist/crypto/localSecret/types.js +31 -0
- package/dist/crypto/pgpKey/encryption.d.ts +49 -0
- package/dist/crypto/pgpKey/encryption.js +104 -0
- package/dist/crypto/pgpKey/export.d.ts +59 -0
- package/dist/crypto/pgpKey/export.js +322 -0
- package/dist/crypto/pgpKey/format.d.ts +61 -0
- package/dist/crypto/pgpKey/format.js +143 -0
- package/dist/crypto/pgpKey/generator.d.ts +20 -0
- package/dist/crypto/pgpKey/generator.js +76 -0
- package/dist/crypto/pgpKey/import.d.ts +69 -0
- package/dist/crypto/pgpKey/import.js +239 -0
- package/dist/crypto/pgpKey/index.d.ts +19 -0
- package/dist/crypto/pgpKey/index.js +67 -0
- package/dist/crypto/pgpKey/signing.d.ts +44 -0
- package/dist/crypto/pgpKey/signing.js +71 -0
- package/dist/crypto/pgpKey/storage.d.ts +43 -0
- package/dist/crypto/pgpKey/storage.js +141 -0
- package/dist/crypto/pgpKey/types.d.ts +86 -0
- package/dist/crypto/pgpKey/types.js +25 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/rules/calculateScore.d.ts +1 -1
- package/dist/rules/convertInstanceToRuleInput.js +99 -97
- package/dist/rules/evaluateBadge.d.ts +36 -0
- package/dist/rules/evaluateBadge.js +36 -0
- package/dist/rules/index.d.ts +1 -0
- package/dist/rules/index.js +1 -0
- package/dist/rules/types/config.d.ts +1 -1
- package/dist/rules/types/dataValueTypes.d.ts +4 -4
- package/dist/schema/expandSchema/constants.js +1 -1
- package/dist/schema/expandSchema/expandSchema.d.ts +3 -3
- package/dist/schema/expandSchema/expandSchema.js +4 -4
- package/dist/schema/expandSchema/i18n.d.ts +6 -1
- package/dist/schema/expandSchema/i18n.js +32 -4
- package/dist/schema/expandSchema/maybeUseI18n.d.ts +2 -2
- package/dist/schema/expandSchema/maybeUseI18n.js +68 -11
- package/dist/schema/expandSchema/processSchema.js +14 -5
- package/dist/schema/expandSchema/removePrivateFields.d.ts +75 -22
- package/dist/schema/expandSchema/sortSchemaProperties.d.ts +4 -1
- package/dist/schema/expandSchema/sortSchemaProperties.js +24 -1
- package/dist/schema/labels.js +1 -2
- package/dist/util/canonicalJsonify.d.ts +7 -1
- package/dist/util/canonicalJsonify.js +3 -2
- package/dist/verifications/safeHarbour.js +5 -0
- package/dist/verifications/verifyCheck/getOwnRealVerifications.js +2 -0
- package/package.json +6 -4
- package/dist/__tests__/docs.test.d.ts +0 -1
- package/dist/__tests__/docs.test.js +0 -24
- package/dist/accessApplication/api/__tests__/fetchKeysForSubmission.test.d.ts +0 -1
- package/dist/accessApplication/api/__tests__/fetchKeysForSubmission.test.js +0 -28
- package/dist/accessApplication/api/__tests__/fetchPOsOrAOsForSubmission.test.d.ts +0 -1
- package/dist/accessApplication/api/__tests__/fetchPOsOrAOsForSubmission.test.js +0 -23
- package/dist/accessApplication/api/__tests__/fetchRelationshipsForSubmission.test.d.ts +0 -1
- package/dist/accessApplication/api/__tests__/fetchRelationshipsForSubmission.test.js +0 -27
- package/dist/accessApplication/api/__tests__/getMissingDataForInstance.test.d.ts +0 -1
- package/dist/accessApplication/api/__tests__/getMissingDataForInstance.test.js +0 -30
- package/dist/accessApplication/api/legacy/__tests__/convertRelationships.test.d.ts +0 -1
- package/dist/accessApplication/api/legacy/__tests__/convertRelationships.test.js +0 -37
- package/dist/rules/helpers/__tests__/addInfiniteThresholdBoundaries.test.d.ts +0 -1
- package/dist/rules/helpers/__tests__/addInfiniteThresholdBoundaries.test.js +0 -27
- package/dist/rules/helpers/__tests__/checkTypeofValue.test.d.ts +0 -1
- package/dist/rules/helpers/__tests__/checkTypeofValue.test.js +0 -49
- package/dist/rules/helpers/__tests__/getValuesFromPath.test.d.ts +0 -1
- package/dist/rules/helpers/__tests__/getValuesFromPath.test.js +0 -67
- package/dist/rules/helpers/__tests__/thresholds.test.d.ts +0 -1
- package/dist/rules/helpers/__tests__/thresholds.test.js +0 -32
- package/dist/rules/operators/__tests__/bool.test.d.ts +0 -1
- package/dist/rules/operators/__tests__/bool.test.js +0 -21
- package/dist/rules/operators/__tests__/date.test.d.ts +0 -1
- package/dist/rules/operators/__tests__/date.test.js +0 -81
- package/dist/rules/operators/__tests__/hfield.test.d.ts +0 -1
- package/dist/rules/operators/__tests__/hfield.test.js +0 -38
- package/dist/rules/operators/__tests__/hschema.test.d.ts +0 -1
- package/dist/rules/operators/__tests__/hschema.test.js +0 -24
- package/dist/rules/operators/__tests__/number.test.d.ts +0 -1
- package/dist/rules/operators/__tests__/number.test.js +0 -53
- package/dist/rules/operators/__tests__/string.test.d.ts +0 -1
- package/dist/rules/operators/__tests__/string.test.js +0 -74
- package/dist/schema/expandSchema/__tests__/addLoadingTimes.test.d.ts +0 -1
- package/dist/schema/expandSchema/__tests__/addLoadingTimes.test.js +0 -24
- package/dist/schema/expandSchema/__tests__/expandSchema.test.d.ts +0 -1
- package/dist/schema/expandSchema/__tests__/expandSchema.test.js +0 -96
- package/dist/schema/expandSchema/__tests__/i18n.test.d.ts +0 -1
- package/dist/schema/expandSchema/__tests__/i18n.test.js +0 -32
- package/dist/schema/expandSchema/__tests__/maybeUseI18n.test.d.ts +0 -1
- package/dist/schema/expandSchema/__tests__/maybeUseI18n.test.js +0 -98
- package/dist/schema/expandSchema/__tests__/processSchema.test.d.ts +0 -1
- package/dist/schema/expandSchema/__tests__/processSchema.test.js +0 -326
- package/dist/schema/expandSchema/__tests__/sortSchemaProperties.test.d.ts +0 -1
- package/dist/schema/expandSchema/__tests__/sortSchemaProperties.test.js +0 -182
- package/dist/schema/expandSchema/__tests__/util.test.d.ts +0 -1
- package/dist/schema/expandSchema/__tests__/util.test.js +0 -19
- package/dist/verifications/cleanInstance.d.ts +0 -9
- package/dist/verifications/cleanInstance.js +0 -15
- package/dist/verifications/verifyCheck/__tests__/getOwnRealVerifications.test.d.ts +0 -1
- package/dist/verifications/verifyCheck/__tests__/getOwnRealVerifications.test.js +0 -221
- package/dist/verifications/verifyCheck/__tests__/getSomeoneElsesRealVerifications.test.d.ts +0 -1
- package/dist/verifications/verifyCheck/__tests__/getSomeoneElsesRealVerifications.test.js +0 -206
- package/dist/verifications/verifyCheck/operations/__tests__/checkOwnVerification.test.d.ts +0 -1
- package/dist/verifications/verifyCheck/operations/__tests__/checkOwnVerification.test.js +0 -138
- package/dist/verifications/verifyCheck/operations/__tests__/checkSomeoneElsesVerifications.test.d.ts +0 -1
- package/dist/verifications/verifyCheck/operations/__tests__/checkSomeoneElsesVerifications.test.js +0 -49
- package/dist/verifications/verifyCheck/operations/__tests__/sampleBundle.json +0 -44
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PGP Key Import Parser
|
|
4
|
+
*
|
|
5
|
+
* Parse and validate armored PGP private keys for import.
|
|
6
|
+
* Converts to PKCS8 format compatible with Web Crypto API.
|
|
7
|
+
*
|
|
8
|
+
* Issue #1374
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
27
|
+
if (mod && mod.__esModule) return mod;
|
|
28
|
+
var result = {};
|
|
29
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
30
|
+
__setModuleDefault(result, mod);
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
33
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
+
exports.PGPKeyImportError = void 0;
|
|
35
|
+
exports.isArmoredPGPKey = isArmoredPGPKey;
|
|
36
|
+
exports.parseArmoredPGPKey = parseArmoredPGPKey;
|
|
37
|
+
exports.validateImportedKey = validateImportedKey;
|
|
38
|
+
const utils_1 = require("../kdf/utils");
|
|
39
|
+
const generator_1 = require("./generator");
|
|
40
|
+
/**
|
|
41
|
+
* Error thrown when key import fails
|
|
42
|
+
*/
|
|
43
|
+
// eslint-disable-next-line fp/no-class -- Custom error class for specific error handling
|
|
44
|
+
class PGPKeyImportError extends Error {
|
|
45
|
+
constructor(message, code) {
|
|
46
|
+
super(message);
|
|
47
|
+
// eslint-disable-next-line fp/no-this, fp/no-mutation -- Required for Error subclassing
|
|
48
|
+
this.name = "PGPKeyImportError";
|
|
49
|
+
// eslint-disable-next-line fp/no-this, fp/no-mutation -- Required for Error subclassing
|
|
50
|
+
this.code = code;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.PGPKeyImportError = PGPKeyImportError;
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// Helper functions (defined first to avoid use-before-define errors)
|
|
56
|
+
// ============================================================================
|
|
57
|
+
/**
|
|
58
|
+
* Convert Uint8Array to base64url encoding (for JWK)
|
|
59
|
+
*/
|
|
60
|
+
function uint8ArrayToBase64Url(bytes) {
|
|
61
|
+
const base64 = (0, utils_1.uint8ArrayToBase64)(bytes);
|
|
62
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Convert BigInt from Uint8Array (big-endian)
|
|
66
|
+
*/
|
|
67
|
+
function bigIntFromUint8Array(bytes) {
|
|
68
|
+
let result = BigInt(0);
|
|
69
|
+
for (const byte of bytes) {
|
|
70
|
+
// eslint-disable-next-line fp/no-mutation, no-bitwise -- Building bigint value using bit shift
|
|
71
|
+
result = (result << BigInt(8)) + BigInt(byte);
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Convert BigInt to Uint8Array (big-endian) with specified length
|
|
77
|
+
*/
|
|
78
|
+
function bigIntToUint8Array(num, length) {
|
|
79
|
+
const hex = num.toString(16).padStart(length * 2, "0");
|
|
80
|
+
const bytes = new Uint8Array(length);
|
|
81
|
+
Array.from({ length }).forEach((_, i) => {
|
|
82
|
+
// eslint-disable-next-line fp/no-mutation -- Building byte array element by element
|
|
83
|
+
bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
84
|
+
});
|
|
85
|
+
return bytes;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Convert ArrayBuffer to PEM format
|
|
89
|
+
*/
|
|
90
|
+
function arrayBufferToPem(buffer, type) {
|
|
91
|
+
var _a;
|
|
92
|
+
const base64 = (0, utils_1.uint8ArrayToBase64)(new Uint8Array(buffer));
|
|
93
|
+
const lines = (_a = base64.match(/.{1,64}/g)) !== null && _a !== void 0 ? _a : [];
|
|
94
|
+
return `-----BEGIN ${type}-----\n${lines.join("\n")}\n-----END ${type}-----`;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Extract key material from openpgp key packet and convert to Web Crypto formats
|
|
98
|
+
*/
|
|
99
|
+
async function extractKeyMaterial(keyPacket) {
|
|
100
|
+
// Get RSA parameters from the key packet
|
|
101
|
+
const { n, e } = keyPacket.publicParams;
|
|
102
|
+
const { d, p, q, u } = keyPacket.privateParams;
|
|
103
|
+
// Compute dp, dq from d, p, q
|
|
104
|
+
// dp = d mod (p-1)
|
|
105
|
+
// dq = d mod (q-1)
|
|
106
|
+
// qi = u (which is q^-1 mod p in PGP)
|
|
107
|
+
const dBigInt = bigIntFromUint8Array(d);
|
|
108
|
+
const pBigInt = bigIntFromUint8Array(p);
|
|
109
|
+
const qBigInt = bigIntFromUint8Array(q);
|
|
110
|
+
const dpBigInt = dBigInt % (pBigInt - BigInt(1));
|
|
111
|
+
const dqBigInt = dBigInt % (qBigInt - BigInt(1));
|
|
112
|
+
// For RSA keys, we need to construct JWK format
|
|
113
|
+
// Import as JWK first, then export as PKCS8
|
|
114
|
+
const publicJwk = {
|
|
115
|
+
kty: "RSA",
|
|
116
|
+
n: uint8ArrayToBase64Url(n),
|
|
117
|
+
e: uint8ArrayToBase64Url(e),
|
|
118
|
+
};
|
|
119
|
+
const privateJwk = Object.assign(Object.assign({}, publicJwk), { d: uint8ArrayToBase64Url(d), p: uint8ArrayToBase64Url(p), q: uint8ArrayToBase64Url(q), dp: uint8ArrayToBase64Url(bigIntToUint8Array(dpBigInt, p.length)), dq: uint8ArrayToBase64Url(bigIntToUint8Array(dqBigInt, q.length)), qi: uint8ArrayToBase64Url(u) });
|
|
120
|
+
// Import private key as JWK
|
|
121
|
+
const cryptoPrivateKey = await crypto.subtle.importKey("jwk", privateJwk, { name: "RSA-PSS", hash: "SHA-256" }, true, ["sign"]);
|
|
122
|
+
// Import public key as JWK
|
|
123
|
+
const cryptoPublicKey = await crypto.subtle.importKey("jwk", publicJwk, { name: "RSA-PSS", hash: "SHA-256" }, true, ["verify"]);
|
|
124
|
+
// Export private key as PKCS8
|
|
125
|
+
const privateKeyBuffer = await crypto.subtle.exportKey("pkcs8", cryptoPrivateKey);
|
|
126
|
+
const privateKeyBytes = new Uint8Array(privateKeyBuffer);
|
|
127
|
+
// Export public key as SPKI and convert to PEM
|
|
128
|
+
const publicKeyBuffer = await crypto.subtle.exportKey("spki", cryptoPublicKey);
|
|
129
|
+
const publicKeyPem = arrayBufferToPem(publicKeyBuffer, "PUBLIC KEY");
|
|
130
|
+
const publicKeySpkiBytes = new Uint8Array(publicKeyBuffer);
|
|
131
|
+
return { privateKeyBytes, publicKeyPem, publicKeySpkiBytes };
|
|
132
|
+
}
|
|
133
|
+
// ============================================================================
|
|
134
|
+
// Public API
|
|
135
|
+
// ============================================================================
|
|
136
|
+
/**
|
|
137
|
+
* Check if a string looks like an armored PGP key
|
|
138
|
+
*
|
|
139
|
+
* @param input - String to check
|
|
140
|
+
* @returns true if it appears to be armored PGP format
|
|
141
|
+
*/
|
|
142
|
+
function isArmoredPGPKey(input) {
|
|
143
|
+
return (input.includes("-----BEGIN PGP PRIVATE KEY BLOCK-----") ||
|
|
144
|
+
input.includes("-----BEGIN PGP PRIVATE KEY-----"));
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Parse an armored PGP private key
|
|
148
|
+
*
|
|
149
|
+
* @param armoredKey - Armored PGP private key string
|
|
150
|
+
* @param passphrase - Optional passphrase if key is encrypted
|
|
151
|
+
* @returns Parsed key data
|
|
152
|
+
* @throws PGPKeyImportError if parsing fails
|
|
153
|
+
*/
|
|
154
|
+
async function parseArmoredPGPKey(armoredKey, passphrase) {
|
|
155
|
+
// Dynamic import to avoid bundling openpgp for users who don't need import
|
|
156
|
+
const openpgp = await Promise.resolve().then(() => __importStar(require("openpgp")));
|
|
157
|
+
let privateKey;
|
|
158
|
+
try {
|
|
159
|
+
// Read the armored key
|
|
160
|
+
// eslint-disable-next-line fp/no-mutation -- Assigning result to declared variable
|
|
161
|
+
privateKey = await openpgp.readPrivateKey({ armoredKey });
|
|
162
|
+
}
|
|
163
|
+
catch (_a) {
|
|
164
|
+
throw new PGPKeyImportError("Failed to parse armored key. Please check the format.", "PARSE_ERROR");
|
|
165
|
+
}
|
|
166
|
+
// Check if key is encrypted and needs passphrase
|
|
167
|
+
if (!privateKey.isDecrypted()) {
|
|
168
|
+
if (!passphrase) {
|
|
169
|
+
throw new PGPKeyImportError("This key is passphrase-protected. Please enter your passphrase.", "PASSPHRASE_REQUIRED");
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
// eslint-disable-next-line fp/no-mutation -- Reassigning decrypted key
|
|
173
|
+
privateKey = await openpgp.decryptKey({
|
|
174
|
+
privateKey,
|
|
175
|
+
passphrase,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
catch (_b) {
|
|
179
|
+
throw new PGPKeyImportError("Incorrect passphrase. Please try again.", "INVALID_PASSPHRASE");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Get the primary key packet
|
|
183
|
+
const { keyPacket } = privateKey;
|
|
184
|
+
// Validate algorithm - we only support RSA
|
|
185
|
+
// openpgp uses numeric enums at runtime: rsaEncryptSign=1, rsaEncrypt=2, rsaSign=3
|
|
186
|
+
const algorithmId = keyPacket.algorithm;
|
|
187
|
+
const RSA_ALGORITHM_IDS = new Set([
|
|
188
|
+
1, // rsaEncryptSign
|
|
189
|
+
2, // rsaEncrypt
|
|
190
|
+
3, // rsaSign
|
|
191
|
+
]);
|
|
192
|
+
if (!RSA_ALGORITHM_IDS.has(algorithmId)) {
|
|
193
|
+
throw new PGPKeyImportError(`Unsupported algorithm: ${algorithmId}. Only RSA keys are supported.`, "UNSUPPORTED_ALGORITHM");
|
|
194
|
+
}
|
|
195
|
+
// Get key size from the modulus (n) length
|
|
196
|
+
// Type assertion needed because openpgp types are complex
|
|
197
|
+
const publicParams = keyPacket.publicParams;
|
|
198
|
+
const keySize = publicParams.n.length * 8;
|
|
199
|
+
// Extract the raw key material and convert to PKCS8
|
|
200
|
+
const { privateKeyBytes, publicKeyPem, publicKeySpkiBytes } = await extractKeyMaterial(keyPacket);
|
|
201
|
+
// Compute fingerprint using SHA-256 of SPKI bytes (consistent with generator)
|
|
202
|
+
const keyId = await (0, generator_1.computeKeyFingerprint)(publicKeySpkiBytes);
|
|
203
|
+
// Get user IDs
|
|
204
|
+
const userIds = privateKey.getUserIDs();
|
|
205
|
+
// Determine algorithm label
|
|
206
|
+
const algorithmLabel = keySize >= 4096 ? "RSA-4096" : "RSA-2048";
|
|
207
|
+
return {
|
|
208
|
+
privateKeyBytes,
|
|
209
|
+
publicKeyPem,
|
|
210
|
+
keyId,
|
|
211
|
+
algorithm: algorithmLabel,
|
|
212
|
+
keySize,
|
|
213
|
+
userIds,
|
|
214
|
+
createdAt: keyPacket.created.toISOString(),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Validate an imported key
|
|
219
|
+
*
|
|
220
|
+
* @param parsedKey - Parsed key to validate
|
|
221
|
+
* @returns Validation result with any warnings
|
|
222
|
+
*/
|
|
223
|
+
function validateImportedKey(parsedKey) {
|
|
224
|
+
// Check minimum key size
|
|
225
|
+
if (parsedKey.keySize < 2048) {
|
|
226
|
+
return {
|
|
227
|
+
isValid: false,
|
|
228
|
+
error: `Key size (${parsedKey.keySize} bits) is too small. Minimum 2048 bits required.`,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
// Warn if key size is less than recommended
|
|
232
|
+
if (parsedKey.keySize < 4096) {
|
|
233
|
+
return {
|
|
234
|
+
isValid: true,
|
|
235
|
+
warning: `Key size is ${parsedKey.keySize} bits. We recommend 4096 bits for maximum security.`,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return { isValid: true };
|
|
239
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PGP Key Module
|
|
3
|
+
*
|
|
4
|
+
* Provides generation, encryption, storage, and management of
|
|
5
|
+
* PGP keys for digital signatures.
|
|
6
|
+
*
|
|
7
|
+
* Issue #1374
|
|
8
|
+
*/
|
|
9
|
+
export * from "./types";
|
|
10
|
+
export { generatePGPKeyPair, computeKeyFingerprint } from "./generator";
|
|
11
|
+
export { encryptPrivateKey, decryptPrivateKey, importPrivateKey, importPublicKey, } from "./encryption";
|
|
12
|
+
export type { EncryptedPrivateKey } from "./encryption";
|
|
13
|
+
export { storePGPPrivateKey, getPGPPrivateKey, deletePGPPrivateKey, hasPGPPrivateKey, createIndexedDBPGPKeyStorage, } from "./storage";
|
|
14
|
+
export { isPemFormat, extractPemType, pemToBytes, bytesToPem, formatFingerprint, } from "./format";
|
|
15
|
+
export { signData, verifySignature, signText, verifyTextSignature, } from "./signing";
|
|
16
|
+
export { isArmoredPGPKey, parseArmoredPGPKey, validateImportedKey, PGPKeyImportError, } from "./import";
|
|
17
|
+
export type { ParsedPGPKey, KeyValidationResult } from "./import";
|
|
18
|
+
export { exportPGPKeyToArmored, PGPKeyExportError } from "./export";
|
|
19
|
+
export type { ExportPGPKeyOptions, ExportedPGPKey } from "./export";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PGP Key Module
|
|
4
|
+
*
|
|
5
|
+
* Provides generation, encryption, storage, and management of
|
|
6
|
+
* PGP keys for digital signatures.
|
|
7
|
+
*
|
|
8
|
+
* Issue #1374
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
22
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.PGPKeyExportError = exports.exportPGPKeyToArmored = exports.PGPKeyImportError = exports.validateImportedKey = exports.parseArmoredPGPKey = exports.isArmoredPGPKey = exports.verifyTextSignature = exports.signText = exports.verifySignature = exports.signData = exports.formatFingerprint = exports.bytesToPem = exports.pemToBytes = exports.extractPemType = exports.isPemFormat = exports.createIndexedDBPGPKeyStorage = exports.hasPGPPrivateKey = exports.deletePGPPrivateKey = exports.getPGPPrivateKey = exports.storePGPPrivateKey = exports.importPublicKey = exports.importPrivateKey = exports.decryptPrivateKey = exports.encryptPrivateKey = exports.computeKeyFingerprint = exports.generatePGPKeyPair = void 0;
|
|
26
|
+
// Re-export types
|
|
27
|
+
__exportStar(require("./types"), exports);
|
|
28
|
+
// Re-export generator
|
|
29
|
+
var generator_1 = require("./generator");
|
|
30
|
+
Object.defineProperty(exports, "generatePGPKeyPair", { enumerable: true, get: function () { return generator_1.generatePGPKeyPair; } });
|
|
31
|
+
Object.defineProperty(exports, "computeKeyFingerprint", { enumerable: true, get: function () { return generator_1.computeKeyFingerprint; } });
|
|
32
|
+
// Re-export encryption
|
|
33
|
+
var encryption_1 = require("./encryption");
|
|
34
|
+
Object.defineProperty(exports, "encryptPrivateKey", { enumerable: true, get: function () { return encryption_1.encryptPrivateKey; } });
|
|
35
|
+
Object.defineProperty(exports, "decryptPrivateKey", { enumerable: true, get: function () { return encryption_1.decryptPrivateKey; } });
|
|
36
|
+
Object.defineProperty(exports, "importPrivateKey", { enumerable: true, get: function () { return encryption_1.importPrivateKey; } });
|
|
37
|
+
Object.defineProperty(exports, "importPublicKey", { enumerable: true, get: function () { return encryption_1.importPublicKey; } });
|
|
38
|
+
// Re-export storage
|
|
39
|
+
var storage_1 = require("./storage");
|
|
40
|
+
Object.defineProperty(exports, "storePGPPrivateKey", { enumerable: true, get: function () { return storage_1.storePGPPrivateKey; } });
|
|
41
|
+
Object.defineProperty(exports, "getPGPPrivateKey", { enumerable: true, get: function () { return storage_1.getPGPPrivateKey; } });
|
|
42
|
+
Object.defineProperty(exports, "deletePGPPrivateKey", { enumerable: true, get: function () { return storage_1.deletePGPPrivateKey; } });
|
|
43
|
+
Object.defineProperty(exports, "hasPGPPrivateKey", { enumerable: true, get: function () { return storage_1.hasPGPPrivateKey; } });
|
|
44
|
+
Object.defineProperty(exports, "createIndexedDBPGPKeyStorage", { enumerable: true, get: function () { return storage_1.createIndexedDBPGPKeyStorage; } });
|
|
45
|
+
// Re-export format utilities
|
|
46
|
+
var format_1 = require("./format");
|
|
47
|
+
Object.defineProperty(exports, "isPemFormat", { enumerable: true, get: function () { return format_1.isPemFormat; } });
|
|
48
|
+
Object.defineProperty(exports, "extractPemType", { enumerable: true, get: function () { return format_1.extractPemType; } });
|
|
49
|
+
Object.defineProperty(exports, "pemToBytes", { enumerable: true, get: function () { return format_1.pemToBytes; } });
|
|
50
|
+
Object.defineProperty(exports, "bytesToPem", { enumerable: true, get: function () { return format_1.bytesToPem; } });
|
|
51
|
+
Object.defineProperty(exports, "formatFingerprint", { enumerable: true, get: function () { return format_1.formatFingerprint; } });
|
|
52
|
+
// Re-export signing
|
|
53
|
+
var signing_1 = require("./signing");
|
|
54
|
+
Object.defineProperty(exports, "signData", { enumerable: true, get: function () { return signing_1.signData; } });
|
|
55
|
+
Object.defineProperty(exports, "verifySignature", { enumerable: true, get: function () { return signing_1.verifySignature; } });
|
|
56
|
+
Object.defineProperty(exports, "signText", { enumerable: true, get: function () { return signing_1.signText; } });
|
|
57
|
+
Object.defineProperty(exports, "verifyTextSignature", { enumerable: true, get: function () { return signing_1.verifyTextSignature; } });
|
|
58
|
+
// Re-export import functions
|
|
59
|
+
var import_1 = require("./import");
|
|
60
|
+
Object.defineProperty(exports, "isArmoredPGPKey", { enumerable: true, get: function () { return import_1.isArmoredPGPKey; } });
|
|
61
|
+
Object.defineProperty(exports, "parseArmoredPGPKey", { enumerable: true, get: function () { return import_1.parseArmoredPGPKey; } });
|
|
62
|
+
Object.defineProperty(exports, "validateImportedKey", { enumerable: true, get: function () { return import_1.validateImportedKey; } });
|
|
63
|
+
Object.defineProperty(exports, "PGPKeyImportError", { enumerable: true, get: function () { return import_1.PGPKeyImportError; } });
|
|
64
|
+
// Re-export export functions
|
|
65
|
+
var export_1 = require("./export");
|
|
66
|
+
Object.defineProperty(exports, "exportPGPKeyToArmored", { enumerable: true, get: function () { return export_1.exportPGPKeyToArmored; } });
|
|
67
|
+
Object.defineProperty(exports, "PGPKeyExportError", { enumerable: true, get: function () { return export_1.PGPKeyExportError; } });
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PGP Key Signing Operations
|
|
3
|
+
*
|
|
4
|
+
* Provides RSA-PSS digital signature and verification functions.
|
|
5
|
+
* Issue #1374
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Sign raw bytes with an RSA-PSS private key
|
|
9
|
+
*
|
|
10
|
+
* @param data - Data to sign as Uint8Array
|
|
11
|
+
* @param privateKey - CryptoKey configured for RSA-PSS signing
|
|
12
|
+
* @returns Signature bytes (512 bytes for RSA-4096)
|
|
13
|
+
*/
|
|
14
|
+
export declare function signData(data: Uint8Array, privateKey: CryptoKey): Promise<Uint8Array>;
|
|
15
|
+
/**
|
|
16
|
+
* Verify an RSA-PSS signature
|
|
17
|
+
*
|
|
18
|
+
* @param data - Original data that was signed
|
|
19
|
+
* @param signature - Signature bytes to verify
|
|
20
|
+
* @param publicKey - CryptoKey configured for RSA-PSS verification
|
|
21
|
+
* @returns True if signature is valid, false otherwise
|
|
22
|
+
*/
|
|
23
|
+
export declare function verifySignature(data: Uint8Array, signature: Uint8Array, publicKey: CryptoKey): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* Sign text and return base64-encoded signature
|
|
26
|
+
*
|
|
27
|
+
* Convenience wrapper that encodes text to UTF-8 bytes before signing.
|
|
28
|
+
*
|
|
29
|
+
* @param text - Text to sign
|
|
30
|
+
* @param privateKey - CryptoKey configured for RSA-PSS signing
|
|
31
|
+
* @returns Base64-encoded signature string
|
|
32
|
+
*/
|
|
33
|
+
export declare function signText(text: string, privateKey: CryptoKey): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Verify a base64-encoded signature for text
|
|
36
|
+
*
|
|
37
|
+
* Convenience wrapper that decodes base64 signature and encodes text to UTF-8.
|
|
38
|
+
*
|
|
39
|
+
* @param text - Original text that was signed
|
|
40
|
+
* @param signatureBase64 - Base64-encoded signature to verify
|
|
41
|
+
* @param publicKey - CryptoKey configured for RSA-PSS verification
|
|
42
|
+
* @returns True if signature is valid, false otherwise
|
|
43
|
+
*/
|
|
44
|
+
export declare function verifyTextSignature(text: string, signatureBase64: string, publicKey: CryptoKey): Promise<boolean>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PGP Key Signing Operations
|
|
4
|
+
*
|
|
5
|
+
* Provides RSA-PSS digital signature and verification functions.
|
|
6
|
+
* Issue #1374
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.signData = signData;
|
|
10
|
+
exports.verifySignature = verifySignature;
|
|
11
|
+
exports.signText = signText;
|
|
12
|
+
exports.verifyTextSignature = verifyTextSignature;
|
|
13
|
+
const utils_1 = require("../kdf/utils");
|
|
14
|
+
/**
|
|
15
|
+
* RSA-PSS signature parameters
|
|
16
|
+
*/
|
|
17
|
+
const RSA_PSS_PARAMS = {
|
|
18
|
+
name: "RSA-PSS",
|
|
19
|
+
saltLength: 32, // Recommended for SHA-256
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Sign raw bytes with an RSA-PSS private key
|
|
23
|
+
*
|
|
24
|
+
* @param data - Data to sign as Uint8Array
|
|
25
|
+
* @param privateKey - CryptoKey configured for RSA-PSS signing
|
|
26
|
+
* @returns Signature bytes (512 bytes for RSA-4096)
|
|
27
|
+
*/
|
|
28
|
+
async function signData(data, privateKey) {
|
|
29
|
+
const signature = await crypto.subtle.sign(RSA_PSS_PARAMS, privateKey, data);
|
|
30
|
+
return new Uint8Array(signature);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Verify an RSA-PSS signature
|
|
34
|
+
*
|
|
35
|
+
* @param data - Original data that was signed
|
|
36
|
+
* @param signature - Signature bytes to verify
|
|
37
|
+
* @param publicKey - CryptoKey configured for RSA-PSS verification
|
|
38
|
+
* @returns True if signature is valid, false otherwise
|
|
39
|
+
*/
|
|
40
|
+
async function verifySignature(data, signature, publicKey) {
|
|
41
|
+
return crypto.subtle.verify(RSA_PSS_PARAMS, publicKey, signature, data);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Sign text and return base64-encoded signature
|
|
45
|
+
*
|
|
46
|
+
* Convenience wrapper that encodes text to UTF-8 bytes before signing.
|
|
47
|
+
*
|
|
48
|
+
* @param text - Text to sign
|
|
49
|
+
* @param privateKey - CryptoKey configured for RSA-PSS signing
|
|
50
|
+
* @returns Base64-encoded signature string
|
|
51
|
+
*/
|
|
52
|
+
async function signText(text, privateKey) {
|
|
53
|
+
const data = new TextEncoder().encode(text);
|
|
54
|
+
const signature = await signData(data, privateKey);
|
|
55
|
+
return (0, utils_1.uint8ArrayToBase64)(signature);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Verify a base64-encoded signature for text
|
|
59
|
+
*
|
|
60
|
+
* Convenience wrapper that decodes base64 signature and encodes text to UTF-8.
|
|
61
|
+
*
|
|
62
|
+
* @param text - Original text that was signed
|
|
63
|
+
* @param signatureBase64 - Base64-encoded signature to verify
|
|
64
|
+
* @param publicKey - CryptoKey configured for RSA-PSS verification
|
|
65
|
+
* @returns True if signature is valid, false otherwise
|
|
66
|
+
*/
|
|
67
|
+
async function verifyTextSignature(text, signatureBase64, publicKey) {
|
|
68
|
+
const data = new TextEncoder().encode(text);
|
|
69
|
+
const signature = Uint8Array.from(atob(signatureBase64), c => c.charCodeAt(0));
|
|
70
|
+
return verifySignature(data, signature, publicKey);
|
|
71
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PGP Key Storage
|
|
3
|
+
*
|
|
4
|
+
* IndexedDB-based storage for encrypted PGP private keys.
|
|
5
|
+
* The encrypted private key is stored locally on the device and never sent to servers.
|
|
6
|
+
*
|
|
7
|
+
* Issue #1374
|
|
8
|
+
*/
|
|
9
|
+
import type { PGPKeyStorage, StoredPGPPrivateKey } from "./types";
|
|
10
|
+
/**
|
|
11
|
+
* Generate storage key for a user's PGP private key
|
|
12
|
+
*/
|
|
13
|
+
export declare function getStorageKey(userId: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Store an encrypted PGP private key in IndexedDB
|
|
16
|
+
*
|
|
17
|
+
* @param record - The encrypted private key record to store
|
|
18
|
+
*/
|
|
19
|
+
export declare function storePGPPrivateKey(record: StoredPGPPrivateKey): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Retrieve an encrypted PGP private key from IndexedDB
|
|
22
|
+
*
|
|
23
|
+
* @param userId - User's Cognito sub
|
|
24
|
+
* @returns The encrypted private key record or null if not found
|
|
25
|
+
*/
|
|
26
|
+
export declare function getPGPPrivateKey(userId: string): Promise<StoredPGPPrivateKey | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Delete an encrypted PGP private key from IndexedDB
|
|
29
|
+
*
|
|
30
|
+
* @param userId - User's Cognito sub
|
|
31
|
+
*/
|
|
32
|
+
export declare function deletePGPPrivateKey(userId: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Check if an encrypted PGP private key exists for a user
|
|
35
|
+
*
|
|
36
|
+
* @param userId - User's Cognito sub
|
|
37
|
+
* @returns true if a key exists
|
|
38
|
+
*/
|
|
39
|
+
export declare function hasPGPPrivateKey(userId: string): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Create a PGPKeyStorage implementation using IndexedDB
|
|
42
|
+
*/
|
|
43
|
+
export declare function createIndexedDBPGPKeyStorage(): PGPKeyStorage;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PGP Key Storage
|
|
4
|
+
*
|
|
5
|
+
* IndexedDB-based storage for encrypted PGP private keys.
|
|
6
|
+
* The encrypted private key is stored locally on the device and never sent to servers.
|
|
7
|
+
*
|
|
8
|
+
* Issue #1374
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.getStorageKey = getStorageKey;
|
|
12
|
+
exports.storePGPPrivateKey = storePGPPrivateKey;
|
|
13
|
+
exports.getPGPPrivateKey = getPGPPrivateKey;
|
|
14
|
+
exports.deletePGPPrivateKey = deletePGPPrivateKey;
|
|
15
|
+
exports.hasPGPPrivateKey = hasPGPPrivateKey;
|
|
16
|
+
exports.createIndexedDBPGPKeyStorage = createIndexedDBPGPKeyStorage;
|
|
17
|
+
const types_1 = require("./types");
|
|
18
|
+
/**
|
|
19
|
+
* Generate storage key for a user's PGP private key
|
|
20
|
+
*/
|
|
21
|
+
function getStorageKey(userId) {
|
|
22
|
+
return `pgp-private-key-${userId}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Open the IndexedDB database for PGP key storage
|
|
26
|
+
*/
|
|
27
|
+
function openDatabase() {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const request = indexedDB.open(types_1.PGP_KEY_DB_CONFIG.name, types_1.PGP_KEY_DB_CONFIG.version);
|
|
30
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
31
|
+
request.onerror = () => {
|
|
32
|
+
reject(new Error("Failed to open PGP key database"));
|
|
33
|
+
};
|
|
34
|
+
request.onsuccess = () => {
|
|
35
|
+
resolve(request.result);
|
|
36
|
+
};
|
|
37
|
+
request.onupgradeneeded = event => {
|
|
38
|
+
const db = event.target.result;
|
|
39
|
+
// Create object store if it doesn't exist
|
|
40
|
+
if (!db.objectStoreNames.contains(types_1.PGP_KEY_DB_CONFIG.storeName)) {
|
|
41
|
+
db.createObjectStore(types_1.PGP_KEY_DB_CONFIG.storeName);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/* eslint-enable fp/no-mutation */
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Store an encrypted PGP private key in IndexedDB
|
|
49
|
+
*
|
|
50
|
+
* @param record - The encrypted private key record to store
|
|
51
|
+
*/
|
|
52
|
+
async function storePGPPrivateKey(record) {
|
|
53
|
+
const db = await openDatabase();
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
const transaction = db.transaction(types_1.PGP_KEY_DB_CONFIG.storeName, "readwrite");
|
|
56
|
+
const store = transaction.objectStore(types_1.PGP_KEY_DB_CONFIG.storeName);
|
|
57
|
+
const request = store.put(record, getStorageKey(record.userId));
|
|
58
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
59
|
+
request.onerror = () => {
|
|
60
|
+
reject(new Error("Failed to store PGP private key"));
|
|
61
|
+
};
|
|
62
|
+
request.onsuccess = () => {
|
|
63
|
+
resolve();
|
|
64
|
+
};
|
|
65
|
+
transaction.oncomplete = () => {
|
|
66
|
+
db.close();
|
|
67
|
+
};
|
|
68
|
+
/* eslint-enable fp/no-mutation */
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Retrieve an encrypted PGP private key from IndexedDB
|
|
73
|
+
*
|
|
74
|
+
* @param userId - User's Cognito sub
|
|
75
|
+
* @returns The encrypted private key record or null if not found
|
|
76
|
+
*/
|
|
77
|
+
async function getPGPPrivateKey(userId) {
|
|
78
|
+
const db = await openDatabase();
|
|
79
|
+
return new Promise((resolve, reject) => {
|
|
80
|
+
const transaction = db.transaction(types_1.PGP_KEY_DB_CONFIG.storeName, "readonly");
|
|
81
|
+
const store = transaction.objectStore(types_1.PGP_KEY_DB_CONFIG.storeName);
|
|
82
|
+
const request = store.get(getStorageKey(userId));
|
|
83
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
84
|
+
request.onerror = () => {
|
|
85
|
+
reject(new Error("Failed to retrieve PGP private key"));
|
|
86
|
+
};
|
|
87
|
+
request.onsuccess = () => {
|
|
88
|
+
var _a;
|
|
89
|
+
resolve((_a = request.result) !== null && _a !== void 0 ? _a : null);
|
|
90
|
+
};
|
|
91
|
+
transaction.oncomplete = () => {
|
|
92
|
+
db.close();
|
|
93
|
+
};
|
|
94
|
+
/* eslint-enable fp/no-mutation */
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Delete an encrypted PGP private key from IndexedDB
|
|
99
|
+
*
|
|
100
|
+
* @param userId - User's Cognito sub
|
|
101
|
+
*/
|
|
102
|
+
async function deletePGPPrivateKey(userId) {
|
|
103
|
+
const db = await openDatabase();
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const transaction = db.transaction(types_1.PGP_KEY_DB_CONFIG.storeName, "readwrite");
|
|
106
|
+
const store = transaction.objectStore(types_1.PGP_KEY_DB_CONFIG.storeName);
|
|
107
|
+
const request = store.delete(getStorageKey(userId));
|
|
108
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
109
|
+
request.onerror = () => {
|
|
110
|
+
reject(new Error("Failed to delete PGP private key"));
|
|
111
|
+
};
|
|
112
|
+
request.onsuccess = () => {
|
|
113
|
+
resolve();
|
|
114
|
+
};
|
|
115
|
+
transaction.oncomplete = () => {
|
|
116
|
+
db.close();
|
|
117
|
+
};
|
|
118
|
+
/* eslint-enable fp/no-mutation */
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Check if an encrypted PGP private key exists for a user
|
|
123
|
+
*
|
|
124
|
+
* @param userId - User's Cognito sub
|
|
125
|
+
* @returns true if a key exists
|
|
126
|
+
*/
|
|
127
|
+
async function hasPGPPrivateKey(userId) {
|
|
128
|
+
const record = await getPGPPrivateKey(userId);
|
|
129
|
+
return record !== null;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Create a PGPKeyStorage implementation using IndexedDB
|
|
133
|
+
*/
|
|
134
|
+
function createIndexedDBPGPKeyStorage() {
|
|
135
|
+
return {
|
|
136
|
+
store: storePGPPrivateKey,
|
|
137
|
+
get: getPGPPrivateKey,
|
|
138
|
+
delete: deletePGPPrivateKey,
|
|
139
|
+
exists: hasPGPPrivateKey,
|
|
140
|
+
};
|
|
141
|
+
}
|