@getmyenv/crypto 0.1.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/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/backup.d.ts +29 -0
- package/dist/backup.d.ts.map +1 -0
- package/dist/backup.js +42 -0
- package/dist/backup.js.map +1 -0
- package/dist/bytes.d.ts +7 -0
- package/dist/bytes.d.ts.map +1 -0
- package/dist/bytes.js +46 -0
- package/dist/bytes.js.map +1 -0
- package/dist/envelope.d.ts +30 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +110 -0
- package/dist/envelope.js.map +1 -0
- package/dist/envelope.test.d.ts +2 -0
- package/dist/envelope.test.d.ts.map +1 -0
- package/dist/envelope.test.js +66 -0
- package/dist/envelope.test.js.map +1 -0
- package/dist/identity.d.ts +12 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +24 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/kdf.d.ts +9 -0
- package/dist/kdf.d.ts.map +1 -0
- package/dist/kdf.js +28 -0
- package/dist/kdf.js.map +1 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 getenv.dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/backup.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { EncryptedBackupEnvelope, EncryptedSecretPayload, WrappedProjectKey } from "./types.js";
|
|
2
|
+
import { encryptSecret, decryptSecret } from "./envelope.js";
|
|
3
|
+
export declare function createBackupEnvelope(input: {
|
|
4
|
+
projectName: string;
|
|
5
|
+
wrappedProjectKey: WrappedProjectKey;
|
|
6
|
+
secrets: Array<{
|
|
7
|
+
name: string;
|
|
8
|
+
environment: string;
|
|
9
|
+
status: "active" | "revoked" | "placeholder";
|
|
10
|
+
expiresAt: string | null;
|
|
11
|
+
payload: EncryptedSecretPayload | null;
|
|
12
|
+
}>;
|
|
13
|
+
}): EncryptedBackupEnvelope;
|
|
14
|
+
export declare function serializeBackup(envelope: EncryptedBackupEnvelope): string;
|
|
15
|
+
export declare function parseBackup(raw: string): EncryptedBackupEnvelope;
|
|
16
|
+
/**
|
|
17
|
+
* Decrypt all secrets from a backup using the vault password.
|
|
18
|
+
* Does not require getmyenv SaaS availability.
|
|
19
|
+
* Placeholders (null payload) restore as empty values.
|
|
20
|
+
*/
|
|
21
|
+
export declare function restoreSecretsFromBackup(vaultPassword: string, envelope: EncryptedBackupEnvelope): Promise<Array<{
|
|
22
|
+
name: string;
|
|
23
|
+
environment: string;
|
|
24
|
+
value: string;
|
|
25
|
+
status: "active" | "revoked" | "placeholder";
|
|
26
|
+
expiresAt: string | null;
|
|
27
|
+
}>>;
|
|
28
|
+
export { encryptSecret, decryptSecret };
|
|
29
|
+
//# sourceMappingURL=backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../src/backup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAErG,OAAO,EAAE,aAAa,EAAE,aAAa,EAAoB,MAAM,eAAe,CAAC;AAE/E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;QAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;KACxC,CAAC,CAAC;CACJ,GAAG,uBAAuB,CAS1B;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,uBAAuB,GAAG,MAAM,CAEzE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,uBAAuB,CAShE;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,uBAAuB,GAChC,OAAO,CACR,KAAK,CAAC;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;IAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC,CACH,CASA;AAED,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC"}
|
package/dist/backup.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { CRYPTO_FORMAT_VERSION } from "./types.js";
|
|
2
|
+
import { encryptSecret, decryptSecret, unwrapProjectKey } from "./envelope.js";
|
|
3
|
+
export function createBackupEnvelope(input) {
|
|
4
|
+
return {
|
|
5
|
+
format: "getmyenv-backup",
|
|
6
|
+
version: CRYPTO_FORMAT_VERSION,
|
|
7
|
+
createdAt: new Date().toISOString(),
|
|
8
|
+
projectName: input.projectName,
|
|
9
|
+
wrappedProjectKey: input.wrappedProjectKey,
|
|
10
|
+
secrets: input.secrets,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function serializeBackup(envelope) {
|
|
14
|
+
return JSON.stringify(envelope, null, 2);
|
|
15
|
+
}
|
|
16
|
+
export function parseBackup(raw) {
|
|
17
|
+
const parsed = JSON.parse(raw);
|
|
18
|
+
if (parsed.format !== "getmyenv-backup") {
|
|
19
|
+
throw new Error("Not a getmyenv backup file");
|
|
20
|
+
}
|
|
21
|
+
if (parsed.version !== CRYPTO_FORMAT_VERSION) {
|
|
22
|
+
throw new Error(`Unsupported backup version: ${parsed.version}`);
|
|
23
|
+
}
|
|
24
|
+
return parsed;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Decrypt all secrets from a backup using the vault password.
|
|
28
|
+
* Does not require getmyenv SaaS availability.
|
|
29
|
+
* Placeholders (null payload) restore as empty values.
|
|
30
|
+
*/
|
|
31
|
+
export async function restoreSecretsFromBackup(vaultPassword, envelope) {
|
|
32
|
+
const pek = await unwrapProjectKey(vaultPassword, envelope.wrappedProjectKey);
|
|
33
|
+
return envelope.secrets.map((s) => ({
|
|
34
|
+
name: s.name,
|
|
35
|
+
environment: s.environment,
|
|
36
|
+
value: s.payload ? decryptSecret(pek, s.payload) : "",
|
|
37
|
+
status: s.status === "placeholder" || !s.payload ? "placeholder" : s.status,
|
|
38
|
+
expiresAt: s.expiresAt,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
export { encryptSecret, decryptSecret };
|
|
42
|
+
//# sourceMappingURL=backup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backup.js","sourceRoot":"","sources":["../src/backup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE/E,MAAM,UAAU,oBAAoB,CAAC,KAUpC;IACC,OAAO;QACL,MAAM,EAAE,iBAAiB;QACzB,OAAO,EAAE,qBAAqB;QAC9B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAiC;IAC/D,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;IAC1D,IAAI,MAAM,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,KAAK,qBAAqB,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,aAAqB,EACrB,QAAiC;IAUjC,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,aAAa,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAC9E,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAClC,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;QACrD,MAAM,EAAE,CAAC,CAAC,MAAM,KAAK,aAAa,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM;QAC3E,SAAS,EAAE,CAAC,CAAC,SAAS;KACvB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC"}
|
package/dist/bytes.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function bytesToBase64(bytes: Uint8Array): string;
|
|
2
|
+
export declare function base64ToBytes(b64: string): Uint8Array;
|
|
3
|
+
export declare function getRandomBytes(length: number): Uint8Array;
|
|
4
|
+
export declare function utf8Encode(text: string): Uint8Array;
|
|
5
|
+
export declare function utf8Decode(bytes: Uint8Array): string;
|
|
6
|
+
export declare function concatBytes(...parts: Uint8Array[]): Uint8Array;
|
|
7
|
+
//# sourceMappingURL=bytes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CASvD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAUrD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAOzD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAEnD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEpD;AAED,wBAAgB,WAAW,CAAC,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,CAS9D"}
|
package/dist/bytes.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export function bytesToBase64(bytes) {
|
|
2
|
+
if (typeof Buffer !== "undefined") {
|
|
3
|
+
return Buffer.from(bytes).toString("base64");
|
|
4
|
+
}
|
|
5
|
+
let binary = "";
|
|
6
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
7
|
+
binary += String.fromCharCode(bytes[i]);
|
|
8
|
+
}
|
|
9
|
+
return btoa(binary);
|
|
10
|
+
}
|
|
11
|
+
export function base64ToBytes(b64) {
|
|
12
|
+
if (typeof Buffer !== "undefined") {
|
|
13
|
+
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
14
|
+
}
|
|
15
|
+
const binary = atob(b64);
|
|
16
|
+
const bytes = new Uint8Array(binary.length);
|
|
17
|
+
for (let i = 0; i < binary.length; i++) {
|
|
18
|
+
bytes[i] = binary.charCodeAt(i);
|
|
19
|
+
}
|
|
20
|
+
return bytes;
|
|
21
|
+
}
|
|
22
|
+
export function getRandomBytes(length) {
|
|
23
|
+
const bytes = new Uint8Array(length);
|
|
24
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
25
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
26
|
+
return bytes;
|
|
27
|
+
}
|
|
28
|
+
throw new Error("Secure random generation is not available");
|
|
29
|
+
}
|
|
30
|
+
export function utf8Encode(text) {
|
|
31
|
+
return new TextEncoder().encode(text);
|
|
32
|
+
}
|
|
33
|
+
export function utf8Decode(bytes) {
|
|
34
|
+
return new TextDecoder().decode(bytes);
|
|
35
|
+
}
|
|
36
|
+
export function concatBytes(...parts) {
|
|
37
|
+
const total = parts.reduce((n, p) => n + p.length, 0);
|
|
38
|
+
const out = new Uint8Array(total);
|
|
39
|
+
let offset = 0;
|
|
40
|
+
for (const part of parts) {
|
|
41
|
+
out.set(part, offset);
|
|
42
|
+
offset += part.length;
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=bytes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.js","sourceRoot":"","sources":["../src/bytes.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,OAAO,UAAU,CAAC,MAAM,EAAE,eAAe,KAAK,UAAU,EAAE,CAAC;QAC7D,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAiB;IAC1C,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAG,KAAmB;IAChD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtB,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IACxB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type EncryptedSecretPayload, type WrappedProjectKey } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Create a new project encryption key and wrap it with a password-derived KEK.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createWrappedProjectKey(vaultPassword: string): Promise<{
|
|
6
|
+
pek: Uint8Array;
|
|
7
|
+
wrapped: WrappedProjectKey;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Unwrap (decrypt) the project encryption key using the vault password.
|
|
11
|
+
*/
|
|
12
|
+
export declare function unwrapProjectKey(vaultPassword: string, wrapped: WrappedProjectKey): Promise<Uint8Array>;
|
|
13
|
+
/**
|
|
14
|
+
* Change vault password: unwrap PEK with old password, rewrap with new.
|
|
15
|
+
* Secret ciphertext does NOT need to be re-encrypted.
|
|
16
|
+
*/
|
|
17
|
+
export declare function rewrapProjectKey(oldPassword: string, newPassword: string, wrapped: WrappedProjectKey): Promise<WrappedProjectKey>;
|
|
18
|
+
/**
|
|
19
|
+
* Encrypt a secret value with the project encryption key.
|
|
20
|
+
*/
|
|
21
|
+
export declare function encryptSecret(pek: Uint8Array, plaintext: string): EncryptedSecretPayload;
|
|
22
|
+
/**
|
|
23
|
+
* Decrypt a secret value with the project encryption key.
|
|
24
|
+
*/
|
|
25
|
+
export declare function decryptSecret(pek: Uint8Array, payload: EncryptedSecretPayload): string;
|
|
26
|
+
export declare function serializePayload(payload: EncryptedSecretPayload): string;
|
|
27
|
+
export declare function parsePayload(raw: string): EncryptedSecretPayload;
|
|
28
|
+
export declare function serializeWrappedKey(wrapped: WrappedProjectKey): string;
|
|
29
|
+
export declare function parseWrappedKey(raw: string): WrappedProjectKey;
|
|
30
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAC;AA+BpB;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAgB1D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,UAAU,CAAC,CASrB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,iBAAiB,CAAC,CAa5B;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,MAAM,GAChB,sBAAsB,CAQxB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,sBAAsB,GAC9B,MAAM,CAaR;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAExE;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAMhE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAEtE;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAM9D"}
|
package/dist/envelope.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { gcm } from "@noble/ciphers/aes.js";
|
|
2
|
+
import { ALGORITHM, CRYPTO_FORMAT_VERSION, DEFAULT_KDF_PARAMS, KDF, } from "./types.js";
|
|
3
|
+
import { base64ToBytes, bytesToBase64, getRandomBytes, utf8Decode, utf8Encode, } from "./bytes.js";
|
|
4
|
+
import { deriveKek, generateProjectKey, generateSalt } from "./kdf.js";
|
|
5
|
+
const NONCE_LENGTH = 12;
|
|
6
|
+
function aesGcmEncrypt(key, plaintext) {
|
|
7
|
+
const nonce = getRandomBytes(NONCE_LENGTH);
|
|
8
|
+
const aes = gcm(key, nonce);
|
|
9
|
+
const ciphertext = aes.encrypt(plaintext);
|
|
10
|
+
return { nonce, ciphertext };
|
|
11
|
+
}
|
|
12
|
+
function aesGcmDecrypt(key, nonce, ciphertext) {
|
|
13
|
+
const aes = gcm(key, nonce);
|
|
14
|
+
return aes.decrypt(ciphertext);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create a new project encryption key and wrap it with a password-derived KEK.
|
|
18
|
+
*/
|
|
19
|
+
export async function createWrappedProjectKey(vaultPassword) {
|
|
20
|
+
const salt = generateSalt();
|
|
21
|
+
const kek = await deriveKek(vaultPassword, salt);
|
|
22
|
+
const pek = generateProjectKey();
|
|
23
|
+
const { nonce, ciphertext } = aesGcmEncrypt(kek, pek);
|
|
24
|
+
const wrapped = {
|
|
25
|
+
version: CRYPTO_FORMAT_VERSION,
|
|
26
|
+
salt: bytesToBase64(salt),
|
|
27
|
+
wrappedKey: bytesToBase64(ciphertext),
|
|
28
|
+
wrappedKeyNonce: bytesToBase64(nonce),
|
|
29
|
+
kdf: KDF,
|
|
30
|
+
kdfParams: { ...DEFAULT_KDF_PARAMS },
|
|
31
|
+
};
|
|
32
|
+
return { pek, wrapped };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Unwrap (decrypt) the project encryption key using the vault password.
|
|
36
|
+
*/
|
|
37
|
+
export async function unwrapProjectKey(vaultPassword, wrapped) {
|
|
38
|
+
if (wrapped.version !== CRYPTO_FORMAT_VERSION) {
|
|
39
|
+
throw new Error(`Unsupported wrapped key version: ${wrapped.version}`);
|
|
40
|
+
}
|
|
41
|
+
const salt = base64ToBytes(wrapped.salt);
|
|
42
|
+
const kek = await deriveKek(vaultPassword, salt, wrapped.kdfParams);
|
|
43
|
+
const nonce = base64ToBytes(wrapped.wrappedKeyNonce);
|
|
44
|
+
const ciphertext = base64ToBytes(wrapped.wrappedKey);
|
|
45
|
+
return aesGcmDecrypt(kek, nonce, ciphertext);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Change vault password: unwrap PEK with old password, rewrap with new.
|
|
49
|
+
* Secret ciphertext does NOT need to be re-encrypted.
|
|
50
|
+
*/
|
|
51
|
+
export async function rewrapProjectKey(oldPassword, newPassword, wrapped) {
|
|
52
|
+
const pek = await unwrapProjectKey(oldPassword, wrapped);
|
|
53
|
+
const salt = generateSalt();
|
|
54
|
+
const kek = await deriveKek(newPassword, salt);
|
|
55
|
+
const { nonce, ciphertext } = aesGcmEncrypt(kek, pek);
|
|
56
|
+
return {
|
|
57
|
+
version: CRYPTO_FORMAT_VERSION,
|
|
58
|
+
salt: bytesToBase64(salt),
|
|
59
|
+
wrappedKey: bytesToBase64(ciphertext),
|
|
60
|
+
wrappedKeyNonce: bytesToBase64(nonce),
|
|
61
|
+
kdf: KDF,
|
|
62
|
+
kdfParams: { ...DEFAULT_KDF_PARAMS },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Encrypt a secret value with the project encryption key.
|
|
67
|
+
*/
|
|
68
|
+
export function encryptSecret(pek, plaintext) {
|
|
69
|
+
const { nonce, ciphertext } = aesGcmEncrypt(pek, utf8Encode(plaintext));
|
|
70
|
+
return {
|
|
71
|
+
version: CRYPTO_FORMAT_VERSION,
|
|
72
|
+
algorithm: ALGORITHM,
|
|
73
|
+
nonce: bytesToBase64(nonce),
|
|
74
|
+
ciphertext: bytesToBase64(ciphertext),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Decrypt a secret value with the project encryption key.
|
|
79
|
+
*/
|
|
80
|
+
export function decryptSecret(pek, payload) {
|
|
81
|
+
if (payload.version !== CRYPTO_FORMAT_VERSION) {
|
|
82
|
+
throw new Error(`Unsupported secret payload version: ${payload.version}`);
|
|
83
|
+
}
|
|
84
|
+
if (payload.algorithm !== ALGORITHM) {
|
|
85
|
+
throw new Error(`Unsupported algorithm: ${payload.algorithm}`);
|
|
86
|
+
}
|
|
87
|
+
const plaintext = aesGcmDecrypt(pek, base64ToBytes(payload.nonce), base64ToBytes(payload.ciphertext));
|
|
88
|
+
return utf8Decode(plaintext);
|
|
89
|
+
}
|
|
90
|
+
export function serializePayload(payload) {
|
|
91
|
+
return JSON.stringify(payload);
|
|
92
|
+
}
|
|
93
|
+
export function parsePayload(raw) {
|
|
94
|
+
const parsed = JSON.parse(raw);
|
|
95
|
+
if (parsed.version !== CRYPTO_FORMAT_VERSION || !parsed.nonce || !parsed.ciphertext) {
|
|
96
|
+
throw new Error("Invalid encrypted secret payload");
|
|
97
|
+
}
|
|
98
|
+
return parsed;
|
|
99
|
+
}
|
|
100
|
+
export function serializeWrappedKey(wrapped) {
|
|
101
|
+
return JSON.stringify(wrapped);
|
|
102
|
+
}
|
|
103
|
+
export function parseWrappedKey(raw) {
|
|
104
|
+
const parsed = JSON.parse(raw);
|
|
105
|
+
if (parsed.version !== CRYPTO_FORMAT_VERSION || !parsed.wrappedKey || !parsed.salt) {
|
|
106
|
+
throw new Error("Invalid wrapped project key");
|
|
107
|
+
}
|
|
108
|
+
return parsed;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.test.d.ts","sourceRoot":"","sources":["../src/envelope.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { createWrappedProjectKey, unwrapProjectKey, rewrapProjectKey, encryptSecret, decryptSecret, createBackupEnvelope, parseBackup, serializeBackup, restoreSecretsFromBackup, generateDevelopmentIdentity, signAccessRequest, verifyAccessRequest, } from "./index.js";
|
|
3
|
+
describe("envelope encryption", () => {
|
|
4
|
+
it("encrypts and decrypts a secret with PEK", async () => {
|
|
5
|
+
const { pek, wrapped } = await createWrappedProjectKey("test-vault-password");
|
|
6
|
+
const payload = encryptSecret(pek, "sk-live-example");
|
|
7
|
+
expect(payload.version).toBe(1);
|
|
8
|
+
expect(decryptSecret(pek, payload)).toBe("sk-live-example");
|
|
9
|
+
const unwrapped = await unwrapProjectKey("test-vault-password", wrapped);
|
|
10
|
+
expect(decryptSecret(unwrapped, payload)).toBe("sk-live-example");
|
|
11
|
+
});
|
|
12
|
+
it("rewraps PEK on password change without re-encrypting secrets", async () => {
|
|
13
|
+
const { pek, wrapped } = await createWrappedProjectKey("old-password");
|
|
14
|
+
const payload = encryptSecret(pek, "DATABASE_URL=postgres://...");
|
|
15
|
+
const rewrapped = await rewrapProjectKey("old-password", "new-password", wrapped);
|
|
16
|
+
const newPek = await unwrapProjectKey("new-password", rewrapped);
|
|
17
|
+
expect(decryptSecret(newPek, payload)).toBe("DATABASE_URL=postgres://...");
|
|
18
|
+
});
|
|
19
|
+
it("rejects wrong password", async () => {
|
|
20
|
+
const { wrapped } = await createWrappedProjectKey("correct");
|
|
21
|
+
await expect(unwrapProjectKey("wrong", wrapped)).rejects.toThrow();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe("backup", () => {
|
|
25
|
+
it("creates portable encrypted backup and restores", async () => {
|
|
26
|
+
const { pek, wrapped } = await createWrappedProjectKey("backup-pass");
|
|
27
|
+
const payload = encryptSecret(pek, "secret-value");
|
|
28
|
+
const envelope = createBackupEnvelope({
|
|
29
|
+
projectName: "my-app",
|
|
30
|
+
wrappedProjectKey: wrapped,
|
|
31
|
+
secrets: [
|
|
32
|
+
{
|
|
33
|
+
name: "API_KEY",
|
|
34
|
+
environment: "Development",
|
|
35
|
+
status: "active",
|
|
36
|
+
expiresAt: null,
|
|
37
|
+
payload,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "PENDING_KEY",
|
|
41
|
+
environment: "Production",
|
|
42
|
+
status: "placeholder",
|
|
43
|
+
expiresAt: null,
|
|
44
|
+
payload: null,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
const raw = serializeBackup(envelope);
|
|
49
|
+
const parsed = parseBackup(raw);
|
|
50
|
+
const restored = await restoreSecretsFromBackup("backup-pass", parsed);
|
|
51
|
+
expect(restored[0]?.value).toBe("secret-value");
|
|
52
|
+
expect(restored[1]?.status).toBe("placeholder");
|
|
53
|
+
expect(restored[1]?.value).toBe("");
|
|
54
|
+
expect(raw).not.toContain("secret-value");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe("development identity", () => {
|
|
58
|
+
it("signs and verifies access requests", () => {
|
|
59
|
+
const id = generateDevelopmentIdentity();
|
|
60
|
+
const msg = "request:abc:project:env";
|
|
61
|
+
const sig = signAccessRequest(id.privateKey, msg);
|
|
62
|
+
expect(verifyAccessRequest(id.publicKey, msg, sig)).toBe(true);
|
|
63
|
+
expect(verifyAccessRequest(id.publicKey, "tampered", sig)).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=envelope.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.test.js","sourceRoot":"","sources":["../src/envelope.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development machine identity keypair.
|
|
3
|
+
* Identifies the environment - does NOT decrypt secrets or grant permanent access.
|
|
4
|
+
*/
|
|
5
|
+
export type DevelopmentKeypair = {
|
|
6
|
+
publicKey: string;
|
|
7
|
+
privateKey: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function generateDevelopmentIdentity(): DevelopmentKeypair;
|
|
10
|
+
export declare function signAccessRequest(privateKeyB64: string, message: string): string;
|
|
11
|
+
export declare function verifyAccessRequest(publicKeyB64: string, message: string, signatureB64: string): boolean;
|
|
12
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,2BAA2B,IAAI,kBAAkB,CAOhE;AAED,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GACd,MAAM,CAIR;AAED,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAUT"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ed25519 } from "@noble/curves/ed25519.js";
|
|
2
|
+
import { bytesToBase64, base64ToBytes, getRandomBytes, utf8Encode } from "./bytes.js";
|
|
3
|
+
export function generateDevelopmentIdentity() {
|
|
4
|
+
const privateKey = getRandomBytes(32);
|
|
5
|
+
const publicKey = ed25519.getPublicKey(privateKey);
|
|
6
|
+
return {
|
|
7
|
+
publicKey: bytesToBase64(publicKey),
|
|
8
|
+
privateKey: bytesToBase64(privateKey),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function signAccessRequest(privateKeyB64, message) {
|
|
12
|
+
const privateKey = base64ToBytes(privateKeyB64);
|
|
13
|
+
const sig = ed25519.sign(utf8Encode(message), privateKey);
|
|
14
|
+
return bytesToBase64(sig);
|
|
15
|
+
}
|
|
16
|
+
export function verifyAccessRequest(publicKeyB64, message, signatureB64) {
|
|
17
|
+
try {
|
|
18
|
+
return ed25519.verify(base64ToBytes(signatureB64), utf8Encode(message), base64ToBytes(publicKeyB64));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAWtF,MAAM,UAAU,2BAA2B;IACzC,MAAM,UAAU,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO;QACL,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC;QACnC,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,aAAqB,EACrB,OAAe;IAEf,MAAM,UAAU,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC;IAC1D,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,YAAoB,EACpB,OAAe,EACf,YAAoB;IAEpB,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,MAAM,CACnB,aAAa,CAAC,YAAY,CAAC,EAC3B,UAAU,CAAC,OAAO,CAAC,EACnB,aAAa,CAAC,YAAY,CAAC,CAC5B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
|
package/dist/kdf.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type KdfParams } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Derive a Key Encryption Key (KEK) from a vault password using Argon2id.
|
|
4
|
+
*/
|
|
5
|
+
export declare function deriveKek(password: string, salt: Uint8Array, params?: KdfParams): Promise<Uint8Array>;
|
|
6
|
+
export declare function generateSalt(length?: number): Uint8Array;
|
|
7
|
+
export declare function generateProjectKey(): Uint8Array;
|
|
8
|
+
export declare function saltToBase64(salt: Uint8Array): string;
|
|
9
|
+
//# sourceMappingURL=kdf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kdf.d.ts","sourceRoot":"","sources":["../src/kdf.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAGpB;;GAEG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,SAA8B,GACrC,OAAO,CAAC,UAAU,CAAC,CAWrB;AAED,wBAAgB,YAAY,CAAC,MAAM,SAAK,GAAG,UAAU,CAEpD;AAED,wBAAgB,kBAAkB,IAAI,UAAU,CAE/C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAErD"}
|
package/dist/kdf.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { argon2id } from "hash-wasm";
|
|
2
|
+
import { DEFAULT_KDF_PARAMS, } from "./types.js";
|
|
3
|
+
import { bytesToBase64, getRandomBytes } from "./bytes.js";
|
|
4
|
+
/**
|
|
5
|
+
* Derive a Key Encryption Key (KEK) from a vault password using Argon2id.
|
|
6
|
+
*/
|
|
7
|
+
export async function deriveKek(password, salt, params = DEFAULT_KDF_PARAMS) {
|
|
8
|
+
const hash = await argon2id({
|
|
9
|
+
password,
|
|
10
|
+
salt,
|
|
11
|
+
parallelism: params.parallelism,
|
|
12
|
+
iterations: params.iterations,
|
|
13
|
+
memorySize: params.memory,
|
|
14
|
+
hashLength: params.hashLength,
|
|
15
|
+
outputType: "binary",
|
|
16
|
+
});
|
|
17
|
+
return hash instanceof Uint8Array ? hash : new Uint8Array(hash);
|
|
18
|
+
}
|
|
19
|
+
export function generateSalt(length = 16) {
|
|
20
|
+
return getRandomBytes(length);
|
|
21
|
+
}
|
|
22
|
+
export function generateProjectKey() {
|
|
23
|
+
return getRandomBytes(32);
|
|
24
|
+
}
|
|
25
|
+
export function saltToBase64(salt) {
|
|
26
|
+
return bytesToBase64(salt);
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=kdf.js.map
|
package/dist/kdf.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kdf.js","sourceRoot":"","sources":["../src/kdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EACL,kBAAkB,GAEnB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE3D;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAgB,EAChB,IAAgB,EAChB,SAAoB,kBAAkB;IAEtC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC;QAC1B,QAAQ;QACR,IAAI;QACJ,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,UAAU,EAAE,QAAQ;KACrB,CAAC,CAAC;IACH,OAAO,IAAI,YAAY,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAM,GAAG,EAAE;IACtC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,cAAc,CAAC,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Versioned getmyenv crypto protocol - shared by browser and CLI. */
|
|
2
|
+
export declare const CRYPTO_FORMAT_VERSION: 1;
|
|
3
|
+
export declare const ALGORITHM: "AES-256-GCM";
|
|
4
|
+
export declare const KDF: "argon2id";
|
|
5
|
+
/** Argon2id parameters (balanced for browser + CLI). */
|
|
6
|
+
export declare const DEFAULT_KDF_PARAMS: {
|
|
7
|
+
readonly memory: number;
|
|
8
|
+
readonly iterations: 3;
|
|
9
|
+
readonly parallelism: 1;
|
|
10
|
+
readonly hashLength: 32;
|
|
11
|
+
};
|
|
12
|
+
export type KdfParams = {
|
|
13
|
+
memory: number;
|
|
14
|
+
iterations: number;
|
|
15
|
+
parallelism: number;
|
|
16
|
+
hashLength: number;
|
|
17
|
+
};
|
|
18
|
+
/** Wrapped project encryption key (stored server-side / in backups). */
|
|
19
|
+
export type WrappedProjectKey = {
|
|
20
|
+
version: typeof CRYPTO_FORMAT_VERSION;
|
|
21
|
+
salt: string;
|
|
22
|
+
wrappedKey: string;
|
|
23
|
+
wrappedKeyNonce: string;
|
|
24
|
+
kdf: typeof KDF;
|
|
25
|
+
kdfParams: KdfParams;
|
|
26
|
+
};
|
|
27
|
+
/** Encrypted secret value payload. */
|
|
28
|
+
export type EncryptedSecretPayload = {
|
|
29
|
+
version: typeof CRYPTO_FORMAT_VERSION;
|
|
30
|
+
algorithm: typeof ALGORITHM;
|
|
31
|
+
nonce: string;
|
|
32
|
+
ciphertext: string;
|
|
33
|
+
};
|
|
34
|
+
/** Portable encrypted backup envelope. */
|
|
35
|
+
export type EncryptedBackupEnvelope = {
|
|
36
|
+
format: "getmyenv-backup";
|
|
37
|
+
version: typeof CRYPTO_FORMAT_VERSION;
|
|
38
|
+
createdAt: string;
|
|
39
|
+
projectName: string;
|
|
40
|
+
wrappedProjectKey: WrappedProjectKey;
|
|
41
|
+
secrets: Array<{
|
|
42
|
+
name: string;
|
|
43
|
+
environment: string;
|
|
44
|
+
status: "active" | "revoked" | "placeholder";
|
|
45
|
+
expiresAt: string | null;
|
|
46
|
+
/** Null for name-only placeholders. */
|
|
47
|
+
payload: EncryptedSecretPayload | null;
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,eAAO,MAAM,qBAAqB,EAAG,CAAU,CAAC;AAChD,eAAO,MAAM,SAAS,EAAG,aAAsB,CAAC;AAChD,eAAO,MAAM,GAAG,EAAG,UAAmB,CAAC;AAEvC,wDAAwD;AACxD,eAAO,MAAM,kBAAkB;;;;;CAKrB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,OAAO,qBAAqB,CAAC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,OAAO,GAAG,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF,sCAAsC;AACtC,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,OAAO,qBAAqB,CAAC;IACtC,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,0CAA0C;AAC1C,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,OAAO,qBAAqB,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;QAC7C,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,uCAAuC;QACvC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;KACxC,CAAC,CAAC;CACJ,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Versioned getmyenv crypto protocol - shared by browser and CLI. */
|
|
2
|
+
export const CRYPTO_FORMAT_VERSION = 1;
|
|
3
|
+
export const ALGORITHM = "AES-256-GCM";
|
|
4
|
+
export const KDF = "argon2id";
|
|
5
|
+
/** Argon2id parameters (balanced for browser + CLI). */
|
|
6
|
+
export const DEFAULT_KDF_PARAMS = {
|
|
7
|
+
memory: 64 * 1024, // KiB
|
|
8
|
+
iterations: 3,
|
|
9
|
+
parallelism: 1,
|
|
10
|
+
hashLength: 32,
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAU,CAAC;AAChD,MAAM,CAAC,MAAM,SAAS,GAAG,aAAsB,CAAC;AAChD,MAAM,CAAC,MAAM,GAAG,GAAG,UAAmB,CAAC;AAEvC,wDAAwD;AACxD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM;IACzB,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,EAAE;CACN,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@getmyenv/crypto",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Envelope encryption for getmyenv (Argon2id + AES-256-GCM)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/yobotn/getmyenv.git",
|
|
22
|
+
"directory": "packages/crypto"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://getmyenv.com",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@noble/ciphers": "^1.2.1",
|
|
31
|
+
"@noble/curves": "^1.8.1",
|
|
32
|
+
"@noble/hashes": "^1.7.1",
|
|
33
|
+
"hash-wasm": "^4.12.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.13.10",
|
|
37
|
+
"typescript": "^5.8.2",
|
|
38
|
+
"vitest": "^4.1.11"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc -p tsconfig.json",
|
|
42
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"lint": "tsc -p tsconfig.json --noEmit"
|
|
45
|
+
}
|
|
46
|
+
}
|