@digitaldefiance/node-ecies-lib 1.1.21 → 1.1.22

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 (211) hide show
  1. package/README.md +4 -0
  2. package/package.json +14 -35
  3. package/src/constants.ts +182 -0
  4. package/src/enumerations/index.ts +1 -0
  5. package/src/enumerations/pbkdf2-profile.ts +8 -0
  6. package/src/i18n/ecies-i18n-factory.ts +435 -0
  7. package/{dist/i18n/index.d.ts → src/i18n/index.ts} +0 -1
  8. package/{dist/index.d.ts → src/index.ts} +0 -1
  9. package/src/interfaces/authenticated-cipher.ts +9 -0
  10. package/src/interfaces/authenticated-decipher.ts +8 -0
  11. package/src/interfaces/checksum-config.ts +4 -0
  12. package/src/interfaces/checksum-consts.ts +13 -0
  13. package/src/interfaces/constants.ts +43 -0
  14. package/src/interfaces/ecies-consts.ts +99 -0
  15. package/src/interfaces/encryption-consts.ts +10 -0
  16. package/{dist/interfaces/index.d.ts → src/interfaces/index.ts} +0 -1
  17. package/src/interfaces/keypair-buffer-with-un-encrypted-private-key.ts +7 -0
  18. package/src/interfaces/keyring-consts.ts +5 -0
  19. package/src/interfaces/member-operational.ts +52 -0
  20. package/{dist/interfaces/member-with-mnemonic.d.ts → src/interfaces/member-with-mnemonic.ts} +3 -3
  21. package/{dist/interfaces/multi-encrypted-message.d.ts → src/interfaces/multi-encrypted-message.ts} +5 -5
  22. package/src/interfaces/multi-encrypted-parsed-header.ts +24 -0
  23. package/{dist/interfaces/pbkdf-profiles.d.ts → src/interfaces/pbkdf-profiles.ts} +2 -2
  24. package/src/interfaces/pbkdf2-result.ts +5 -0
  25. package/src/interfaces/signing-key-private-key-info.ts +12 -0
  26. package/{dist/interfaces/simple-keypair-buffer.d.ts → src/interfaces/simple-keypair-buffer.ts} +3 -3
  27. package/{dist/interfaces/simple-keypair.d.ts → src/interfaces/simple-keypair.ts} +3 -3
  28. package/src/interfaces/simple-public-key-only-buffer.ts +3 -0
  29. package/src/interfaces/simple-public-key-only.ts +3 -0
  30. package/src/interfaces/single-encrypted-parsed-header.ts +35 -0
  31. package/{dist/interfaces/wallet-seed.d.ts → src/interfaces/wallet-seed.ts} +3 -3
  32. package/src/interfaces/wrapped-key-consts.ts +6 -0
  33. package/src/member.ts +463 -0
  34. package/src/services/aes-gcm.ts +160 -0
  35. package/src/services/ecies/crypto-core.ts +213 -0
  36. package/src/services/ecies/file.ts +174 -0
  37. package/{dist/services/ecies/index.d.ts → src/services/ecies/index.ts} +0 -1
  38. package/src/services/ecies/multi-recipient.ts +583 -0
  39. package/src/services/ecies/service.ts +351 -0
  40. package/src/services/ecies/signature.ts +91 -0
  41. package/src/services/ecies/single-recipient.ts +676 -0
  42. package/src/services/ecies/utilities.ts +111 -0
  43. package/src/services/index.ts +3 -0
  44. package/src/services/pbkdf2.ts +307 -0
  45. package/{dist/types.d.ts → src/types.ts} +26 -9
  46. package/src/utils.ts +104 -0
  47. package/dist/constants.d.ts +0 -32
  48. package/dist/constants.d.ts.map +0 -1
  49. package/dist/constants.js +0 -137
  50. package/dist/constants.js.map +0 -1
  51. package/dist/enumerations/index.d.ts +0 -2
  52. package/dist/enumerations/index.d.ts.map +0 -1
  53. package/dist/enumerations/index.js +0 -18
  54. package/dist/enumerations/index.js.map +0 -1
  55. package/dist/enumerations/pbkdf2-profile.d.ts +0 -9
  56. package/dist/enumerations/pbkdf2-profile.d.ts.map +0 -1
  57. package/dist/enumerations/pbkdf2-profile.js +0 -13
  58. package/dist/enumerations/pbkdf2-profile.js.map +0 -1
  59. package/dist/i18n/ecies-i18n-factory.d.ts +0 -54
  60. package/dist/i18n/ecies-i18n-factory.d.ts.map +0 -1
  61. package/dist/i18n/ecies-i18n-factory.js +0 -333
  62. package/dist/i18n/ecies-i18n-factory.js.map +0 -1
  63. package/dist/i18n/index.d.ts.map +0 -1
  64. package/dist/i18n/index.js +0 -18
  65. package/dist/i18n/index.js.map +0 -1
  66. package/dist/index.d.ts.map +0 -1
  67. package/dist/index.js +0 -24
  68. package/dist/index.js.map +0 -1
  69. package/dist/interfaces/authenticated-cipher.d.ts +0 -10
  70. package/dist/interfaces/authenticated-cipher.d.ts.map +0 -1
  71. package/dist/interfaces/authenticated-cipher.js +0 -3
  72. package/dist/interfaces/authenticated-cipher.js.map +0 -1
  73. package/dist/interfaces/authenticated-decipher.d.ts +0 -9
  74. package/dist/interfaces/authenticated-decipher.d.ts.map +0 -1
  75. package/dist/interfaces/authenticated-decipher.js +0 -3
  76. package/dist/interfaces/authenticated-decipher.js.map +0 -1
  77. package/dist/interfaces/checksum-config.d.ts +0 -5
  78. package/dist/interfaces/checksum-config.d.ts.map +0 -1
  79. package/dist/interfaces/checksum-config.js +0 -3
  80. package/dist/interfaces/checksum-config.js.map +0 -1
  81. package/dist/interfaces/checksum-consts.d.ts +0 -11
  82. package/dist/interfaces/checksum-consts.d.ts.map +0 -1
  83. package/dist/interfaces/checksum-consts.js +0 -3
  84. package/dist/interfaces/checksum-consts.js.map +0 -1
  85. package/dist/interfaces/constants.d.ts +0 -43
  86. package/dist/interfaces/constants.d.ts.map +0 -1
  87. package/dist/interfaces/constants.js +0 -3
  88. package/dist/interfaces/constants.js.map +0 -1
  89. package/dist/interfaces/ecies-consts.d.ts +0 -88
  90. package/dist/interfaces/ecies-consts.d.ts.map +0 -1
  91. package/dist/interfaces/ecies-consts.js +0 -3
  92. package/dist/interfaces/ecies-consts.js.map +0 -1
  93. package/dist/interfaces/encryption-consts.d.ts +0 -11
  94. package/dist/interfaces/encryption-consts.d.ts.map +0 -1
  95. package/dist/interfaces/encryption-consts.js +0 -3
  96. package/dist/interfaces/encryption-consts.js.map +0 -1
  97. package/dist/interfaces/index.d.ts.map +0 -1
  98. package/dist/interfaces/index.js +0 -34
  99. package/dist/interfaces/index.js.map +0 -1
  100. package/dist/interfaces/keypair-buffer-with-un-encrypted-private-key.d.ts +0 -6
  101. package/dist/interfaces/keypair-buffer-with-un-encrypted-private-key.d.ts.map +0 -1
  102. package/dist/interfaces/keypair-buffer-with-un-encrypted-private-key.js +0 -3
  103. package/dist/interfaces/keypair-buffer-with-un-encrypted-private-key.js.map +0 -1
  104. package/dist/interfaces/keyring-consts.d.ts +0 -6
  105. package/dist/interfaces/keyring-consts.d.ts.map +0 -1
  106. package/dist/interfaces/keyring-consts.js +0 -3
  107. package/dist/interfaces/keyring-consts.js.map +0 -1
  108. package/dist/interfaces/member-operational.d.ts +0 -36
  109. package/dist/interfaces/member-operational.d.ts.map +0 -1
  110. package/dist/interfaces/member-operational.js +0 -3
  111. package/dist/interfaces/member-operational.js.map +0 -1
  112. package/dist/interfaces/member-with-mnemonic.d.ts.map +0 -1
  113. package/dist/interfaces/member-with-mnemonic.js +0 -3
  114. package/dist/interfaces/member-with-mnemonic.js.map +0 -1
  115. package/dist/interfaces/multi-encrypted-message.d.ts.map +0 -1
  116. package/dist/interfaces/multi-encrypted-message.js +0 -3
  117. package/dist/interfaces/multi-encrypted-message.js.map +0 -1
  118. package/dist/interfaces/multi-encrypted-parsed-header.d.ts +0 -24
  119. package/dist/interfaces/multi-encrypted-parsed-header.d.ts.map +0 -1
  120. package/dist/interfaces/multi-encrypted-parsed-header.js +0 -3
  121. package/dist/interfaces/multi-encrypted-parsed-header.js.map +0 -1
  122. package/dist/interfaces/pbkdf-profiles.d.ts.map +0 -1
  123. package/dist/interfaces/pbkdf-profiles.js +0 -3
  124. package/dist/interfaces/pbkdf-profiles.js.map +0 -1
  125. package/dist/interfaces/pbkdf2-result.d.ts +0 -6
  126. package/dist/interfaces/pbkdf2-result.d.ts.map +0 -1
  127. package/dist/interfaces/pbkdf2-result.js +0 -3
  128. package/dist/interfaces/pbkdf2-result.js.map +0 -1
  129. package/dist/interfaces/signing-key-private-key-info.d.ts +0 -11
  130. package/dist/interfaces/signing-key-private-key-info.d.ts.map +0 -1
  131. package/dist/interfaces/signing-key-private-key-info.js +0 -3
  132. package/dist/interfaces/signing-key-private-key-info.js.map +0 -1
  133. package/dist/interfaces/simple-keypair-buffer.d.ts.map +0 -1
  134. package/dist/interfaces/simple-keypair-buffer.js +0 -3
  135. package/dist/interfaces/simple-keypair-buffer.js.map +0 -1
  136. package/dist/interfaces/simple-keypair.d.ts.map +0 -1
  137. package/dist/interfaces/simple-keypair.js +0 -3
  138. package/dist/interfaces/simple-keypair.js.map +0 -1
  139. package/dist/interfaces/simple-public-key-only-buffer.d.ts +0 -4
  140. package/dist/interfaces/simple-public-key-only-buffer.d.ts.map +0 -1
  141. package/dist/interfaces/simple-public-key-only-buffer.js +0 -3
  142. package/dist/interfaces/simple-public-key-only-buffer.js.map +0 -1
  143. package/dist/interfaces/simple-public-key-only.d.ts +0 -4
  144. package/dist/interfaces/simple-public-key-only.d.ts.map +0 -1
  145. package/dist/interfaces/simple-public-key-only.js +0 -3
  146. package/dist/interfaces/simple-public-key-only.js.map +0 -1
  147. package/dist/interfaces/single-encrypted-parsed-header.d.ts +0 -35
  148. package/dist/interfaces/single-encrypted-parsed-header.d.ts.map +0 -1
  149. package/dist/interfaces/single-encrypted-parsed-header.js +0 -3
  150. package/dist/interfaces/single-encrypted-parsed-header.js.map +0 -1
  151. package/dist/interfaces/wallet-seed.d.ts.map +0 -1
  152. package/dist/interfaces/wallet-seed.js +0 -3
  153. package/dist/interfaces/wallet-seed.js.map +0 -1
  154. package/dist/interfaces/wrapped-key-consts.d.ts +0 -7
  155. package/dist/interfaces/wrapped-key-consts.d.ts.map +0 -1
  156. package/dist/interfaces/wrapped-key-consts.js +0 -3
  157. package/dist/interfaces/wrapped-key-consts.js.map +0 -1
  158. package/dist/member.d.ts +0 -74
  159. package/dist/member.d.ts.map +0 -1
  160. package/dist/member.js +0 -273
  161. package/dist/member.js.map +0 -1
  162. package/dist/services/aes-gcm.d.ts +0 -66
  163. package/dist/services/aes-gcm.d.ts.map +0 -1
  164. package/dist/services/aes-gcm.js +0 -115
  165. package/dist/services/aes-gcm.js.map +0 -1
  166. package/dist/services/ecies/crypto-core.d.ts +0 -83
  167. package/dist/services/ecies/crypto-core.d.ts.map +0 -1
  168. package/dist/services/ecies/crypto-core.js +0 -166
  169. package/dist/services/ecies/crypto-core.js.map +0 -1
  170. package/dist/services/ecies/file.d.ts +0 -30
  171. package/dist/services/ecies/file.d.ts.map +0 -1
  172. package/dist/services/ecies/file.js +0 -144
  173. package/dist/services/ecies/file.js.map +0 -1
  174. package/dist/services/ecies/index.d.ts.map +0 -1
  175. package/dist/services/ecies/index.js +0 -24
  176. package/dist/services/ecies/index.js.map +0 -1
  177. package/dist/services/ecies/multi-recipient.d.ts +0 -82
  178. package/dist/services/ecies/multi-recipient.d.ts.map +0 -1
  179. package/dist/services/ecies/multi-recipient.js +0 -360
  180. package/dist/services/ecies/multi-recipient.js.map +0 -1
  181. package/dist/services/ecies/service.d.ts +0 -70
  182. package/dist/services/ecies/service.d.ts.map +0 -1
  183. package/dist/services/ecies/service.js +0 -167
  184. package/dist/services/ecies/service.js.map +0 -1
  185. package/dist/services/ecies/signature.d.ts +0 -38
  186. package/dist/services/ecies/signature.d.ts.map +0 -1
  187. package/dist/services/ecies/signature.js +0 -69
  188. package/dist/services/ecies/signature.js.map +0 -1
  189. package/dist/services/ecies/single-recipient.d.ts +0 -85
  190. package/dist/services/ecies/single-recipient.d.ts.map +0 -1
  191. package/dist/services/ecies/single-recipient.js +0 -399
  192. package/dist/services/ecies/single-recipient.js.map +0 -1
  193. package/dist/services/ecies/utilities.d.ts +0 -22
  194. package/dist/services/ecies/utilities.d.ts.map +0 -1
  195. package/dist/services/ecies/utilities.js +0 -75
  196. package/dist/services/ecies/utilities.js.map +0 -1
  197. package/dist/services/index.d.ts +0 -4
  198. package/dist/services/index.d.ts.map +0 -1
  199. package/dist/services/index.js +0 -20
  200. package/dist/services/index.js.map +0 -1
  201. package/dist/services/pbkdf2.d.ts +0 -106
  202. package/dist/services/pbkdf2.d.ts.map +0 -1
  203. package/dist/services/pbkdf2.js +0 -195
  204. package/dist/services/pbkdf2.js.map +0 -1
  205. package/dist/types.d.ts.map +0 -1
  206. package/dist/types.js +0 -3
  207. package/dist/types.js.map +0 -1
  208. package/dist/utils.d.ts +0 -11
  209. package/dist/utils.d.ts.map +0 -1
  210. package/dist/utils.js +0 -82
  211. package/dist/utils.js.map +0 -1
@@ -0,0 +1,5 @@
1
+ export interface IKeyringConsts {
2
+ ALGORITHM: string;
3
+ KEY_BITS: number;
4
+ MODE: string;
5
+ }
@@ -0,0 +1,52 @@
1
+ import {
2
+ EmailString,
3
+ MemberType,
4
+ SecureBuffer,
5
+ SecureString,
6
+ } from '@digitaldefiance/ecies-lib';
7
+ import { Wallet } from '@ethereumjs/wallet';
8
+ import { Types } from 'mongoose';
9
+ import { SignatureBuffer } from '../types';
10
+
11
+ /**
12
+ * Operational interface for member - defines getters and methods
13
+ */
14
+ export interface IMemberOperational<I extends string | Types.ObjectId> {
15
+ // Required getters
16
+ get id(): I;
17
+ get type(): MemberType;
18
+ get name(): string;
19
+ get email(): EmailString;
20
+ get publicKey(): Uint8Array;
21
+ get creatorId(): I;
22
+ get dateCreated(): Date;
23
+ get dateUpdated(): Date;
24
+
25
+ // Optional private data getters
26
+ get privateKey(): SecureBuffer | undefined;
27
+ get wallet(): Wallet | undefined;
28
+
29
+ // State getters
30
+ get hasPrivateKey(): boolean;
31
+
32
+ // Methods
33
+ sign(data: Buffer): SignatureBuffer;
34
+ verify(signature: SignatureBuffer, data: Buffer): boolean;
35
+ encryptData(data: string | Buffer): Uint8Array;
36
+ decryptData(encryptedData: Buffer): Uint8Array;
37
+ toJson(): string;
38
+
39
+ // Private key management
40
+ loadWallet(mnemonic: SecureString): void;
41
+ unloadPrivateKey(): void;
42
+ unloadWallet(): void;
43
+ unloadWalletAndPrivateKey(): void;
44
+ }
45
+
46
+ /**
47
+ * Extended operational interface for test members
48
+ */
49
+ export interface ITestBrightChainMemberOperational
50
+ extends IMemberOperational<Types.ObjectId> {
51
+ get mnemonic(): SecureString | undefined;
52
+ }
@@ -1,7 +1,7 @@
1
1
  import { SecureString } from '@digitaldefiance/ecies-lib';
2
2
  import { Member } from '../member';
3
+
3
4
  export interface IBackendMemberWithMnemonic {
4
- member: Member;
5
- mnemonic: SecureString;
5
+ member: Member;
6
+ mnemonic: SecureString;
6
7
  }
7
- //# sourceMappingURL=member-with-mnemonic.d.ts.map
@@ -1,8 +1,8 @@
1
1
  import { IMultiEncryptedParsedHeader } from './multi-encrypted-parsed-header';
2
+
2
3
  export interface IMultiEncryptedMessage extends IMultiEncryptedParsedHeader {
3
- /**
4
- * The encrypted message.
5
- */
6
- readonly encryptedMessage: Buffer;
4
+ /**
5
+ * The encrypted message.
6
+ */
7
+ readonly encryptedMessage: Buffer;
7
8
  }
8
- //# sourceMappingURL=multi-encrypted-message.d.ts.map
@@ -0,0 +1,24 @@
1
+ import { Types } from 'mongoose';
2
+
3
+ export interface IMultiEncryptedParsedHeader {
4
+ /**
5
+ * The length of the data before encryption
6
+ */
7
+ readonly dataLength: number;
8
+ /**
9
+ * The number of recipients
10
+ */
11
+ readonly recipientCount: number;
12
+ /**
13
+ * The IDs of the recipients
14
+ */
15
+ readonly recipientIds: Types.ObjectId[];
16
+ /**
17
+ * An encrypted version of the symmetric key for each recipient
18
+ */
19
+ readonly recipientKeys: Buffer[];
20
+ /**
21
+ * The size of the header, up to the encrypted message start (excludes encrypted message IV+auth tag)
22
+ */
23
+ readonly headerSize: number;
24
+ }
@@ -1,6 +1,6 @@
1
1
  import { IPbkdf2Config } from '@digitaldefiance/ecies-lib';
2
2
  import { Pbkdf2ProfileEnum } from '../enumerations/pbkdf2-profile';
3
+
3
4
  export type PbkdfProfiles = {
4
- [key in Pbkdf2ProfileEnum]: IPbkdf2Config;
5
+ [key in Pbkdf2ProfileEnum]: IPbkdf2Config;
5
6
  };
6
- //# sourceMappingURL=pbkdf-profiles.d.ts.map
@@ -0,0 +1,5 @@
1
+ export interface IPbkdf2Result {
2
+ salt: Buffer;
3
+ hash: Buffer;
4
+ iterations: number;
5
+ }
@@ -0,0 +1,12 @@
1
+ import { ec } from 'elliptic';
2
+ import { IKeyPairBufferWithUnEncryptedPrivateKey } from './keypair-buffer-with-un-encrypted-private-key';
3
+
4
+ export interface ISigningKeyPrivateKeyInfo
5
+ extends IKeyPairBufferWithUnEncryptedPrivateKey {
6
+ keyPair: ec.KeyPair;
7
+ publicKey: Buffer;
8
+ privateKey: Buffer;
9
+ seedHex: string;
10
+ entropy: string;
11
+ mnemonic: string;
12
+ }
@@ -1,6 +1,6 @@
1
1
  import { ISimplePublicKeyOnlyBuffer } from './simple-public-key-only-buffer';
2
+
2
3
  export interface ISimpleKeyPairBuffer extends ISimplePublicKeyOnlyBuffer {
3
- publicKey: Buffer;
4
- privateKey: Buffer;
4
+ publicKey: Buffer;
5
+ privateKey: Buffer;
5
6
  }
6
- //# sourceMappingURL=simple-keypair-buffer.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { ISimplePublicKeyOnly } from './simple-public-key-only';
2
+
2
3
  export interface ISimpleKeyPair extends ISimplePublicKeyOnly {
3
- publicKey: string;
4
- privateKey: Buffer;
4
+ publicKey: string;
5
+ privateKey: Buffer;
5
6
  }
6
- //# sourceMappingURL=simple-keypair.d.ts.map
@@ -0,0 +1,3 @@
1
+ export interface ISimplePublicKeyOnlyBuffer {
2
+ publicKey: Buffer;
3
+ }
@@ -0,0 +1,3 @@
1
+ export interface ISimplePublicKeyOnly {
2
+ publicKey: string;
3
+ }
@@ -0,0 +1,35 @@
1
+ import { EciesEncryptionTypeEnum } from '@digitaldefiance/ecies-lib';
2
+
3
+ /**
4
+ * Interface for encrypted messages
5
+ */
6
+ export interface ISingleEncryptedParsedHeader {
7
+ /**
8
+ * The optional preamble, if specified/relevant
9
+ */
10
+ readonly preamble?: Buffer;
11
+ /**
12
+ * The encryption type used to encrypt the data
13
+ */
14
+ readonly encryptionType: EciesEncryptionTypeEnum;
15
+ /**
16
+ * The ephemeral public key used to encrypt the data
17
+ */
18
+ readonly ephemeralPublicKey: Buffer;
19
+ /**
20
+ * The initialization vector used to encrypt the data
21
+ */
22
+ readonly iv: Buffer;
23
+ /**
24
+ * The authentication tag used to encrypt the data
25
+ */
26
+ readonly authTag: Buffer;
27
+ /**
28
+ * The length of the encrypted data
29
+ */
30
+ readonly dataLength: number;
31
+ /**
32
+ * The size of the encrypted data header
33
+ */
34
+ readonly headerSize: number;
35
+ }
@@ -1,7 +1,7 @@
1
1
  import { SecureBuffer } from '@digitaldefiance/ecies-lib';
2
2
  import { Wallet } from '@ethereumjs/wallet';
3
+
3
4
  export interface IWalletSeed {
4
- wallet: Wallet;
5
- seed: SecureBuffer;
5
+ wallet: Wallet;
6
+ seed: SecureBuffer;
6
7
  }
7
- //# sourceMappingURL=wallet-seed.d.ts.map
@@ -0,0 +1,6 @@
1
+ export interface IWrappedKeyConsts {
2
+ SALT_SIZE: number;
3
+ IV_SIZE: number;
4
+ MASTER_KEY_SIZE: number;
5
+ MIN_ITERATIONS: number;
6
+ }
package/src/member.ts ADDED
@@ -0,0 +1,463 @@
1
+ import {
2
+ ECIES,
3
+ EmailString,
4
+ IMemberStorageData,
5
+ MemberErrorType,
6
+ MemberType,
7
+ SecureBuffer,
8
+ SecureString,
9
+ } from '@digitaldefiance/ecies-lib';
10
+ import { Wallet } from '@ethereumjs/wallet';
11
+ import {
12
+ getNodeEciesTranslation,
13
+ NodeEciesStringKey,
14
+ } from './i18n/ecies-i18n-factory';
15
+
16
+ /**
17
+ * Custom error classes that work with the plugin i18n system
18
+ */
19
+ export class NodeMemberError extends Error {
20
+ constructor(message: string, public readonly type: MemberErrorType) {
21
+ super(message);
22
+ this.name = 'NodeMemberError';
23
+ }
24
+ }
25
+
26
+ import { ECIESService } from './services/ecies/service';
27
+ // Removed: import { ServiceProvider } from './services/service.provider';
28
+ import { ObjectId } from 'mongodb';
29
+ import { Types } from 'mongoose';
30
+ import { IMemberOperational } from './interfaces/member-operational';
31
+ import { SignatureBuffer } from './types';
32
+
33
+ /**
34
+ * A member of Brightchain.
35
+ * In the Owner Free Filesystem (OFF), members are used to:
36
+ * 1. Sign and verify data
37
+ * 2. Encrypt and decrypt data
38
+ * 3. Participate in voting
39
+ * 4. Establish ownership of data
40
+ */
41
+ export class Member implements IMemberOperational<Types.ObjectId> {
42
+ private readonly _eciesService: ECIESService;
43
+ private readonly _id: Types.ObjectId;
44
+ private readonly _type: MemberType;
45
+ private readonly _name: string;
46
+ private readonly _email: EmailString;
47
+ private readonly _publicKey: Buffer;
48
+ private readonly _creatorId: Types.ObjectId;
49
+ private readonly _dateCreated: Date;
50
+ private readonly _dateUpdated: Date;
51
+ private _privateKey?: SecureBuffer;
52
+ private _wallet?: Wallet;
53
+
54
+ constructor(
55
+ // Add injected services as parameters
56
+ eciesService: ECIESService,
57
+ // Original parameters
58
+ type: MemberType,
59
+ name: string,
60
+ email: EmailString,
61
+ publicKey: Buffer,
62
+ privateKey?: SecureBuffer,
63
+ wallet?: Wallet,
64
+ id?: Types.ObjectId,
65
+ dateCreated?: Date,
66
+ dateUpdated?: Date,
67
+ creatorId?: Types.ObjectId,
68
+ ) {
69
+ // Assign injected services
70
+ this._eciesService = eciesService;
71
+ // Assign original parameters
72
+ this._type = type;
73
+ this._id = id ?? new ObjectId();
74
+ this._name = name;
75
+ if (!this._name || this._name.length == 0) {
76
+ throw new NodeMemberError(
77
+ getNodeEciesTranslation(
78
+ NodeEciesStringKey.Error_Member_MissingMemberName,
79
+ ),
80
+ MemberErrorType.MissingMemberName,
81
+ );
82
+ }
83
+ if (this._name.trim() != this._name) {
84
+ throw new NodeMemberError(
85
+ getNodeEciesTranslation(
86
+ NodeEciesStringKey.Error_Member_InvalidMemberNameWhitespace,
87
+ ),
88
+ MemberErrorType.InvalidMemberNameWhitespace,
89
+ );
90
+ }
91
+ this._email = email;
92
+ this._publicKey = publicKey;
93
+ this._privateKey = privateKey;
94
+ this._wallet = wallet;
95
+
96
+ // don't create a new date object with nearly identical values to the existing one
97
+ let _now: null | Date = null;
98
+ const now = function () {
99
+ if (!_now) {
100
+ _now = new Date();
101
+ }
102
+ return _now;
103
+ };
104
+ this._dateCreated = dateCreated ?? now();
105
+ this._dateUpdated = dateUpdated ?? now();
106
+ this._creatorId = creatorId ?? this._id;
107
+ }
108
+
109
+ // Required getters
110
+ public get id(): Types.ObjectId {
111
+ return this._id;
112
+ }
113
+ public get type(): MemberType {
114
+ return this._type;
115
+ }
116
+ public get name(): string {
117
+ return this._name;
118
+ }
119
+ public get email(): EmailString {
120
+ return this._email;
121
+ }
122
+ public get publicKey(): Buffer {
123
+ return this._publicKey;
124
+ }
125
+ public get creatorId(): Types.ObjectId {
126
+ return this._creatorId;
127
+ }
128
+ public get dateCreated(): Date {
129
+ return this._dateCreated;
130
+ }
131
+ public get dateUpdated(): Date {
132
+ return this._dateUpdated;
133
+ }
134
+
135
+ // Optional private data getters
136
+ public get privateKey(): SecureBuffer | undefined {
137
+ return this._privateKey;
138
+ }
139
+ public get wallet(): Wallet {
140
+ if (!this._wallet) {
141
+ throw new NodeMemberError(
142
+ getNodeEciesTranslation(NodeEciesStringKey.Error_Member_NoWallet),
143
+ MemberErrorType.NoWallet,
144
+ );
145
+ }
146
+ return this._wallet;
147
+ }
148
+
149
+ // State getters
150
+ public get hasPrivateKey(): boolean {
151
+ return this._privateKey !== undefined;
152
+ }
153
+
154
+ public unloadPrivateKey(): void {
155
+ // Do not dispose here; tests expect the same SecureBuffer instance to remain usable
156
+ // when reloaded into another member in the same process.
157
+ this._privateKey = undefined;
158
+ }
159
+
160
+ public unloadWallet(): void {
161
+ this._wallet = undefined;
162
+ }
163
+
164
+ public unloadWalletAndPrivateKey(): void {
165
+ this.unloadWallet();
166
+ this.unloadPrivateKey();
167
+ }
168
+
169
+ public loadWallet(mnemonic: SecureString): void {
170
+ if (this._wallet) {
171
+ throw new NodeMemberError(
172
+ getNodeEciesTranslation(
173
+ NodeEciesStringKey.Error_Member_WalletAlreadyLoaded,
174
+ ),
175
+ MemberErrorType.WalletAlreadyLoaded,
176
+ );
177
+ }
178
+ const { wallet } = this._eciesService.walletAndSeedFromMnemonic(mnemonic);
179
+ const privateKey = wallet.getPrivateKey();
180
+ const publicKey = wallet.getPublicKey();
181
+ const publicKeyWithPrefix = Buffer.concat([
182
+ Buffer.from([ECIES.PUBLIC_KEY_MAGIC]),
183
+ publicKey,
184
+ ]);
185
+
186
+ if (
187
+ publicKeyWithPrefix.toString('hex') !== this._publicKey.toString('hex')
188
+ ) {
189
+ throw new NodeMemberError(
190
+ getNodeEciesTranslation(
191
+ NodeEciesStringKey.Error_Member_InvalidMnemonic,
192
+ ),
193
+ MemberErrorType.InvalidMnemonic,
194
+ );
195
+ }
196
+ this._wallet = wallet;
197
+ this._privateKey = new SecureBuffer(privateKey);
198
+ }
199
+
200
+ /**
201
+ * Loads the private key and optionally the voting private key.
202
+ *
203
+ * @param privateKey The private key to load.
204
+ * @param votingPrivateKey The voting private key to load.
205
+ */
206
+ public loadPrivateKey(privateKey: SecureBuffer): void {
207
+ this._privateKey = privateKey;
208
+ }
209
+
210
+ public sign(data: Buffer): SignatureBuffer {
211
+ if (!this._privateKey) {
212
+ throw new NodeMemberError(
213
+ getNodeEciesTranslation(
214
+ NodeEciesStringKey.Error_Member_MissingPrivateKey,
215
+ ),
216
+ MemberErrorType.MissingPrivateKey,
217
+ );
218
+ }
219
+ return this._eciesService.signMessage(
220
+ Buffer.from(this._privateKey.value),
221
+ data,
222
+ );
223
+ }
224
+
225
+ public signData(data: Buffer): SignatureBuffer {
226
+ if (!this._privateKey) {
227
+ throw new NodeMemberError(
228
+ getNodeEciesTranslation(
229
+ NodeEciesStringKey.Error_Member_MissingPrivateKey,
230
+ ),
231
+ MemberErrorType.MissingPrivateKey,
232
+ );
233
+ }
234
+ return this._eciesService.signMessage(
235
+ Buffer.from(this._privateKey.value),
236
+ data,
237
+ );
238
+ }
239
+
240
+ public verify(signature: SignatureBuffer, data: Buffer): boolean {
241
+ return this._eciesService.verifyMessage(this._publicKey, data, signature);
242
+ }
243
+
244
+ public verifySignature(
245
+ data: Buffer,
246
+ signature: Buffer,
247
+ publicKey: Buffer,
248
+ ): boolean {
249
+ return this._eciesService.verifyMessage(
250
+ publicKey,
251
+ data,
252
+ signature as SignatureBuffer,
253
+ );
254
+ }
255
+
256
+ private static readonly MAX_ENCRYPTION_SIZE = 1024 * 1024 * 10; // 10MB limit
257
+ private static readonly VALID_STRING_REGEX = /^[\x20-\x7E\n\r\t]*$/; // Printable ASCII + common whitespace
258
+
259
+ public encryptData(
260
+ data: string | Buffer,
261
+ recipientPublicKey?: Buffer,
262
+ ): Buffer {
263
+ // Validate input
264
+ if (!data) {
265
+ throw new NodeMemberError(
266
+ getNodeEciesTranslation(
267
+ NodeEciesStringKey.Error_Member_MissingEncryptionData,
268
+ ),
269
+ MemberErrorType.MissingEncryptionData,
270
+ );
271
+ }
272
+
273
+ // Check size limit
274
+ const dataSize = Buffer.isBuffer(data)
275
+ ? data.length
276
+ : Buffer.byteLength(data);
277
+ if (dataSize > Member.MAX_ENCRYPTION_SIZE) {
278
+ throw new NodeMemberError(
279
+ getNodeEciesTranslation(
280
+ NodeEciesStringKey.Error_Member_EncryptionDataTooLarge,
281
+ ),
282
+ MemberErrorType.EncryptionDataTooLarge,
283
+ );
284
+ }
285
+
286
+ // Create buffer from data
287
+ const bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data);
288
+
289
+ // Use recipient public key or self public key
290
+ const targetPublicKey = recipientPublicKey || this._publicKey;
291
+
292
+ return this._eciesService.encryptSimpleOrSingle(
293
+ false,
294
+ targetPublicKey,
295
+ bufferData,
296
+ );
297
+ }
298
+
299
+ public decryptData(encryptedData: Buffer): Buffer {
300
+ if (!this._privateKey) {
301
+ throw new NodeMemberError(
302
+ getNodeEciesTranslation(
303
+ NodeEciesStringKey.Error_Member_MissingPrivateKey,
304
+ ),
305
+ MemberErrorType.MissingPrivateKey,
306
+ );
307
+ }
308
+ // decryptSingleWithHeader now returns the Buffer directly
309
+ return this._eciesService.decryptSimpleOrSingleWithHeader(
310
+ false,
311
+ Buffer.from(this._privateKey.value),
312
+ encryptedData,
313
+ );
314
+ }
315
+
316
+ public toJson(): string {
317
+ const storage: IMemberStorageData = {
318
+ id: this._id.toString(),
319
+ type: this._type,
320
+ name: this._name,
321
+ email: this._email.toString(),
322
+ publicKey: this._publicKey.toString('base64'),
323
+ creatorId: this._creatorId.toString(),
324
+ dateCreated: this._dateCreated.toISOString(),
325
+ dateUpdated: this._dateUpdated.toISOString(),
326
+ };
327
+ return JSON.stringify(storage);
328
+ }
329
+
330
+ public dispose(): void {
331
+ // Ensure secret material is zeroized when disposing
332
+ try {
333
+ this._privateKey?.dispose();
334
+ } finally {
335
+ this.unloadWalletAndPrivateKey();
336
+ }
337
+ }
338
+
339
+ public static fromJson(
340
+ json: string,
341
+ // Add injected services as parameters
342
+ eciesService: ECIESService,
343
+ ): Member {
344
+ const storage: IMemberStorageData = JSON.parse(json);
345
+ const email = new EmailString(storage.email);
346
+
347
+ // Pass injected services to constructor
348
+ const dateCreated = new Date(storage.dateCreated);
349
+ return new Member(
350
+ eciesService,
351
+ storage.type,
352
+ storage.name,
353
+ email,
354
+ Buffer.from(storage.publicKey, 'base64'),
355
+ undefined,
356
+ undefined,
357
+ new ObjectId(storage.id),
358
+ dateCreated,
359
+ new Date(storage.dateUpdated),
360
+ new ObjectId(storage.creatorId),
361
+ );
362
+ }
363
+
364
+ public static fromMnemonic(
365
+ mnemonic: SecureString,
366
+ eciesService: ECIESService,
367
+ memberType = MemberType.User,
368
+ name = 'Test User',
369
+ email = new EmailString('test@example.com'),
370
+ ): Member {
371
+ const { wallet } = eciesService.walletAndSeedFromMnemonic(mnemonic);
372
+ const privateKey = wallet.getPrivateKey();
373
+ const publicKeyWithPrefix = Buffer.concat([
374
+ Buffer.from([ECIES.PUBLIC_KEY_MAGIC]),
375
+ wallet.getPublicKey(),
376
+ ]);
377
+
378
+ return new Member(
379
+ eciesService,
380
+ memberType,
381
+ name,
382
+ email,
383
+ publicKeyWithPrefix,
384
+ new SecureBuffer(privateKey),
385
+ wallet,
386
+ );
387
+ }
388
+
389
+ public static newMember(
390
+ // Add injected services as parameters
391
+ eciesService: ECIESService,
392
+ // Original parameters
393
+ type: MemberType,
394
+ name: string,
395
+ email: EmailString,
396
+ forceMnemonic?: SecureString,
397
+ createdBy?: Types.ObjectId,
398
+ ): { member: Member; mnemonic: SecureString } {
399
+ // Validate inputs first
400
+ if (!name || name.length == 0) {
401
+ throw new NodeMemberError(
402
+ getNodeEciesTranslation(
403
+ NodeEciesStringKey.Error_Member_MissingMemberName,
404
+ ),
405
+ MemberErrorType.MissingMemberName,
406
+ );
407
+ }
408
+ if (name.trim() != name) {
409
+ throw new NodeMemberError(
410
+ getNodeEciesTranslation(
411
+ NodeEciesStringKey.Error_Member_InvalidMemberNameWhitespace,
412
+ ),
413
+ MemberErrorType.InvalidMemberNameWhitespace,
414
+ );
415
+ }
416
+ if (!email || email.toString().length == 0) {
417
+ throw new NodeMemberError(
418
+ getNodeEciesTranslation(NodeEciesStringKey.Error_Member_MissingEmail),
419
+ MemberErrorType.MissingEmail,
420
+ );
421
+ }
422
+ if (email.toString().trim() != email.toString()) {
423
+ throw new NodeMemberError(
424
+ getNodeEciesTranslation(
425
+ NodeEciesStringKey.Error_Member_InvalidEmailWhitespace,
426
+ ),
427
+ MemberErrorType.InvalidEmailWhitespace,
428
+ );
429
+ }
430
+
431
+ // Use injected services
432
+ const mnemonic = forceMnemonic ?? eciesService.generateNewMnemonic();
433
+ const { wallet } = eciesService.walletAndSeedFromMnemonic(mnemonic);
434
+
435
+ // Get private key from wallet
436
+ const privateKey = wallet.getPrivateKey();
437
+ // Get public key with 0x04 prefix
438
+ const publicKeyWithPrefix = Buffer.concat([
439
+ Buffer.from([ECIES.PUBLIC_KEY_MAGIC]),
440
+ wallet.getPublicKey(),
441
+ ]);
442
+
443
+ const newId = new ObjectId();
444
+ const dateCreated = new Date();
445
+ return {
446
+ // Pass injected services to constructor
447
+ member: new Member(
448
+ eciesService,
449
+ type,
450
+ name,
451
+ email,
452
+ publicKeyWithPrefix,
453
+ new SecureBuffer(privateKey),
454
+ wallet,
455
+ newId,
456
+ dateCreated,
457
+ dateCreated,
458
+ createdBy ?? newId,
459
+ ),
460
+ mnemonic,
461
+ };
462
+ }
463
+ }