@raytio/core 11.5.0 → 11.6.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,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LocalSecret Storage
|
|
4
|
+
*
|
|
5
|
+
* IndexedDB-based storage for LocalSecrets.
|
|
6
|
+
* The LocalSecret is stored locally on the device and never sent to servers.
|
|
7
|
+
*
|
|
8
|
+
* Issue #1649
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.getOrCreateDeviceId = getOrCreateDeviceId;
|
|
12
|
+
exports.storeLocalSecret = storeLocalSecret;
|
|
13
|
+
exports.getLocalSecret = getLocalSecret;
|
|
14
|
+
exports.deleteLocalSecret = deleteLocalSecret;
|
|
15
|
+
exports.hasLocalSecret = hasLocalSecret;
|
|
16
|
+
exports.getLocalSecretRecord = getLocalSecretRecord;
|
|
17
|
+
exports.createIndexedDBStorage = createIndexedDBStorage;
|
|
18
|
+
const types_1 = require("./types");
|
|
19
|
+
const generator_1 = require("./generator");
|
|
20
|
+
// Cached device ID
|
|
21
|
+
let deviceId = null;
|
|
22
|
+
/**
|
|
23
|
+
* Get or create a unique device ID
|
|
24
|
+
*
|
|
25
|
+
* The device ID is stored in localStorage for persistence.
|
|
26
|
+
*/
|
|
27
|
+
async function getOrCreateDeviceId() {
|
|
28
|
+
if (deviceId) {
|
|
29
|
+
return deviceId;
|
|
30
|
+
}
|
|
31
|
+
const storageKey = "raytio-device-id";
|
|
32
|
+
try {
|
|
33
|
+
const stored = localStorage.getItem(storageKey);
|
|
34
|
+
if (stored) {
|
|
35
|
+
// eslint-disable-next-line fp/no-mutation -- Cache assignment
|
|
36
|
+
deviceId = stored;
|
|
37
|
+
return deviceId;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (_a) {
|
|
41
|
+
// localStorage not available
|
|
42
|
+
}
|
|
43
|
+
// Generate new device ID
|
|
44
|
+
const newDeviceId = (0, generator_1.generateDeviceId)();
|
|
45
|
+
// eslint-disable-next-line fp/no-mutation -- Cache assignment
|
|
46
|
+
deviceId = newDeviceId;
|
|
47
|
+
try {
|
|
48
|
+
localStorage.setItem(storageKey, newDeviceId);
|
|
49
|
+
}
|
|
50
|
+
catch (_b) {
|
|
51
|
+
// localStorage not available, device ID will be regenerated on next session
|
|
52
|
+
}
|
|
53
|
+
return newDeviceId;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Open the IndexedDB database for LocalSecret storage
|
|
57
|
+
*/
|
|
58
|
+
function openDatabase() {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
const request = indexedDB.open(types_1.LOCAL_SECRET_DB_CONFIG.name, types_1.LOCAL_SECRET_DB_CONFIG.version);
|
|
61
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
62
|
+
request.onerror = () => {
|
|
63
|
+
reject(new Error("Failed to open LocalSecret database"));
|
|
64
|
+
};
|
|
65
|
+
request.onsuccess = () => {
|
|
66
|
+
resolve(request.result);
|
|
67
|
+
};
|
|
68
|
+
request.onupgradeneeded = event => {
|
|
69
|
+
const db = event.target.result;
|
|
70
|
+
// Create object store if it doesn't exist
|
|
71
|
+
if (!db.objectStoreNames.contains(types_1.LOCAL_SECRET_DB_CONFIG.storeName)) {
|
|
72
|
+
db.createObjectStore(types_1.LOCAL_SECRET_DB_CONFIG.storeName);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
/* eslint-enable fp/no-mutation */
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Store a LocalSecret in IndexedDB
|
|
80
|
+
*
|
|
81
|
+
* @param userId - User's Cognito sub
|
|
82
|
+
* @param secret - The 32-byte LocalSecret
|
|
83
|
+
*/
|
|
84
|
+
async function storeLocalSecret(userId, secret) {
|
|
85
|
+
const db = await openDatabase();
|
|
86
|
+
const deviceIdValue = await getOrCreateDeviceId();
|
|
87
|
+
const record = {
|
|
88
|
+
secret,
|
|
89
|
+
userId,
|
|
90
|
+
createdAt: new Date().toISOString(),
|
|
91
|
+
deviceId: deviceIdValue,
|
|
92
|
+
};
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
const transaction = db.transaction(types_1.LOCAL_SECRET_DB_CONFIG.storeName, "readwrite");
|
|
95
|
+
const store = transaction.objectStore(types_1.LOCAL_SECRET_DB_CONFIG.storeName);
|
|
96
|
+
const request = store.put(record, `local-secret-${userId}`);
|
|
97
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
98
|
+
request.onerror = () => {
|
|
99
|
+
reject(new Error("Failed to store LocalSecret"));
|
|
100
|
+
};
|
|
101
|
+
request.onsuccess = () => {
|
|
102
|
+
resolve();
|
|
103
|
+
};
|
|
104
|
+
transaction.oncomplete = () => {
|
|
105
|
+
db.close();
|
|
106
|
+
};
|
|
107
|
+
/* eslint-enable fp/no-mutation */
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Retrieve a LocalSecret from IndexedDB
|
|
112
|
+
*
|
|
113
|
+
* @param userId - User's Cognito sub
|
|
114
|
+
* @returns The LocalSecret or null if not found
|
|
115
|
+
*/
|
|
116
|
+
async function getLocalSecret(userId) {
|
|
117
|
+
const db = await openDatabase();
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
const transaction = db.transaction(types_1.LOCAL_SECRET_DB_CONFIG.storeName, "readonly");
|
|
120
|
+
const store = transaction.objectStore(types_1.LOCAL_SECRET_DB_CONFIG.storeName);
|
|
121
|
+
const request = store.get(`local-secret-${userId}`);
|
|
122
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
123
|
+
request.onerror = () => {
|
|
124
|
+
reject(new Error("Failed to retrieve LocalSecret"));
|
|
125
|
+
};
|
|
126
|
+
request.onsuccess = () => {
|
|
127
|
+
var _a;
|
|
128
|
+
const record = request.result;
|
|
129
|
+
resolve((_a = record === null || record === void 0 ? void 0 : record.secret) !== null && _a !== void 0 ? _a : null);
|
|
130
|
+
};
|
|
131
|
+
transaction.oncomplete = () => {
|
|
132
|
+
db.close();
|
|
133
|
+
};
|
|
134
|
+
/* eslint-enable fp/no-mutation */
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Delete a LocalSecret from IndexedDB
|
|
139
|
+
*
|
|
140
|
+
* @param userId - User's Cognito sub
|
|
141
|
+
*/
|
|
142
|
+
async function deleteLocalSecret(userId) {
|
|
143
|
+
const db = await openDatabase();
|
|
144
|
+
return new Promise((resolve, reject) => {
|
|
145
|
+
const transaction = db.transaction(types_1.LOCAL_SECRET_DB_CONFIG.storeName, "readwrite");
|
|
146
|
+
const store = transaction.objectStore(types_1.LOCAL_SECRET_DB_CONFIG.storeName);
|
|
147
|
+
const request = store.delete(`local-secret-${userId}`);
|
|
148
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
149
|
+
request.onerror = () => {
|
|
150
|
+
reject(new Error("Failed to delete LocalSecret"));
|
|
151
|
+
};
|
|
152
|
+
request.onsuccess = () => {
|
|
153
|
+
resolve();
|
|
154
|
+
};
|
|
155
|
+
transaction.oncomplete = () => {
|
|
156
|
+
db.close();
|
|
157
|
+
};
|
|
158
|
+
/* eslint-enable fp/no-mutation */
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if a LocalSecret exists for a user
|
|
163
|
+
*
|
|
164
|
+
* @param userId - User's Cognito sub
|
|
165
|
+
* @returns true if a LocalSecret exists
|
|
166
|
+
*/
|
|
167
|
+
async function hasLocalSecret(userId) {
|
|
168
|
+
const secret = await getLocalSecret(userId);
|
|
169
|
+
return secret !== null;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get the stored LocalSecret record (including metadata)
|
|
173
|
+
*
|
|
174
|
+
* @param userId - User's Cognito sub
|
|
175
|
+
* @returns The full storage record or null
|
|
176
|
+
*/
|
|
177
|
+
async function getLocalSecretRecord(userId) {
|
|
178
|
+
const db = await openDatabase();
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
const transaction = db.transaction(types_1.LOCAL_SECRET_DB_CONFIG.storeName, "readonly");
|
|
181
|
+
const store = transaction.objectStore(types_1.LOCAL_SECRET_DB_CONFIG.storeName);
|
|
182
|
+
const request = store.get(`local-secret-${userId}`);
|
|
183
|
+
/* eslint-disable fp/no-mutation -- IndexedDB API requires callback assignment */
|
|
184
|
+
request.onerror = () => {
|
|
185
|
+
reject(new Error("Failed to retrieve LocalSecret record"));
|
|
186
|
+
};
|
|
187
|
+
request.onsuccess = () => {
|
|
188
|
+
var _a;
|
|
189
|
+
resolve((_a = request.result) !== null && _a !== void 0 ? _a : null);
|
|
190
|
+
};
|
|
191
|
+
transaction.oncomplete = () => {
|
|
192
|
+
db.close();
|
|
193
|
+
};
|
|
194
|
+
/* eslint-enable fp/no-mutation */
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Create a LocalSecretStorage implementation using IndexedDB
|
|
199
|
+
*/
|
|
200
|
+
function createIndexedDBStorage() {
|
|
201
|
+
return {
|
|
202
|
+
store: storeLocalSecret,
|
|
203
|
+
get: getLocalSecret,
|
|
204
|
+
delete: deleteLocalSecret,
|
|
205
|
+
exists: hasLocalSecret,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalSecret Types
|
|
3
|
+
*
|
|
4
|
+
* Types for the device-bound LocalSecret used in 2SKD.
|
|
5
|
+
* Issue #1649
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* LocalSecret storage record
|
|
9
|
+
*/
|
|
10
|
+
export interface StoredLocalSecret {
|
|
11
|
+
/** The 32-byte LocalSecret */
|
|
12
|
+
secret: Uint8Array;
|
|
13
|
+
/** User's Cognito sub (user ID) */
|
|
14
|
+
userId: string;
|
|
15
|
+
/** When the LocalSecret was created */
|
|
16
|
+
createdAt: string;
|
|
17
|
+
/** Unique identifier for this device */
|
|
18
|
+
deviceId: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* LocalSecret display format
|
|
22
|
+
*
|
|
23
|
+
* Formatted for human readability with dashes between groups.
|
|
24
|
+
* Uses unambiguous character set (no 0, 1, I, O).
|
|
25
|
+
*/
|
|
26
|
+
export interface FormattedLocalSecret {
|
|
27
|
+
/** Full formatted string (e.g., "A7K2M9-X4P8N3-...") */
|
|
28
|
+
formatted: string;
|
|
29
|
+
/** Individual groups for display */
|
|
30
|
+
groups: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* LocalSecret storage interface
|
|
34
|
+
*
|
|
35
|
+
* Abstraction for storing LocalSecrets (IndexedDB, Keychain, etc.)
|
|
36
|
+
*/
|
|
37
|
+
export interface LocalSecretStorage {
|
|
38
|
+
/** Store a LocalSecret for a user */
|
|
39
|
+
store(userId: string, secret: Uint8Array): Promise<void>;
|
|
40
|
+
/** Retrieve a LocalSecret for a user */
|
|
41
|
+
get(userId: string): Promise<Uint8Array | null>;
|
|
42
|
+
/** Delete a LocalSecret for a user */
|
|
43
|
+
delete(userId: string): Promise<void>;
|
|
44
|
+
/** Check if a LocalSecret exists for a user */
|
|
45
|
+
exists(userId: string): Promise<boolean>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* IndexedDB configuration for LocalSecret storage
|
|
49
|
+
*/
|
|
50
|
+
export declare const LOCAL_SECRET_DB_CONFIG: {
|
|
51
|
+
readonly name: "raytio-secrets";
|
|
52
|
+
readonly version: 1;
|
|
53
|
+
readonly storeName: "local-secrets";
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* LocalSecret size in bytes (256 bits)
|
|
57
|
+
*/
|
|
58
|
+
export declare const LOCAL_SECRET_SIZE = 32;
|
|
59
|
+
/**
|
|
60
|
+
* Character set for LocalSecret display format
|
|
61
|
+
*
|
|
62
|
+
* Excludes ambiguous characters: 0, 1, I, O
|
|
63
|
+
*/
|
|
64
|
+
export declare const LOCAL_SECRET_CHARSET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
65
|
+
/**
|
|
66
|
+
* Number of characters per group in formatted display
|
|
67
|
+
*/
|
|
68
|
+
export declare const LOCAL_SECRET_GROUP_SIZE = 6;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LocalSecret Types
|
|
4
|
+
*
|
|
5
|
+
* Types for the device-bound LocalSecret used in 2SKD.
|
|
6
|
+
* Issue #1649
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.LOCAL_SECRET_GROUP_SIZE = exports.LOCAL_SECRET_CHARSET = exports.LOCAL_SECRET_SIZE = exports.LOCAL_SECRET_DB_CONFIG = void 0;
|
|
10
|
+
/**
|
|
11
|
+
* IndexedDB configuration for LocalSecret storage
|
|
12
|
+
*/
|
|
13
|
+
exports.LOCAL_SECRET_DB_CONFIG = {
|
|
14
|
+
name: "raytio-secrets",
|
|
15
|
+
version: 1,
|
|
16
|
+
storeName: "local-secrets",
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* LocalSecret size in bytes (256 bits)
|
|
20
|
+
*/
|
|
21
|
+
exports.LOCAL_SECRET_SIZE = 32;
|
|
22
|
+
/**
|
|
23
|
+
* Character set for LocalSecret display format
|
|
24
|
+
*
|
|
25
|
+
* Excludes ambiguous characters: 0, 1, I, O
|
|
26
|
+
*/
|
|
27
|
+
exports.LOCAL_SECRET_CHARSET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
28
|
+
/**
|
|
29
|
+
* Number of characters per group in formatted display
|
|
30
|
+
*/
|
|
31
|
+
exports.LOCAL_SECRET_GROUP_SIZE = 6;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PGP Private Key Encryption
|
|
3
|
+
*
|
|
4
|
+
* Encrypts private keys using AES-GCM with the user's 2SKD KEK.
|
|
5
|
+
* Issue #1374
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Encryption result containing ciphertext and IV
|
|
9
|
+
*/
|
|
10
|
+
export interface EncryptedPrivateKey {
|
|
11
|
+
/** AES-GCM encrypted private key bytes */
|
|
12
|
+
encryptedPrivateKey: Uint8Array;
|
|
13
|
+
/** 12-byte initialization vector for decryption */
|
|
14
|
+
iv: Uint8Array;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Encrypt private key bytes with the user's KEK using AES-GCM
|
|
18
|
+
*
|
|
19
|
+
* Uses a random 12-byte IV for each encryption operation.
|
|
20
|
+
*
|
|
21
|
+
* @param privateKeyBytes - Raw private key bytes (PKCS8 format)
|
|
22
|
+
* @param kek - 32-byte Key Encryption Key from 2SKD
|
|
23
|
+
* @returns Encrypted private key and IV
|
|
24
|
+
*/
|
|
25
|
+
export declare function encryptPrivateKey(privateKeyBytes: Uint8Array, kek: Uint8Array): Promise<EncryptedPrivateKey>;
|
|
26
|
+
/**
|
|
27
|
+
* Decrypt private key bytes with the user's KEK using AES-GCM
|
|
28
|
+
*
|
|
29
|
+
* @param encryptedPrivateKey - AES-GCM encrypted private key bytes
|
|
30
|
+
* @param iv - 12-byte initialization vector used during encryption
|
|
31
|
+
* @param kek - 32-byte Key Encryption Key from 2SKD
|
|
32
|
+
* @returns Decrypted private key bytes (PKCS8 format)
|
|
33
|
+
* @throws Error if decryption fails (wrong key or tampered data)
|
|
34
|
+
*/
|
|
35
|
+
export declare function decryptPrivateKey(encryptedPrivateKey: Uint8Array, iv: Uint8Array, kek: Uint8Array): Promise<Uint8Array>;
|
|
36
|
+
/**
|
|
37
|
+
* Import private key bytes as a CryptoKey for RSA-PSS signing
|
|
38
|
+
*
|
|
39
|
+
* @param privateKeyBytes - Private key in PKCS8 format
|
|
40
|
+
* @returns CryptoKey configured for RSA-PSS signing with SHA-256
|
|
41
|
+
*/
|
|
42
|
+
export declare function importPrivateKey(privateKeyBytes: Uint8Array): Promise<CryptoKey>;
|
|
43
|
+
/**
|
|
44
|
+
* Import a PEM-encoded public key as a CryptoKey for RSA-PSS verification
|
|
45
|
+
*
|
|
46
|
+
* @param publicKeyPem - Public key in PEM format (SPKI)
|
|
47
|
+
* @returns CryptoKey configured for RSA-PSS verification with SHA-256
|
|
48
|
+
*/
|
|
49
|
+
export declare function importPublicKey(publicKeyPem: string): Promise<CryptoKey>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PGP Private Key Encryption
|
|
4
|
+
*
|
|
5
|
+
* Encrypts private keys using AES-GCM with the user's 2SKD KEK.
|
|
6
|
+
* Issue #1374
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.encryptPrivateKey = encryptPrivateKey;
|
|
10
|
+
exports.decryptPrivateKey = decryptPrivateKey;
|
|
11
|
+
exports.importPrivateKey = importPrivateKey;
|
|
12
|
+
exports.importPublicKey = importPublicKey;
|
|
13
|
+
const types_1 = require("./types");
|
|
14
|
+
/**
|
|
15
|
+
* Import a raw KEK as a CryptoKey for AES-GCM operations
|
|
16
|
+
*
|
|
17
|
+
* @param kek - 32-byte KEK (Key Encryption Key)
|
|
18
|
+
* @returns CryptoKey for encryption/decryption
|
|
19
|
+
*/
|
|
20
|
+
async function importKek(kek) {
|
|
21
|
+
return crypto.subtle.importKey("raw", kek, { name: "AES-GCM" }, false, [
|
|
22
|
+
"encrypt",
|
|
23
|
+
"decrypt",
|
|
24
|
+
]);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Encrypt private key bytes with the user's KEK using AES-GCM
|
|
28
|
+
*
|
|
29
|
+
* Uses a random 12-byte IV for each encryption operation.
|
|
30
|
+
*
|
|
31
|
+
* @param privateKeyBytes - Raw private key bytes (PKCS8 format)
|
|
32
|
+
* @param kek - 32-byte Key Encryption Key from 2SKD
|
|
33
|
+
* @returns Encrypted private key and IV
|
|
34
|
+
*/
|
|
35
|
+
async function encryptPrivateKey(privateKeyBytes, kek) {
|
|
36
|
+
if (kek.length !== 32) {
|
|
37
|
+
throw new Error("KEK must be 32 bytes for AES-256");
|
|
38
|
+
}
|
|
39
|
+
if (privateKeyBytes.length === 0) {
|
|
40
|
+
throw new Error("Private key cannot be empty");
|
|
41
|
+
}
|
|
42
|
+
// Generate random IV
|
|
43
|
+
const iv = new Uint8Array(types_1.AES_GCM_IV_SIZE);
|
|
44
|
+
crypto.getRandomValues(iv);
|
|
45
|
+
// Import KEK as CryptoKey
|
|
46
|
+
const cryptoKey = await importKek(kek);
|
|
47
|
+
// Encrypt with AES-GCM
|
|
48
|
+
const encryptedBuffer = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, cryptoKey, privateKeyBytes);
|
|
49
|
+
return {
|
|
50
|
+
encryptedPrivateKey: new Uint8Array(encryptedBuffer),
|
|
51
|
+
iv,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Decrypt private key bytes with the user's KEK using AES-GCM
|
|
56
|
+
*
|
|
57
|
+
* @param encryptedPrivateKey - AES-GCM encrypted private key bytes
|
|
58
|
+
* @param iv - 12-byte initialization vector used during encryption
|
|
59
|
+
* @param kek - 32-byte Key Encryption Key from 2SKD
|
|
60
|
+
* @returns Decrypted private key bytes (PKCS8 format)
|
|
61
|
+
* @throws Error if decryption fails (wrong key or tampered data)
|
|
62
|
+
*/
|
|
63
|
+
async function decryptPrivateKey(encryptedPrivateKey, iv, kek) {
|
|
64
|
+
if (kek.length !== 32) {
|
|
65
|
+
throw new Error("KEK must be 32 bytes for AES-256");
|
|
66
|
+
}
|
|
67
|
+
if (iv.length !== types_1.AES_GCM_IV_SIZE) {
|
|
68
|
+
throw new Error("IV must be 12 bytes");
|
|
69
|
+
}
|
|
70
|
+
if (encryptedPrivateKey.length === 0) {
|
|
71
|
+
throw new Error("Encrypted private key cannot be empty");
|
|
72
|
+
}
|
|
73
|
+
// Import KEK as CryptoKey
|
|
74
|
+
const cryptoKey = await importKek(kek);
|
|
75
|
+
// Decrypt with AES-GCM
|
|
76
|
+
const decryptedBuffer = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, cryptoKey, encryptedPrivateKey);
|
|
77
|
+
return new Uint8Array(decryptedBuffer);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Import private key bytes as a CryptoKey for RSA-PSS signing
|
|
81
|
+
*
|
|
82
|
+
* @param privateKeyBytes - Private key in PKCS8 format
|
|
83
|
+
* @returns CryptoKey configured for RSA-PSS signing with SHA-256
|
|
84
|
+
*/
|
|
85
|
+
async function importPrivateKey(privateKeyBytes) {
|
|
86
|
+
return crypto.subtle.importKey("pkcs8", privateKeyBytes, { name: "RSA-PSS", hash: "SHA-256" }, false, ["sign"]);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Import a PEM-encoded public key as a CryptoKey for RSA-PSS verification
|
|
90
|
+
*
|
|
91
|
+
* @param publicKeyPem - Public key in PEM format (SPKI)
|
|
92
|
+
* @returns CryptoKey configured for RSA-PSS verification with SHA-256
|
|
93
|
+
*/
|
|
94
|
+
async function importPublicKey(publicKeyPem) {
|
|
95
|
+
// Extract base64 content from PEM
|
|
96
|
+
const pemContents = publicKeyPem
|
|
97
|
+
.replace(/-----BEGIN PUBLIC KEY-----/, "")
|
|
98
|
+
.replace(/-----END PUBLIC KEY-----/, "")
|
|
99
|
+
.replace(/\s/g, "");
|
|
100
|
+
// Decode base64 to bytes using functional approach
|
|
101
|
+
const binaryString = atob(pemContents);
|
|
102
|
+
const bytes = Uint8Array.from(binaryString, c => c.charCodeAt(0));
|
|
103
|
+
return crypto.subtle.importKey("spki", bytes, { name: "RSA-PSS", hash: "SHA-256" }, false, ["verify"]);
|
|
104
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PGP Key Export
|
|
3
|
+
*
|
|
4
|
+
* Export PKCS8 private keys to OpenPGP armored format.
|
|
5
|
+
* Compatible with GPG and GitHub.
|
|
6
|
+
*
|
|
7
|
+
* This module converts existing PKCS8 key material to OpenPGP format,
|
|
8
|
+
* preserving the original cryptographic material rather than generating
|
|
9
|
+
* new keys.
|
|
10
|
+
*
|
|
11
|
+
* Issue #1374
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Options for exporting a PGP key
|
|
15
|
+
*/
|
|
16
|
+
export interface ExportPGPKeyOptions {
|
|
17
|
+
/** Optional passphrase to encrypt the exported key */
|
|
18
|
+
passphrase?: string;
|
|
19
|
+
/** User IDs to associate with the key */
|
|
20
|
+
userIds?: Array<{
|
|
21
|
+
name?: string;
|
|
22
|
+
email?: string;
|
|
23
|
+
}>;
|
|
24
|
+
/** Key creation date (defaults to current time) */
|
|
25
|
+
date?: Date;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Result of exporting a PGP key
|
|
29
|
+
*/
|
|
30
|
+
export interface ExportedPGPKey {
|
|
31
|
+
/** Armored private key in OpenPGP format */
|
|
32
|
+
armoredPrivateKey: string;
|
|
33
|
+
/** Armored public key in OpenPGP format */
|
|
34
|
+
armoredPublicKey: string;
|
|
35
|
+
/** Whether the exported private key is encrypted */
|
|
36
|
+
isEncrypted: boolean;
|
|
37
|
+
/** Key fingerprint (SHA-256 of SPKI bytes, first 40 hex chars) */
|
|
38
|
+
fingerprint: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Error thrown when key export fails
|
|
42
|
+
*/
|
|
43
|
+
export declare class PGPKeyExportError extends Error {
|
|
44
|
+
readonly code: string;
|
|
45
|
+
constructor(message: string, code: string);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Export a PKCS8 private key to OpenPGP armored format
|
|
49
|
+
*
|
|
50
|
+
* This function converts existing PKCS8 RSA key material to OpenPGP format,
|
|
51
|
+
* preserving the original cryptographic material. The exported key can be
|
|
52
|
+
* used with GPG, GitHub, and other OpenPGP-compatible tools.
|
|
53
|
+
*
|
|
54
|
+
* @param privateKeyBytes - PKCS8 encoded private key bytes
|
|
55
|
+
* @param options - Export options (passphrase, userIds, date)
|
|
56
|
+
* @returns Armored private and public keys with fingerprint
|
|
57
|
+
* @throws PGPKeyExportError if export fails
|
|
58
|
+
*/
|
|
59
|
+
export declare function exportPGPKeyToArmored(privateKeyBytes: Uint8Array, options?: ExportPGPKeyOptions): Promise<ExportedPGPKey>;
|