@sebastienrousseau/crypto-server 0.0.7 → 0.0.9
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 +159 -56
- package/dist/@types/types.d.ts +1 -2
- package/dist/@types/types.d.ts.map +1 -1
- package/dist/config/auth-policy.d.ts +18 -0
- package/dist/config/auth-policy.d.ts.map +1 -1
- package/dist/config/auth-policy.js +109 -0
- package/dist/enterprise/metering.d.ts.map +1 -1
- package/dist/enterprise/metering.js +2 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/auth.d.ts +4 -1
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +87 -40
- package/dist/lib/kdf-runner.d.ts +18 -0
- package/dist/lib/kdf-runner.d.ts.map +1 -0
- package/dist/lib/kdf-runner.js +27 -0
- package/dist/lib/key-store.d.ts +30 -0
- package/dist/lib/key-store.d.ts.map +1 -0
- package/dist/lib/key-store.js +126 -0
- package/dist/lib/problem.d.ts +66 -0
- package/dist/lib/problem.d.ts.map +1 -0
- package/dist/lib/problem.js +152 -0
- package/dist/routes/v1/decrypt.d.ts.map +1 -1
- package/dist/routes/v1/decrypt.js +20 -15
- package/dist/routes/v1/encrypt.d.ts.map +1 -1
- package/dist/routes/v1/encrypt.js +12 -13
- package/dist/routes/v1/generate.d.ts.map +1 -1
- package/dist/routes/v1/generate.js +22 -25
- package/dist/routes/v1/revoke.d.ts.map +1 -1
- package/dist/routes/v1/revoke.js +6 -11
- package/dist/routes/v1/verify.d.ts.map +1 -1
- package/dist/routes/v1/verify.js +6 -11
- package/dist/routes/v2/algorithms.js +1 -1
- package/dist/routes/v2/compliance.js +1 -1
- package/dist/routes/v2/encrypt.d.ts.map +1 -1
- package/dist/routes/v2/encrypt.js +1 -1
- package/dist/routes/v2/hash.d.ts.map +1 -1
- package/dist/routes/v2/hash.js +1 -1
- package/dist/routes/v2/kdf.d.ts +5 -0
- package/dist/routes/v2/kdf.d.ts.map +1 -1
- package/dist/routes/v2/kdf.js +27 -12
- package/dist/routes/v2/key-wrap.d.ts.map +1 -1
- package/dist/routes/v2/key-wrap.js +9 -3
- package/dist/routes/v2/keys.d.ts.map +1 -1
- package/dist/routes/v2/keys.js +39 -26
- package/dist/routes/v2/mac.d.ts.map +1 -1
- package/dist/routes/v2/mac.js +9 -3
- package/dist/routes/v2/multi-recipient.d.ts.map +1 -1
- package/dist/routes/v2/multi-recipient.js +12 -11
- package/dist/routes/v2/password-encrypt.d.ts.map +1 -1
- package/dist/routes/v2/password-encrypt.js +13 -46
- package/dist/routes/v2/password.d.ts +4 -0
- package/dist/routes/v2/password.d.ts.map +1 -1
- package/dist/routes/v2/password.js +28 -53
- package/dist/routes/v2/pq-hash-sign.d.ts.map +1 -1
- package/dist/routes/v2/pq-hash-sign.js +30 -24
- package/dist/routes/v2/pq-sign.d.ts.map +1 -1
- package/dist/routes/v2/pq-sign.js +30 -24
- package/dist/routes/v2/pq.d.ts.map +1 -1
- package/dist/routes/v2/pq.js +57 -38
- package/dist/routes/v2/sealedbox.d.ts.map +1 -1
- package/dist/routes/v2/sealedbox.js +32 -14
- package/dist/routes/v2/secretbox.d.ts.map +1 -1
- package/dist/routes/v2/secretbox.js +10 -3
- package/dist/routes/v2/signing.d.ts.map +1 -1
- package/dist/routes/v2/signing.js +16 -13
- package/dist/routes/v2/stream.d.ts.map +1 -1
- package/dist/routes/v2/stream.js +29 -24
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +15 -5
- package/dist/utils/keys.d.ts +17 -0
- package/dist/utils/keys.d.ts.map +1 -0
- package/dist/utils/keys.js +36 -0
- package/dist/utils/route-helpers.d.ts +1 -5
- package/dist/utils/route-helpers.d.ts.map +1 -1
- package/dist/utils/route-helpers.js +16 -10
- package/dist/utils/validation.d.ts +1 -0
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +17 -9
- package/package.json +23 -20
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.collectValidation = collectValidation;
|
|
4
4
|
exports.classifyCryptoError = classifyCryptoError;
|
|
5
|
+
const problem_1 = require("../lib/problem");
|
|
5
6
|
const validation_1 = require("./validation");
|
|
6
7
|
function collectValidation(results, reply) {
|
|
7
8
|
const errors = [];
|
|
@@ -22,21 +23,26 @@ function collectValidation(results, reply) {
|
|
|
22
23
|
}
|
|
23
24
|
return out;
|
|
24
25
|
}
|
|
26
|
+
const INPUT_ERROR_PATTERNS = [
|
|
27
|
+
/invalid hex/i,
|
|
28
|
+
/must be \d+ bytes/i,
|
|
29
|
+
/too short/i,
|
|
30
|
+
/unsupported/i,
|
|
31
|
+
/expected.*length/i,
|
|
32
|
+
/of length \d+ expected/i,
|
|
33
|
+
];
|
|
25
34
|
function classifyCryptoError(error, request, reply, operation) {
|
|
26
35
|
const msg = error instanceof Error ? error.message : String(error);
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/of length \d+ expected/i.test(msg);
|
|
36
|
+
const code = (0, problem_1.isCryptoError)(error) ? error.code : undefined;
|
|
37
|
+
const isInputError = code === undefined
|
|
38
|
+
? INPUT_ERROR_PATTERNS.some((pattern) => pattern.test(msg))
|
|
39
|
+
: (0, problem_1.cryptoErrorStatus)(code) === 400;
|
|
40
|
+
const extensions = code === undefined ? {} : { code };
|
|
33
41
|
if (isInputError) {
|
|
34
42
|
request.log.error(error, `${operation} input error`);
|
|
35
|
-
return reply
|
|
36
|
-
.status(400)
|
|
37
|
-
.send({ error: `${operation} failed: invalid input` });
|
|
43
|
+
return (0, problem_1.sendProblem)(reply, 400, "invalid-input", `${operation} failed: invalid input`, extensions);
|
|
38
44
|
}
|
|
39
45
|
request.log.error(error, `${operation} failed`);
|
|
40
|
-
return
|
|
46
|
+
return (0, problem_1.sendProblem)(reply, 500, "internal-error", `${operation} failed`, extensions);
|
|
41
47
|
}
|
|
42
48
|
//# sourceMappingURL=route-helpers.js.map
|
|
@@ -20,6 +20,7 @@ export declare function validateOptionalNumber(value: unknown, defaultValue: num
|
|
|
20
20
|
max?: number;
|
|
21
21
|
}): ValidationResult<number>;
|
|
22
22
|
export declare function validateBase64(value: unknown, fieldName: string): ValidationResult<string>;
|
|
23
|
+
export declare function isEmailShaped(value: string): boolean;
|
|
23
24
|
export declare function validateEmail(value: unknown, fieldName: string): ValidationResult<string>;
|
|
24
25
|
export declare function validateEnum<T extends string>(value: unknown, fieldName: string, allowedValues: readonly T[]): ValidationResult<T>;
|
|
25
26
|
export declare function validateDateString(value: unknown, fieldName: string): ValidationResult<Date>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAMvC,MAAM,WAAW,eAAe;IAE9B,KAAK,EAAE,MAAM,CAAC;IAEd,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAC1B;IAEE,KAAK,EAAE,IAAI,CAAC;IAEZ,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IAEE,KAAK,EAAE,KAAK,CAAC;IAEb,KAAK,EAAE,eAAe,CAAC;CACxB,CAAC;AAKN,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,gBAAgB,CAAC,MAAM,CAAC,CAiB1B;AAKD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC,gBAAgB,CAAC,MAAM,CAAC,CAqC1B;AAKD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC,gBAAgB,CAAC,MAAM,CAAC,CAK1B;AAKD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,gBAAgB,CAAC,MAAM,CAAC,CAgB1B;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAMpD;AAKD,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,gBAAgB,CAAC,MAAM,CAAC,CAc1B;AAKD,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,EAC3C,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,SAAS,CAAC,EAAE,GAC1B,gBAAgB,CAAC,CAAC,CAAC,CAcrB;AAKD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,GAChB,gBAAgB,CAAC,IAAI,CAAC,CAexB;AAMD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,eAAe,EAAE,GACxB,IAAI,CAIN;AAOD,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAKD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,OAAO,CAcT"}
|
package/dist/utils/validation.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.validateRequiredString = validateRequiredString;
|
|
|
4
4
|
exports.validateRequiredNumber = validateRequiredNumber;
|
|
5
5
|
exports.validateOptionalNumber = validateOptionalNumber;
|
|
6
6
|
exports.validateBase64 = validateBase64;
|
|
7
|
+
exports.isEmailShaped = isEmailShaped;
|
|
7
8
|
exports.validateEmail = validateEmail;
|
|
8
9
|
exports.validateEnum = validateEnum;
|
|
9
10
|
exports.validateDateString = validateDateString;
|
|
@@ -11,6 +12,7 @@ exports.sendValidationError = sendValidationError;
|
|
|
11
12
|
exports.anonymousAllowed = anonymousAllowed;
|
|
12
13
|
exports.validateApiKey = validateApiKey;
|
|
13
14
|
const crypto_1 = require("crypto");
|
|
15
|
+
const problem_1 = require("../lib/problem");
|
|
14
16
|
function validateRequiredString(value, fieldName) {
|
|
15
17
|
if (value === undefined || value === null) {
|
|
16
18
|
return {
|
|
@@ -37,6 +39,7 @@ function validateRequiredNumber(value, fieldName, options) {
|
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
41
|
const numValue = typeof value === "number" ? value : Number(value);
|
|
42
|
+
const { min, max } = options ?? {};
|
|
40
43
|
if (!Number.isFinite(numValue)) {
|
|
41
44
|
return {
|
|
42
45
|
valid: false,
|
|
@@ -46,21 +49,21 @@ function validateRequiredNumber(value, fieldName, options) {
|
|
|
46
49
|
},
|
|
47
50
|
};
|
|
48
51
|
}
|
|
49
|
-
if (
|
|
52
|
+
if (min !== undefined && numValue < min) {
|
|
50
53
|
return {
|
|
51
54
|
valid: false,
|
|
52
55
|
error: {
|
|
53
56
|
field: fieldName,
|
|
54
|
-
message: `${fieldName} must be at least ${
|
|
57
|
+
message: `${fieldName} must be at least ${min}`,
|
|
55
58
|
},
|
|
56
59
|
};
|
|
57
60
|
}
|
|
58
|
-
if (
|
|
61
|
+
if (max !== undefined && numValue > max) {
|
|
59
62
|
return {
|
|
60
63
|
valid: false,
|
|
61
64
|
error: {
|
|
62
65
|
field: fieldName,
|
|
63
|
-
message: `${fieldName} must be at most ${
|
|
66
|
+
message: `${fieldName} must be at most ${max}`,
|
|
64
67
|
},
|
|
65
68
|
};
|
|
66
69
|
}
|
|
@@ -88,12 +91,18 @@ function validateBase64(value, fieldName) {
|
|
|
88
91
|
}
|
|
89
92
|
return { valid: true, value: stringResult.value };
|
|
90
93
|
}
|
|
94
|
+
function isEmailShaped(value) {
|
|
95
|
+
const at = value.indexOf("@");
|
|
96
|
+
if (at < 1 || value.indexOf("@", at + 1) !== -1 || /\s/.test(value)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return value.slice(at + 2, -1).includes(".");
|
|
100
|
+
}
|
|
91
101
|
function validateEmail(value, fieldName) {
|
|
92
102
|
const stringResult = validateRequiredString(value, fieldName);
|
|
93
103
|
if (!stringResult.valid)
|
|
94
104
|
return stringResult;
|
|
95
|
-
|
|
96
|
-
if (!emailRegex.test(stringResult.value)) {
|
|
105
|
+
if (!isEmailShaped(stringResult.value)) {
|
|
97
106
|
return {
|
|
98
107
|
valid: false,
|
|
99
108
|
error: {
|
|
@@ -136,9 +145,8 @@ function validateDateString(value, fieldName) {
|
|
|
136
145
|
return { valid: true, value: date };
|
|
137
146
|
}
|
|
138
147
|
function sendValidationError(reply, errors) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
details: errors,
|
|
148
|
+
(0, problem_1.sendProblem)(reply, 400, "validation-failed", "Validation failed", {
|
|
149
|
+
errors,
|
|
142
150
|
});
|
|
143
151
|
}
|
|
144
152
|
function anonymousAllowed() {
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sebastienrousseau/crypto-server",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Crypto Server is a Fastify web server that exposes easy consumable REST APIs to perform low-level cryptographic operations.",
|
|
5
5
|
"author": "Sebastien Rousseau <sebastienrousseau@users.noreply.github.com>",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
7
7
|
"homepage": "https://crypto-server.io",
|
|
8
8
|
"repository": {
|
|
9
|
-
"directory": "packages/crypto-server",
|
|
10
9
|
"type": "git",
|
|
11
|
-
"url": "git
|
|
10
|
+
"url": "git+https://github.com/sebastienrousseau/crypto-service.git",
|
|
11
|
+
"directory": "packages/crypto-server"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/sebastienrousseau/crypto-service/issues"
|
|
@@ -16,16 +16,18 @@
|
|
|
16
16
|
"engines": {
|
|
17
17
|
"node": ">=22.0.0"
|
|
18
18
|
},
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
19
|
+
"type": "commonjs",
|
|
20
|
+
"main": "./dist/server.js",
|
|
21
|
+
"types": "./dist/server.d.ts",
|
|
22
22
|
"exports": {
|
|
23
23
|
".": {
|
|
24
|
-
"types": "./dist/
|
|
25
|
-
"require": "./dist/
|
|
26
|
-
"
|
|
27
|
-
}
|
|
24
|
+
"types": "./dist/server.d.ts",
|
|
25
|
+
"require": "./dist/server.js",
|
|
26
|
+
"default": "./dist/server.js"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
28
29
|
},
|
|
30
|
+
"sideEffects": false,
|
|
29
31
|
"bin": {
|
|
30
32
|
"crypto-server": "dist/index.js"
|
|
31
33
|
},
|
|
@@ -58,20 +60,21 @@
|
|
|
58
60
|
"fastify-healthcheck": "^5.1.0",
|
|
59
61
|
"uuid": "^14.0.2",
|
|
60
62
|
"winston": "^3.17.0",
|
|
61
|
-
"@sebastienrousseau/crypto-lib": "0.0.
|
|
63
|
+
"@sebastienrousseau/crypto-lib": "0.0.9"
|
|
62
64
|
},
|
|
63
65
|
"devDependencies": {
|
|
64
|
-
"@types/chai": "^
|
|
66
|
+
"@types/chai": "^5.2.3",
|
|
65
67
|
"@types/chai-as-promised": "^8.0.2",
|
|
66
|
-
"@types/mocha": "^10.0.
|
|
67
|
-
"@types/node": "^26.
|
|
68
|
+
"@types/mocha": "^10.0.10",
|
|
69
|
+
"@types/node": "^26.6.3",
|
|
68
70
|
"@types/uuid": "^11.0.0",
|
|
69
71
|
"c8": "^12.0.0",
|
|
70
|
-
"chai": "^
|
|
71
|
-
"chai-as-promised": "^
|
|
72
|
-
"
|
|
72
|
+
"chai": "^6.3.0",
|
|
73
|
+
"chai-as-promised": "^8.0.2",
|
|
74
|
+
"fast-check": "^4.10.2",
|
|
75
|
+
"mocha": "^12.0.3",
|
|
73
76
|
"openpgp": "^6.3.1",
|
|
74
|
-
"prettier": "^3.9.
|
|
77
|
+
"prettier": "^3.9.9",
|
|
75
78
|
"rimraf": "^6.1.3",
|
|
76
79
|
"ts-node": "^10.9.2",
|
|
77
80
|
"typedoc": "^0.28.20",
|
|
@@ -93,8 +96,8 @@
|
|
|
93
96
|
"scripts": {
|
|
94
97
|
"build": "tsc --build tsconfig.json",
|
|
95
98
|
"clean": "rimraf ./coverage ./dist ./docs",
|
|
96
|
-
"lint": "eslint
|
|
97
|
-
"lint:fix": "eslint --cache --fix
|
|
99
|
+
"lint": "eslint src __tests__",
|
|
100
|
+
"lint:fix": "eslint --cache --fix src __tests__",
|
|
98
101
|
"format": "prettier --write src/**/*.ts",
|
|
99
102
|
"format:check": "prettier --check \"src/**/*.ts\"",
|
|
100
103
|
"start": "node dist/index.js",
|