@nivinjoseph/n-sec 6.0.2 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/.yarn/releases/yarn-4.14.1.cjs +940 -0
  2. package/.yarnrc.yml +6 -1
  3. package/README.md +114 -1
  4. package/dist/api-security/claim.js +2 -0
  5. package/dist/api-security/claim.js.map +1 -1
  6. package/dist/api-security/claims-identity.js +1 -0
  7. package/dist/api-security/claims-identity.js.map +1 -1
  8. package/dist/api-security/expired-token-exception.js +1 -0
  9. package/dist/api-security/expired-token-exception.js.map +1 -1
  10. package/dist/api-security/invalid-token-exception.js +2 -0
  11. package/dist/api-security/invalid-token-exception.js.map +1 -1
  12. package/dist/api-security/json-web-token.d.ts +1 -1
  13. package/dist/api-security/json-web-token.d.ts.map +1 -1
  14. package/dist/api-security/json-web-token.js +35 -10
  15. package/dist/api-security/json-web-token.js.map +1 -1
  16. package/dist/api-security/security-token.js +2 -0
  17. package/dist/api-security/security-token.js.map +1 -1
  18. package/dist/bin.js +1 -1
  19. package/dist/bin.js.map +1 -1
  20. package/dist/crypto/hash.d.ts +40 -0
  21. package/dist/crypto/hash.d.ts.map +1 -1
  22. package/dist/crypto/hash.js +60 -1
  23. package/dist/crypto/hash.js.map +1 -1
  24. package/dist/crypto/symmetric-encryption.d.ts +51 -3
  25. package/dist/crypto/symmetric-encryption.d.ts.map +1 -1
  26. package/dist/crypto/symmetric-encryption.js +90 -44
  27. package/dist/crypto/symmetric-encryption.js.map +1 -1
  28. package/dist/tsconfig.json +1 -0
  29. package/eslint.config.js +5 -5
  30. package/package.json +15 -15
  31. package/src/api-security/json-web-token.ts +37 -12
  32. package/src/bin.ts +1 -1
  33. package/src/crypto/hash.ts +66 -1
  34. package/src/crypto/symmetric-encryption.ts +98 -55
  35. package/test/hash.test.ts +89 -0
  36. package/test/hmac.test.ts +12 -12
  37. package/test/json-web-token.test.ts +76 -10
  38. package/test/symmetric-encryption.test.ts +51 -12
  39. package/tsconfig.json +5 -2
  40. package/.yarn/releases/yarn-4.0.2.cjs +0 -893
package/.yarnrc.yml CHANGED
@@ -1,3 +1,8 @@
1
+ approvedGitRepositories:
2
+ - "**"
3
+
4
+ enableScripts: false
5
+
1
6
  nodeLinker: node-modules
2
7
 
3
- yarnPath: .yarn/releases/yarn-4.0.2.cjs
8
+ yarnPath: .yarn/releases/yarn-4.14.1.cjs
package/README.md CHANGED
@@ -1,8 +1,121 @@
1
1
  # n-sec
2
- Security library
3
2
 
3
+ A comprehensive security library for Node.js applications providing cryptographic operations and API security features.
4
4
 
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @nivinjoseph/n-sec
9
+ # or
10
+ yarn add @nivinjoseph/n-sec
11
+ ```
12
+
13
+ ## Features
14
+
15
+ ### Cryptographic Operations
16
+
17
+ 1. **Hash**
18
+ - Secure hashing operations using SHA-512
19
+ - Generate hash digests for data
20
+ - Support for salted hashing
21
+
22
+ 2. **HMAC (Hash-based Message Authentication Code)**
23
+ - Generate HMAC signatures using SHA-256
24
+
25
+ 3. **Symmetric Encryption**
26
+ - AES-256-CBC encryption and decryption
27
+ - Secure key generation
28
+ - IV (Initialization Vector) handling
29
+
30
+ ### API Security
31
+
32
+ 1. **JSON Web Tokens (JWT)**
33
+ - JWT creation and validation
34
+ - Support for HMAC algorithm
35
+ - Token expiration handling
36
+ - Claims management
37
+
38
+ 2. **Claims-based Identity**
39
+ - Claims management
40
+ - Identity verification
41
+ - Custom claims support
42
+
43
+ 3. **Security Tokens**
44
+ - Token generation and validation
45
+ - Token expiration handling
46
+ - Invalid token detection
47
+
48
+ ## Usage
49
+
50
+ ### Cryptographic Operations
51
+
52
+ ```typescript
53
+ import { Hash, Hmac, SymmetricEncryption } from '@nivinjoseph/n-sec';
54
+
55
+ // Hashing
56
+ const hash = Hash.create('your-data');
57
+ const saltedHash = Hash.createUsingSalt('your-data', 'your-salt');
58
+
59
+ // HMAC
60
+ const hmac = Hmac.create('your-secret-key', 'your-data');
61
+
62
+ // Symmetric Encryption
63
+ const key = await SymmetricEncryption.generateKey();
64
+ const encrypted = await SymmetricEncryption.encrypt(key, 'your-data');
65
+ const decrypted = SymmetricEncryption.decrypt(key, encrypted);
66
+ ```
67
+
68
+ ### API Security
69
+
70
+ ```typescript
71
+ import { JsonWebToken, ClaimsIdentity, Claim, AlgType } from '@nivinjoseph/n-sec';
72
+
73
+ // Create a claims identity
74
+ const claims = [
75
+ new Claim('sub', 'user123'),
76
+ new Claim('role', 'admin')
77
+ ];
78
+
79
+ // Create a JWT
80
+ const jwt = JsonWebToken.fromClaims(
81
+ 'your-issuer',
82
+ AlgType.hmac,
83
+ 'your-secret-key',
84
+ Date.now() + 3600000, // 1 hour expiry
85
+ claims
86
+ );
87
+ const token = jwt.generateToken();
88
+
89
+ // Verify a JWT
90
+ const verifiedJwt = JsonWebToken.fromToken(
91
+ 'your-issuer',
92
+ AlgType.hmac,
93
+ 'your-secret-key',
94
+ token
95
+ );
96
+ const verifiedClaims = verifiedJwt.claims;
97
+ ```
98
+
99
+ ## Error Handling
100
+
101
+ The library provides specific exception types for error handling:
102
+
103
+ - `CryptoException`: Base exception for cryptographic operations
104
+ - `ExpiredTokenException`: Thrown when a token has expired
105
+ - `InvalidTokenException`: Thrown when a token is invalid
106
+
107
+ ## Requirements
108
+
109
+ - Node.js >= 20.10
110
+ - TypeScript support
111
+
112
+ ## Contributing
113
+
114
+ Feel free to submit issues and pull requests.
5
115
  For Windows development:
6
116
  - Build tools => Open PowerShell as admin and run => npm install -g windows-build-tools
7
117
  - OpenSSL => Go to https://slproweb.com/products/Win32OpenSSL.html => Get version Win64 OpenSSL v1.0.2q
8
118
 
119
+ ## License
120
+
121
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -1,6 +1,8 @@
1
1
  import { given } from "@nivinjoseph/n-defensive";
2
2
  // public
3
3
  export class Claim {
4
+ _type;
5
+ _value;
4
6
  get type() { return this._type; }
5
7
  get value() { return this._value; }
6
8
  constructor(type, value) {
@@ -1 +1 @@
1
- {"version":3,"file":"claim.js","sourceRoot":"","sources":["../../src/api-security/claim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAGjD,SAAS;AACT,MAAM,OAAO,KAAK;IAMd,IAAW,IAAI,KAAa,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,IAAW,KAAK,KAAc,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAGnD,YAAmB,IAAY,EAAE,KAAc;QAE3C,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QAEtD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAGM,MAAM,CAAC,KAAY;QAEtB,uEAAuE;QACvE,IAAI,KAAK,IAAI,IAAI;YACb,OAAO,KAAK,CAAC;QAEjB,IAAI,KAAK,KAAK,IAAI;YACd,OAAO,IAAI,CAAC;QAEhB,OAAO,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC;IAClE,CAAC;CACJ"}
1
+ {"version":3,"file":"claim.js","sourceRoot":"","sources":["../../src/api-security/claim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAGjD,SAAS;AACT,MAAM,OAAO,KAAK;IAEG,KAAK,CAAS;IACd,MAAM,CAAU;IAGjC,IAAW,IAAI,KAAa,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,IAAW,KAAK,KAAc,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAGnD,YAAmB,IAAY,EAAE,KAAc;QAE3C,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QAEtD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAGM,MAAM,CAAC,KAAY;QAEtB,uEAAuE;QACvE,IAAI,KAAK,IAAI,IAAI;YACb,OAAO,KAAK,CAAC;QAEjB,IAAI,KAAK,KAAK,IAAI;YACd,OAAO,IAAI,CAAC;QAEhB,OAAO,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC;IAClE,CAAC;CACJ"}
@@ -1,6 +1,7 @@
1
1
  import { given } from "@nivinjoseph/n-defensive";
2
2
  // public
3
3
  export class ClaimsIdentity {
4
+ _claims;
4
5
  get claims() { return this._claims; }
5
6
  constructor(claims) {
6
7
  given(claims, "claims").ensureHasValue().ensureIsArray();
@@ -1 +1 @@
1
- {"version":3,"file":"claims-identity.js","sourceRoot":"","sources":["../../src/api-security/claims-identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAIjD,SAAS;AACT,MAAM,OAAO,cAAc;IAKvB,IAAW,MAAM,KAA2B,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAGlE,YAAmB,MAA4B;QAE3C,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,aAAa,EAAE,CAAC;QAEzD,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/B,CAAC;IAGM,QAAQ,CAAC,KAAY;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;CACJ"}
1
+ {"version":3,"file":"claims-identity.js","sourceRoot":"","sources":["../../src/api-security/claims-identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAIjD,SAAS;AACT,MAAM,OAAO,cAAc;IAEN,OAAO,CAAe;IAGvC,IAAW,MAAM,KAA2B,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAGlE,YAAmB,MAA4B;QAE3C,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,aAAa,EAAE,CAAC;QAEzD,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/B,CAAC;IAGM,QAAQ,CAAC,KAAY;QAExB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;CACJ"}
@@ -2,6 +2,7 @@ import { Exception } from "@nivinjoseph/n-exception";
2
2
  import { given } from "@nivinjoseph/n-defensive";
3
3
  // public
4
4
  export class ExpiredTokenException extends Exception {
5
+ _token;
5
6
  get token() { return this._token; }
6
7
  constructor(token) {
7
8
  given(token, "token").ensureHasValue().ensureIsString();
@@ -1 +1 @@
1
- {"version":3,"file":"expired-token-exception.js","sourceRoot":"","sources":["../../src/api-security/expired-token-exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAGjD,SAAS;AACT,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IAKhD,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAGlD,YAAmB,KAAa;QAE5B,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QACxD,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,CAAC,UAAU,KAAK,eAAe,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;CACJ"}
1
+ {"version":3,"file":"expired-token-exception.js","sourceRoot":"","sources":["../../src/api-security/expired-token-exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAGjD,SAAS;AACT,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IAE/B,MAAM,CAAS;IAGhC,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAGlD,YAAmB,KAAa;QAE5B,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QACxD,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,CAAC,UAAU,KAAK,eAAe,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;CACJ"}
@@ -2,6 +2,8 @@ import { Exception } from "@nivinjoseph/n-exception";
2
2
  import { given } from "@nivinjoseph/n-defensive";
3
3
  // public
4
4
  export class InvalidTokenException extends Exception {
5
+ _token;
6
+ _reason;
5
7
  get token() { return this._token; }
6
8
  get reason() { return this._reason; }
7
9
  constructor(token, reason) {
@@ -1 +1 @@
1
- {"version":3,"file":"invalid-token-exception.js","sourceRoot":"","sources":["../../src/api-security/invalid-token-exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAGjD,SAAS;AACT,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IAMhD,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,IAAW,MAAM,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAGpD,YAAmB,KAAa,EAAE,MAAc;QAE5C,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QACxD,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QAE1D,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,CAAC,UAAU,KAAK,wBAAwB,MAAM,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IAC1B,CAAC;CACJ"}
1
+ {"version":3,"file":"invalid-token-exception.js","sourceRoot":"","sources":["../../src/api-security/invalid-token-exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAGjD,SAAS;AACT,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IAE/B,MAAM,CAAS;IACf,OAAO,CAAS;IAGjC,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,IAAW,MAAM,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAGpD,YAAmB,KAAa,EAAE,MAAc;QAE5C,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QACxD,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QAE1D,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,CAAC,UAAU,KAAK,wBAAwB,MAAM,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IAC1B,CAAC;CACJ"}
@@ -4,7 +4,7 @@ export declare class JsonWebToken {
4
4
  private readonly _issuer;
5
5
  private readonly _algType;
6
6
  private readonly _key;
7
- private readonly _isfullKey;
7
+ private readonly _isFullKey;
8
8
  private readonly _expiry;
9
9
  private readonly _claims;
10
10
  get issuer(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"json-web-token.d.ts","sourceRoot":"","sources":["../../src/api-security/json-web-token.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAOnC,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAGvC,IAAW,MAAM,IAAI,MAAM,CAAyB;IACpD,IAAW,OAAO,IAAI,OAAO,CAA0B;IACvD,IAAW,GAAG,IAAI,MAAM,CAAsB;IAC9C,IAAW,gBAAgB,IAAI,OAAO,CAA4B;IAClE,IAAW,MAAM,IAAI,MAAM,CAAyB;IACpD,IAAW,SAAS,IAAI,OAAO,CAAuC;IACtE,IAAW,MAAM,IAAI,aAAa,CAAC,KAAK,CAAC,CAAyB;IAGlE,OAAO;WAmBO,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAClF,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,YAAY;WAKzB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY;IAyEnG,OAAO,CAAC,MAAM,CAAC,SAAS;IAOjB,aAAa,IAAI,MAAM;IA0B9B,OAAO,CAAC,MAAM;CAMjB"}
1
+ {"version":3,"file":"json-web-token.d.ts","sourceRoot":"","sources":["../../src/api-security/json-web-token.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAOnC,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAGvC,IAAW,MAAM,IAAI,MAAM,CAAyB;IACpD,IAAW,OAAO,IAAI,OAAO,CAA0B;IACvD,IAAW,GAAG,IAAI,MAAM,CAAsB;IAC9C,IAAW,gBAAgB,IAAI,OAAO,CAA4B;IAClE,IAAW,MAAM,IAAI,MAAM,CAAyB;IACpD,IAAW,SAAS,IAAI,OAAO,CAAuC;IACtE,IAAW,MAAM,IAAI,aAAa,CAAC,KAAK,CAAC,CAAyB;IAGlE,OAAO;WAmBO,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAClF,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,YAAY;WAKzB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY;IAkGnG,OAAO,CAAC,MAAM,CAAC,SAAS;IAMjB,aAAa,IAAI,MAAM;IA0B9B,OAAO,CAAC,MAAM;CAMjB"}
@@ -1,5 +1,6 @@
1
1
  import { given } from "@nivinjoseph/n-defensive";
2
2
  import { InvalidOperationException } from "@nivinjoseph/n-exception";
3
+ import { timingSafeEqual } from "node:crypto";
3
4
  import { Hmac } from "./../crypto/hmac.js";
4
5
  import { AlgType } from "./alg-type.js";
5
6
  import { Claim } from "./claim.js";
@@ -8,10 +9,16 @@ import { InvalidTokenException } from "./invalid-token-exception.js";
8
9
  import { ExpiredTokenException } from "./expired-token-exception.js";
9
10
  // public
10
11
  export class JsonWebToken {
12
+ _issuer;
13
+ _algType;
14
+ _key;
15
+ _isFullKey;
16
+ _expiry;
17
+ _claims;
11
18
  get issuer() { return this._issuer; }
12
19
  get algType() { return this._algType; }
13
20
  get key() { return this._key; }
14
- get canGenerateToken() { return this._isfullKey; }
21
+ get canGenerateToken() { return this._isFullKey; }
15
22
  get expiry() { return this._expiry; }
16
23
  get isExpired() { return this._expiry <= Date.now(); }
17
24
  get claims() { return this._claims; }
@@ -26,7 +33,7 @@ export class JsonWebToken {
26
33
  this._issuer = issuer.trim();
27
34
  this._algType = algType;
28
35
  this._key = key.trim();
29
- this._isfullKey = isFullKey;
36
+ this._isFullKey = isFullKey;
30
37
  this._expiry = expiry;
31
38
  this._claims = [...claims];
32
39
  }
@@ -47,8 +54,21 @@ export class JsonWebToken {
47
54
  const headerString = tokenSplitted[0];
48
55
  const bodyString = tokenSplitted[1];
49
56
  const signature = tokenSplitted[2];
50
- const header = JsonWebToken._toObject(headerString);
51
- const body = JsonWebToken._toObject(bodyString);
57
+ let parsedHeader;
58
+ let parsedBody;
59
+ try {
60
+ parsedHeader = JsonWebToken._toObject(headerString);
61
+ parsedBody = JsonWebToken._toObject(bodyString);
62
+ }
63
+ catch {
64
+ throw new InvalidTokenException(token, "header or body could not be parsed");
65
+ }
66
+ if (parsedHeader == null || typeof parsedHeader !== "object" || Array.isArray(parsedHeader))
67
+ throw new InvalidTokenException(token, "header is not an object");
68
+ if (parsedBody == null || typeof parsedBody !== "object" || Array.isArray(parsedBody))
69
+ throw new InvalidTokenException(token, "body is not an object");
70
+ const header = parsedHeader;
71
+ const body = parsedBody;
52
72
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
53
73
  if (header.iss === undefined || header.iss === null)
54
74
  throw new InvalidTokenException(token, "iss was not present");
@@ -80,20 +100,25 @@ export class JsonWebToken {
80
100
  // throw new InvalidTokenException(token, "signature could not be verified");
81
101
  // }
82
102
  const computedSignature = Hmac.create(key, headerString + "." + bodyString);
83
- if (computedSignature !== signature)
103
+ const expected = Buffer.from(computedSignature, "utf8");
104
+ const provided = Buffer.from(signature, "utf8");
105
+ if (expected.length !== provided.length || !timingSafeEqual(expected, provided))
84
106
  throw new InvalidTokenException(token, "signature could not be verified");
107
+ const invalidBodyKeys = new Set(["__proto__", "constructor", "prototype"]);
85
108
  const claims = new Array();
86
- for (const item in body)
87
- claims.push(new Claim(item, body[item]));
109
+ for (const [type, value] of Object.entries(body)) {
110
+ if (invalidBodyKeys.has(type))
111
+ throw new InvalidTokenException(token, `body contains invalid key '${type}'`);
112
+ claims.push(new Claim(type, value));
113
+ }
88
114
  return new JsonWebToken(issuer, algType, key, false, header.exp, claims);
89
115
  }
90
116
  static _toObject(hex) {
91
117
  const json = Buffer.from(hex.toLowerCase(), "hex").toString("utf8");
92
- const obj = JSON.parse(json);
93
- return obj;
118
+ return JSON.parse(json);
94
119
  }
95
120
  generateToken() {
96
- if (!this._isfullKey)
121
+ if (!this._isFullKey)
97
122
  throw new InvalidOperationException("generating token using an instance created from token");
98
123
  const header = {
99
124
  iss: this._issuer,
@@ -1 +1 @@
1
- {"version":3,"file":"json-web-token.js","sourceRoot":"","sources":["../../src/api-security/json-web-token.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"json-web-token.js","sourceRoot":"","sources":["../../src/api-security/json-web-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,uEAAuE;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,SAAS;AACT,MAAM,OAAO,YAAY;IAEJ,OAAO,CAAS;IAChB,QAAQ,CAAU;IAClB,IAAI,CAAS;IACb,UAAU,CAAU;IACpB,OAAO,CAAS;IAChB,OAAO,CAAe;IAGvC,IAAW,MAAM,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,IAAW,OAAO,KAAc,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvD,IAAW,GAAG,KAAa,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,IAAW,gBAAgB,KAAc,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAClE,IAAW,MAAM,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,IAAW,SAAS,KAAc,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACtE,IAAW,MAAM,KAA2B,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAGlE,YAAoB,MAAc,EAAE,OAAgB,EAAE,GAAW,EAAE,SAAkB,EAAE,MAAc,EACjG,MAAoB;QAEpB,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QAC1D,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,cAAc,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACjE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QACpD,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC;QACjE,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QAC1D,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,aAAa,EAAE;aACnD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;QAElD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAC/B,CAAC;IAEM,MAAM,CAAC,UAAU,CAAC,MAAc,EAAE,OAAgB,EAAE,GAAW,EAAE,MAAc,EAClF,MAAoB;QAEpB,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxE,CAAC;IAEM,MAAM,CAAC,SAAS,CAAC,MAAc,EAAE,OAAgB,EAAE,GAAW,EAAE,KAAa;QAEhF,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC;QACzC,KAAK,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,cAAc,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACjE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC;QACnC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC;QAEvC,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QACvB,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAErB,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;YAC1B,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAElE,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QAEnC,IAAI,YAAqB,CAAC;QAC1B,IAAI,UAAmB,CAAC;QACxB,IACA,CAAC;YACG,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;YACpD,UAAU,GAAG,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACpD,CAAC;QACD,MACA,CAAC;YACG,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,oCAAoC,CAAC,CAAC;QACjF,CAAC;QAED,IAAI,YAAY,IAAI,IAAI,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;YACvF,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC;QAEtE,IAAI,UAAU,IAAI,IAAI,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;YACjF,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;QAEpE,MAAM,MAAM,GAAG,YAAsB,CAAC;QACtC,MAAM,IAAI,GAAG,UAAqC,CAAC;QAEnD,uEAAuE;QACvE,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI;YAC/C,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAElE,IAAI,MAAM,CAAC,GAAG,KAAK,MAAM;YACrB,MAAM,IAAI,qBAAqB,CAAC,KAAK,EACjC,2BAA2B,MAAM,sBAAsB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;QAE9E,uEAAuE;QACvE,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI;YAC/C,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAElE,uEAAuE;QACvE,IAAI,MAAM,CAAC,GAAG,KAAK,OAAO;YACtB,MAAM,IAAI,qBAAqB,CAAC,KAAK,EACjC,2BAA2B,OAAO,sBAAsB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;QAE/E,uEAAuE;QACvE,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,KAAK,IAAI;YAC/C,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;QAElE,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;YAC9B,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,cAAc,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC;QAEnF,IAAI,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE;YACxB,MAAM,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAE3C,gCAAgC;QAChC,IAAI;QACJ,uFAAuF;QACvF,2CAA2C;QAC3C,yFAAyF;QACzF,OAAO;QACP,OAAO;QACP,IAAI;QACJ,yGAAyG;QACzG,yBAAyB;QACzB,uFAAuF;QACvF,QAAQ;QAER,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,GAAG,GAAG,UAAU,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAChD,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC;YAC3E,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,iCAAiC,CAAC,CAAC;QAE9E,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,IAAI,KAAK,EAAS,CAAC;QAClC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAChD,CAAC;YACG,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;gBACzB,MAAM,IAAI,qBAAqB,CAAC,KAAK,EAAE,8BAA8B,IAAI,GAAG,CAAC,CAAC;YAClF,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,IAAI,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC7E,CAAC;IAEO,MAAM,CAAC,SAAS,CAAC,GAAW;QAEhC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAEM,aAAa;QAEhB,IAAI,CAAC,IAAI,CAAC,UAAU;YAChB,MAAM,IAAI,yBAAyB,CAAC,uDAAuD,CAAC,CAAC;QAEjG,MAAM,MAAM,GAAW;YACnB,GAAG,EAAE,IAAI,CAAC,OAAO;YACjB,GAAG,EAAE,IAAI,CAAC,QAAQ;YAClB,GAAG,EAAE,IAAI,CAAC,OAAO;SACpB,CAAC;QAEF,MAAM,IAAI,GAAQ,EAAE,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QAElD,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAEpE,iDAAiD;QACjD,oDAAoD;QACpD,+DAA+D;QAE/D,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QAExD,MAAM,KAAK,GAAG,aAAa,GAAG,GAAG,GAAG,SAAS,CAAC;QAC9C,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,MAAM,CAAC,GAAW;QAEtB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtD,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC;CACJ"}
@@ -1,5 +1,7 @@
1
1
  import { given } from "@nivinjoseph/n-defensive";
2
2
  export class SecurityToken {
3
+ _scheme;
4
+ _token;
3
5
  get scheme() { return this._scheme; }
4
6
  get token() { return this._token; }
5
7
  constructor(scheme, token) {
@@ -1 +1 @@
1
- {"version":3,"file":"security-token.js","sourceRoot":"","sources":["../../src/api-security/security-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEjD,MAAM,OAAO,aAAa;IAMtB,IAAW,MAAM,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAGlD,YAAmB,MAAc,EAAE,KAAa;QAE5C,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE;aACpD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QAEtB,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE;aAClD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAGM,QAAQ;QAEX,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5C,CAAC;CACJ"}
1
+ {"version":3,"file":"security-token.js","sourceRoot":"","sources":["../../src/api-security/security-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEjD,MAAM,OAAO,aAAa;IAEL,OAAO,CAAS;IAChB,MAAM,CAAS;IAGhC,IAAW,MAAM,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,IAAW,KAAK,KAAa,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAGlD,YAAmB,MAAc,EAAE,KAAa;QAE5C,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE;aACpD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QAEtB,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE;aAClD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAGM,QAAQ;QAEX,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;IAC5C,CAAC;CACJ"}
package/dist/bin.js CHANGED
@@ -13,7 +13,7 @@ async function executeCommand(command) {
13
13
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
14
14
  case SupportedCommands.generateSymmetricKey:
15
15
  {
16
- const key = await SymmetricEncryption.generateKey();
16
+ const key = SymmetricEncryption.generateKey();
17
17
  console.log("SYMMETRIC KEY => ", key);
18
18
  break;
19
19
  }
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA,oDAAoD;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAEvE,IAAK,iBAGJ;AAHD,WAAK,iBAAiB;IAElB,oEAA+C,CAAA;AACnD,CAAC,EAHI,iBAAiB,KAAjB,iBAAiB,QAGrB;AAED,MAAM,uBAAuB,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9G,KAAK,UAAU,cAAc,CAAC,OAA0B;IAEpD,+DAA+D;IAE/D,QAAQ,OAAO,EACf,CAAC;QACG,uEAAuE;QACvE,KAAK,iBAAiB,CAAC,oBAAoB;YACvC,CAAC;gBACG,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,WAAW,EAAE,CAAC;gBACpD,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;gBACtC,MAAM;YACV,CAAC;QACL;YACI,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,6BAA6B,uBAAuB,GAAG,CAAC,CAAC;IAC1G,CAAC;AACL,CAAC;AAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EACrB,CAAC;IACG,OAAO,CAAC,KAAK,CAAC,yDAAyD,uBAAuB,GAAG,CAAC,CAAC;IACnG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB;AACxC,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAsB,CAAC;AAE7C,cAAc,CAAC,OAAO,CAAC;KAClB,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KAC3B,KAAK,CAAC,CAAC,CAAC,EAAE;IAEP,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA,oDAAoD;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAEvE,IAAK,iBAGJ;AAHD,WAAK,iBAAiB;IAElB,oEAA+C,CAAA;AACnD,CAAC,EAHI,iBAAiB,KAAjB,iBAAiB,QAGrB;AAED,MAAM,uBAAuB,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9G,KAAK,UAAU,cAAc,CAAC,OAA0B;IAEpD,+DAA+D;IAE/D,QAAQ,OAAO,EACf,CAAC;QACG,uEAAuE;QACvE,KAAK,iBAAiB,CAAC,oBAAoB;YACvC,CAAC;gBACG,MAAM,GAAG,GAAG,mBAAmB,CAAC,WAAW,EAAE,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;gBACtC,MAAM;YACV,CAAC;QACL;YACI,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,6BAA6B,uBAAuB,GAAG,CAAC,CAAC;IAC1G,CAAC;AACL,CAAC;AAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EACrB,CAAC;IACG,OAAO,CAAC,KAAK,CAAC,yDAAyD,uBAAuB,GAAG,CAAC,CAAC;IACnG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB;AACxC,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAsB,CAAC;AAE7C,cAAc,CAAC,OAAO,CAAC;KAClB,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KAC3B,KAAK,CAAC,CAAC,CAAC,EAAE;IAEP,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -1,6 +1,46 @@
1
1
  export declare class Hash {
2
2
  private constructor();
3
3
  static create(value: string): string;
4
+ /**
5
+ * @deprecated Unsafe for password storage. Uses a single round of
6
+ * SHA-512, which a GPU can compute at billions of hashes/second —
7
+ * leaked hashes can be brute-forced rapidly against any wordlist.
8
+ * Additionally trims leading/trailing whitespace from both `value`
9
+ * and `salt`, so inputs differing only in whitespace collide.
10
+ *
11
+ * For password hashing, use {@link createForPassword} +
12
+ * {@link verifyPassword} instead.
13
+ */
4
14
  static createUsingSalt(value: string, salt: string): string;
15
+ /**
16
+ * Derives a 64-byte hash from `password` and `salt` using scrypt with
17
+ * parameters N=2^15, r=8, p=1 (RFC 7914 recommended defaults). Suitable
18
+ * for password storage: slow and memory-hard, so leaked hashes resist
19
+ * GPU brute-force attacks far better than a plain SHA-512.
20
+ *
21
+ * Inputs are NOT trimmed — the exact bytes of `password` and `salt` are
22
+ * hashed. Two passwords differing only in whitespace produce different
23
+ * outputs.
24
+ *
25
+ * @param password - The password to hash. Hashed as UTF-8.
26
+ * @param salt - A per-user random value (recommended: ≥16 random bytes,
27
+ * e.g. `randomBytes(16).toString("hex")`). Must be stored alongside
28
+ * the hash so the same value can be passed on verification.
29
+ * @returns A 128-character uppercase hex string (64 bytes).
30
+ */
31
+ static createForPassword(password: string, salt: string): string;
32
+ /**
33
+ * Verifies a password against a hash previously produced by
34
+ * {@link createForPassword}. The comparison is constant-time, so
35
+ * timing cannot be used to learn how many leading bytes matched.
36
+ *
37
+ * @param password - The candidate password to verify. Hashed as UTF-8.
38
+ * @param salt - The same salt that was passed to
39
+ * {@link createForPassword} when the stored hash was created.
40
+ * @param expectedHash - The previously-stored hash (hex string, any case).
41
+ * @returns `true` if the candidate matches; `false` if it doesn't,
42
+ * if `expectedHash` is not valid hex, or if lengths differ.
43
+ */
44
+ static verifyPassword(password: string, salt: string, expectedHash: string): boolean;
5
45
  }
6
46
  //# sourceMappingURL=hash.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/crypto/hash.ts"],"names":[],"mappings":"AAKA,qBAAa,IAAI;IAEb,OAAO;WAGO,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;WAU7B,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;CAyBrE"}
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/crypto/hash.ts"],"names":[],"mappings":"AAKA,qBAAa,IAAI;IAEb,OAAO;WAGO,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAU3C;;;;;;;;;OASG;WACW,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IA0BlE;;;;;;;;;;;;;;;OAeG;WACW,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAcvE;;;;;;;;;;;OAWG;WACW,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;CAY9F"}
@@ -1,5 +1,5 @@
1
1
  import { given } from "@nivinjoseph/n-defensive";
2
- import { createHash } from "node:crypto";
2
+ import { createHash, scryptSync, timingSafeEqual } from "node:crypto";
3
3
  // public
4
4
  export class Hash {
5
5
  constructor() { }
@@ -10,6 +10,16 @@ export class Hash {
10
10
  hash.update(value, "utf8");
11
11
  return hash.digest("hex").toUpperCase();
12
12
  }
13
+ /**
14
+ * @deprecated Unsafe for password storage. Uses a single round of
15
+ * SHA-512, which a GPU can compute at billions of hashes/second —
16
+ * leaked hashes can be brute-forced rapidly against any wordlist.
17
+ * Additionally trims leading/trailing whitespace from both `value`
18
+ * and `salt`, so inputs differing only in whitespace collide.
19
+ *
20
+ * For password hashing, use {@link createForPassword} +
21
+ * {@link verifyPassword} instead.
22
+ */
13
23
  static createUsingSalt(value, salt) {
14
24
  given(value, "value").ensureHasValue().ensureIsString();
15
25
  given(salt, "salt").ensureHasValue().ensureIsString();
@@ -27,5 +37,54 @@ export class Hash {
27
37
  const saltedValue = `${salt}${value}${valueReverse}${salt}${saltReverse}${salt}${valueReverse}`;
28
38
  return Hash.create(saltedValue);
29
39
  }
40
+ /**
41
+ * Derives a 64-byte hash from `password` and `salt` using scrypt with
42
+ * parameters N=2^15, r=8, p=1 (RFC 7914 recommended defaults). Suitable
43
+ * for password storage: slow and memory-hard, so leaked hashes resist
44
+ * GPU brute-force attacks far better than a plain SHA-512.
45
+ *
46
+ * Inputs are NOT trimmed — the exact bytes of `password` and `salt` are
47
+ * hashed. Two passwords differing only in whitespace produce different
48
+ * outputs.
49
+ *
50
+ * @param password - The password to hash. Hashed as UTF-8.
51
+ * @param salt - A per-user random value (recommended: ≥16 random bytes,
52
+ * e.g. `randomBytes(16).toString("hex")`). Must be stored alongside
53
+ * the hash so the same value can be passed on verification.
54
+ * @returns A 128-character uppercase hex string (64 bytes).
55
+ */
56
+ static createForPassword(password, salt) {
57
+ given(password, "password").ensureHasValue().ensureIsString();
58
+ given(salt, "salt").ensureHasValue().ensureIsString();
59
+ const derived = scryptSync(password, salt, 64, {
60
+ N: 1 << 15,
61
+ r: 8,
62
+ p: 1,
63
+ maxmem: 64 * 1024 * 1024
64
+ });
65
+ return derived.toString("hex").toUpperCase();
66
+ }
67
+ /**
68
+ * Verifies a password against a hash previously produced by
69
+ * {@link createForPassword}. The comparison is constant-time, so
70
+ * timing cannot be used to learn how many leading bytes matched.
71
+ *
72
+ * @param password - The candidate password to verify. Hashed as UTF-8.
73
+ * @param salt - The same salt that was passed to
74
+ * {@link createForPassword} when the stored hash was created.
75
+ * @param expectedHash - The previously-stored hash (hex string, any case).
76
+ * @returns `true` if the candidate matches; `false` if it doesn't,
77
+ * if `expectedHash` is not valid hex, or if lengths differ.
78
+ */
79
+ static verifyPassword(password, salt, expectedHash) {
80
+ given(password, "password").ensureHasValue().ensureIsString();
81
+ given(salt, "salt").ensureHasValue().ensureIsString();
82
+ given(expectedHash, "expectedHash").ensureHasValue().ensureIsString();
83
+ const computed = Buffer.from(Hash.createForPassword(password, salt), "hex");
84
+ const expected = Buffer.from(expectedHash, "hex");
85
+ if (computed.length !== expected.length)
86
+ return false;
87
+ return timingSafeEqual(computed, expected);
88
+ }
30
89
  }
31
90
  //# sourceMappingURL=hash.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/crypto/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,SAAS;AACT,MAAM,OAAO,IAAI;IAEb,gBAAwB,CAAC;IAGlB,MAAM,CAAC,MAAM,CAAC,KAAa;QAE9B,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QACxD,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAErB,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,CAAC;IAEM,MAAM,CAAC,eAAe,CAAC,KAAa,EAAE,IAAY;QAErD,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QACxD,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;QAEtD,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAEnB,MAAM,OAAO,GAAG,CAAC,GAAW,EAAU,EAAE;YAEpC,IAAI,GAAG,GAAG,EAAE,CAAC;YACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;gBAC/B,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;YACvB,OAAO,GAAG,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAElC,8FAA8F;QAE9F,MAAM,WAAW,GAAG,GAAG,IAAI,GAAG,KAAK,GAAG,YAAY,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,GAAG,YAAY,EAAE,CAAC;QAEhG,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;CACJ"}
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/crypto/hash.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,55 @@
1
1
  export declare class SymmetricEncryption {
2
2
  private constructor();
3
- static generateKey(): Promise<string>;
4
- static encrypt(key: string, value: string): Promise<string>;
5
- static decrypt(key: string, value: string): string;
3
+ /**
4
+ * Generates a cryptographically random 256-bit key suitable for use with
5
+ * {@link encrypt} and {@link decrypt}.
6
+ *
7
+ * @returns A 64-character uppercase hex string (32 bytes) sourced from the
8
+ * platform CSPRNG via Node's `crypto.randomBytes`.
9
+ */
10
+ static generateKey(): string;
11
+ /**
12
+ * Encrypts a UTF-8 string using AES-256-GCM with a fresh random 96-bit IV.
13
+ *
14
+ * The result is an authenticated ciphertext: any bit-flip, truncation, or
15
+ * substitution will cause {@link decrypt} to throw a {@link CryptoException}.
16
+ *
17
+ * @param key - A 64-character hex string (32 bytes) as produced by
18
+ * {@link generateKey}. Case-insensitive.
19
+ * @param value - The plaintext to encrypt. Interpreted as UTF-8.
20
+ * @param aad - Optional Additional Authenticated Data. When supplied, its
21
+ * UTF-8 bytes are bound into the auth tag but not stored in the output;
22
+ * the exact same `aad` must be passed to {@link decrypt}, otherwise
23
+ * decryption will fail. Use this to bind a ciphertext to its context
24
+ * (e.g. `` `user:${userId}` ``) so a valid ciphertext from one record
25
+ * cannot be substituted into another.
26
+ * @returns An uppercase hex string in the form `IV.CIPHERTEXT.TAG`, where
27
+ * `IV` is 24 hex chars (12 bytes), `TAG` is 32 hex chars (16 bytes), and
28
+ * `CIPHERTEXT` is the encrypted payload.
29
+ * @throws {CryptoException} If `key` is not exactly 64 hex characters.
30
+ */
31
+ static encrypt(key: string, value: string, aad?: string): string;
32
+ /**
33
+ * Decrypts a ciphertext produced by {@link encrypt} and returns the
34
+ * original UTF-8 plaintext. Integrity is verified via the GCM auth tag
35
+ * before the plaintext is returned — if verification fails, nothing is
36
+ * returned.
37
+ *
38
+ * @param key - The same 64-character hex key that was used to encrypt.
39
+ * Case-insensitive.
40
+ * @param value - The ciphertext string in `IV.CIPHERTEXT.TAG` form as
41
+ * produced by {@link encrypt}.
42
+ * @param aad - The same Additional Authenticated Data that was supplied
43
+ * to {@link encrypt}, or omitted if none was supplied. Any mismatch
44
+ * (wrong value, supplied here but not at encrypt, or vice versa) will
45
+ * cause the auth tag check to fail.
46
+ * @returns The original plaintext decoded as UTF-8.
47
+ * @throws {CryptoException} If `key` is not exactly 64 hex characters,
48
+ * if `value` is not in the expected `IV.CIPHERTEXT.TAG` format with
49
+ * correct component lengths, or if the auth tag verification fails
50
+ * (wrong key, tampered ciphertext, or mismatched `aad`).
51
+ */
52
+ static decrypt(key: string, value: string, aad?: string): string;
53
+ private static _decodeKey;
6
54
  }
7
55
  //# sourceMappingURL=symmetric-encryption.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"symmetric-encryption.d.ts","sourceRoot":"","sources":["../../src/crypto/symmetric-encryption.ts"],"names":[],"mappings":"AAMA,qBAAa,mBAAmB;IAE5B,OAAO;WAGO,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;WAiB9B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;WAmCpD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;CAkB5D"}
1
+ {"version":3,"file":"symmetric-encryption.d.ts","sourceRoot":"","sources":["../../src/crypto/symmetric-encryption.ts"],"names":[],"mappings":"AAMA,qBAAa,mBAAmB;IAE5B,OAAO;IAGP;;;;;;OAMG;WACW,WAAW,IAAI,MAAM;IAKnC;;;;;;;;;;;;;;;;;;;OAmBG;WACW,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM;IAoBvE;;;;;;;;;;;;;;;;;;;OAmBG;WACW,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM;IAkCvE,OAAO,CAAC,MAAM,CAAC,UAAU;CAO5B"}