@binsky/passman-client-ts 0.1.0-7

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 (91) hide show
  1. package/README.md +9 -0
  2. package/lib/BrowserStorage.d.ts +39 -0
  3. package/lib/BrowserStorage.js +137 -0
  4. package/lib/Exception/ConfigurationError.d.ts +6 -0
  5. package/lib/Exception/ConfigurationError.js +11 -0
  6. package/lib/Exception/FormFieldError.d.ts +4 -0
  7. package/lib/Exception/FormFieldError.js +2 -0
  8. package/lib/Interfaces/Credential/CredentialInterface.d.ts +33 -0
  9. package/lib/Interfaces/Credential/CredentialInterface.js +2 -0
  10. package/lib/Interfaces/Credential/CustomFieldInterface.d.ts +6 -0
  11. package/lib/Interfaces/Credential/CustomFieldInterface.js +2 -0
  12. package/lib/Interfaces/Credential/EncryptedCredentialInterface.d.ts +31 -0
  13. package/lib/Interfaces/Credential/EncryptedCredentialInterface.js +2 -0
  14. package/lib/Interfaces/Credential/IconInterface.d.ts +4 -0
  15. package/lib/Interfaces/Credential/IconInterface.js +2 -0
  16. package/lib/Interfaces/Credential/OTPConfigInterface.d.ts +14 -0
  17. package/lib/Interfaces/Credential/OTPConfigInterface.js +2 -0
  18. package/lib/Interfaces/Credential/TagInterface.d.ts +3 -0
  19. package/lib/Interfaces/Credential/TagInterface.js +2 -0
  20. package/lib/Interfaces/CredentialFilterService/FilterStatsInterface.d.ts +10 -0
  21. package/lib/Interfaces/CredentialFilterService/FilterStatsInterface.js +2 -0
  22. package/lib/Interfaces/File/DeleteFilesRequestBodyInterface.d.ts +3 -0
  23. package/lib/Interfaces/File/DeleteFilesRequestBodyInterface.js +2 -0
  24. package/lib/Interfaces/File/DeleteFilesResponseInterface.d.ts +4 -0
  25. package/lib/Interfaces/File/DeleteFilesResponseInterface.js +2 -0
  26. package/lib/Interfaces/File/FileInterface.d.ts +9 -0
  27. package/lib/Interfaces/File/FileInterface.js +2 -0
  28. package/lib/Interfaces/File/FileUploadResponseInterface.d.ts +9 -0
  29. package/lib/Interfaces/File/FileUploadResponseInterface.js +2 -0
  30. package/lib/Interfaces/LoggingHandlerInterface.d.ts +9 -0
  31. package/lib/Interfaces/LoggingHandlerInterface.js +2 -0
  32. package/lib/Interfaces/NextcloudServer/NextcloudServerInterface.d.ts +6 -0
  33. package/lib/Interfaces/NextcloudServer/NextcloudServerInterface.js +2 -0
  34. package/lib/Interfaces/PassmanCrypto/GenerateKeypairResponseInterface.d.ts +5 -0
  35. package/lib/Interfaces/PassmanCrypto/GenerateKeypairResponseInterface.js +2 -0
  36. package/lib/Interfaces/PassmanCrypto/PEMRSAKeypairInterface.d.ts +4 -0
  37. package/lib/Interfaces/PassmanCrypto/PEMRSAKeypairInterface.js +2 -0
  38. package/lib/Interfaces/PassmanCrypto/RSAKeypairInterface.d.ts +5 -0
  39. package/lib/Interfaces/PassmanCrypto/RSAKeypairInterface.js +2 -0
  40. package/lib/Interfaces/PasswordGeneratorService/PasswordGeneratorConfigurationInterface.d.ts +9 -0
  41. package/lib/Interfaces/PasswordGeneratorService/PasswordGeneratorConfigurationInterface.js +2 -0
  42. package/lib/Interfaces/ReEncryptionService/ReEncryptionProgressInterface.d.ts +7 -0
  43. package/lib/Interfaces/ReEncryptionService/ReEncryptionProgressInterface.js +2 -0
  44. package/lib/Interfaces/ReEncryptionService/ReEncryptionStageProgressInterface.d.ts +5 -0
  45. package/lib/Interfaces/ReEncryptionService/ReEncryptionStageProgressInterface.js +2 -0
  46. package/lib/Interfaces/Revision/RevisionInterface.d.ts +8 -0
  47. package/lib/Interfaces/Revision/RevisionInterface.js +2 -0
  48. package/lib/Interfaces/ShareService/ACLInterface.d.ts +15 -0
  49. package/lib/Interfaces/ShareService/ACLInterface.js +2 -0
  50. package/lib/Interfaces/ShareService/CredentialShareRequestInterface.d.ts +16 -0
  51. package/lib/Interfaces/ShareService/CredentialShareRequestInterface.js +2 -0
  52. package/lib/Interfaces/Vault/VaultInterface.d.ts +15 -0
  53. package/lib/Interfaces/Vault/VaultInterface.js +2 -0
  54. package/lib/Interfaces/Vault/VaultResponseInterface.d.ts +15 -0
  55. package/lib/Interfaces/Vault/VaultResponseInterface.js +2 -0
  56. package/lib/LocalPassmanStore.d.ts +4 -0
  57. package/lib/LocalPassmanStore.js +14 -0
  58. package/lib/Model/Credential.d.ts +173 -0
  59. package/lib/Model/Credential.js +594 -0
  60. package/lib/Model/File.d.ts +15 -0
  61. package/lib/Model/File.js +55 -0
  62. package/lib/Model/NextcloudServer.d.ts +27 -0
  63. package/lib/Model/NextcloudServer.js +108 -0
  64. package/lib/Model/Revision.d.ts +21 -0
  65. package/lib/Model/Revision.js +33 -0
  66. package/lib/Model/SharingACL.d.ts +28 -0
  67. package/lib/Model/SharingACL.js +48 -0
  68. package/lib/Model/Vault.d.ts +38 -0
  69. package/lib/Model/Vault.js +265 -0
  70. package/lib/PassmanClient.d.ts +20 -0
  71. package/lib/PassmanClient.js +80 -0
  72. package/lib/Service/CredentialFilterService.d.ts +24 -0
  73. package/lib/Service/CredentialFilterService.js +209 -0
  74. package/lib/Service/CustomMathsService.d.ts +7 -0
  75. package/lib/Service/CustomMathsService.js +52 -0
  76. package/lib/Service/DefaultLoggingService.d.ts +10 -0
  77. package/lib/Service/DefaultLoggingService.js +27 -0
  78. package/lib/Service/DownloadService.d.ts +12 -0
  79. package/lib/Service/DownloadService.js +121 -0
  80. package/lib/Service/OTPService.d.ts +22 -0
  81. package/lib/Service/OTPService.js +134 -0
  82. package/lib/Service/PassmanCrypto.d.ts +10 -0
  83. package/lib/Service/PassmanCrypto.js +57 -0
  84. package/lib/Service/PasswordGeneratorService.d.ts +6 -0
  85. package/lib/Service/PasswordGeneratorService.js +73 -0
  86. package/lib/Service/ReEncryptionService.d.ts +23 -0
  87. package/lib/Service/ReEncryptionService.js +318 -0
  88. package/lib/Service/ShareService.d.ts +15 -0
  89. package/lib/Service/ShareService.js +56 -0
  90. package/lib/tsconfig.tsbuildinfo +1 -0
  91. package/package.json +36 -0
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.CredentialFilterService = exports.FILTERS = void 0;
27
+ const core_1 = require("@zxcvbn-ts/core");
28
+ const zxcvbnEnPackage = __importStar(require("@zxcvbn-ts/language-en"));
29
+ const zxcvbnCommonPackage = __importStar(require("@zxcvbn-ts/language-common"));
30
+ var FILTERS;
31
+ (function (FILTERS) {
32
+ FILTERS[FILTERS["SHOW_ALL"] = 0] = "SHOW_ALL";
33
+ FILTERS[FILTERS["COMPROMISED"] = 1] = "COMPROMISED";
34
+ FILTERS[FILTERS["STRENGTH_LOW"] = 2] = "STRENGTH_LOW";
35
+ FILTERS[FILTERS["STRENGTH_MEDIUM"] = 3] = "STRENGTH_MEDIUM";
36
+ FILTERS[FILTERS["STRENGTH_GOOD"] = 4] = "STRENGTH_GOOD";
37
+ FILTERS[FILTERS["EXPIRED"] = 5] = "EXPIRED";
38
+ FILTERS[FILTERS["DELETED"] = 6] = "DELETED";
39
+ FILTERS[FILTERS["ENCRYPTION_BROKEN"] = 7] = "ENCRYPTION_BROKEN"; // use FILTERS.ENCRYPTION_BROKEN only when you really know what you are doing
40
+ })(FILTERS || (exports.FILTERS = FILTERS = {}));
41
+ class CredentialFilterService {
42
+ static getFilteredCredentials = (allCredentials, filter, additionalFilterText = undefined) => {
43
+ let filtered = [];
44
+ for (const credential of allCredentials) {
45
+ if (filter === FILTERS.ENCRYPTION_BROKEN) {
46
+ // do not care about other major categories (like hidden / deleted / text) for this filter option
47
+ if (credential.hasUnspecifiedEncryptionError()) {
48
+ filtered.push(credential);
49
+ }
50
+ continue;
51
+ }
52
+ if (CredentialFilterService.isHidden(credential)) {
53
+ // hidden credentials are never shown in the list
54
+ // matches usually only the (required) first test credential
55
+ continue;
56
+ }
57
+ const additionalTextFilterEnabled = additionalFilterText !== undefined && additionalFilterText !== '';
58
+ // filter text if possible, otherwise ignore filter and proceed
59
+ if (!additionalTextFilterEnabled || (additionalTextFilterEnabled && CredentialFilterService.matchesFilterText(credential, additionalFilterText))) {
60
+ if (filter === FILTERS.DELETED) {
61
+ // deleted credentials will not match any other category
62
+ if (CredentialFilterService.isDeleted(credential)) {
63
+ filtered.push(credential);
64
+ }
65
+ }
66
+ else {
67
+ if (CredentialFilterService.isDeleted(credential)) {
68
+ // deleted credentials will not match any other category
69
+ continue;
70
+ }
71
+ if (filter === FILTERS.SHOW_ALL) {
72
+ filtered.push(credential);
73
+ }
74
+ else if (filter === FILTERS.COMPROMISED) {
75
+ if (CredentialFilterService.isCompromised(credential)) {
76
+ filtered.push(credential);
77
+ }
78
+ }
79
+ else if (filter === FILTERS.STRENGTH_LOW) {
80
+ if (CredentialFilterService.hasLowStrength(credential)) {
81
+ filtered.push(credential);
82
+ }
83
+ }
84
+ else if (filter === FILTERS.STRENGTH_MEDIUM) {
85
+ if (CredentialFilterService.hasMediumStrength(credential)) {
86
+ filtered.push(credential);
87
+ }
88
+ }
89
+ else if (filter === FILTERS.STRENGTH_GOOD) {
90
+ if (CredentialFilterService.hasGoodStrength(credential)) {
91
+ filtered.push(credential);
92
+ }
93
+ }
94
+ else if (filter === FILTERS.EXPIRED) {
95
+ if (CredentialFilterService.isExpired(credential)) {
96
+ filtered.push(credential);
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+ return filtered;
103
+ };
104
+ static getFilterStats = (allCredentials) => {
105
+ const stats = {
106
+ allVisible: 0,
107
+ compromised: 0,
108
+ strengthLow: 0,
109
+ strengthMedium: 0,
110
+ strengthGood: 0,
111
+ expired: 0,
112
+ deleted: 0,
113
+ encryptionBroken: 0
114
+ };
115
+ const options = {
116
+ translations: zxcvbnEnPackage.translations,
117
+ graphs: zxcvbnCommonPackage.adjacencyGraphs,
118
+ dictionary: {}, // do not use dictionaries for a faster evaluation
119
+ };
120
+ core_1.zxcvbnOptions.setOptions(options);
121
+ const now = Date.now();
122
+ for (const credential of allCredentials) {
123
+ if (!CredentialFilterService.isHidden(credential)) {
124
+ if (CredentialFilterService.isDeleted(credential)) {
125
+ stats.deleted++;
126
+ }
127
+ else {
128
+ stats.allVisible++;
129
+ if (CredentialFilterService.isCompromised(credential)) {
130
+ stats.compromised++;
131
+ }
132
+ if (CredentialFilterService.isExpired(credential, now)) {
133
+ stats.expired++;
134
+ }
135
+ if (credential.password != null) {
136
+ // do not categorize credential by strength if it has no primary password set
137
+ // zxcvbn will fail for credential.password = null
138
+ const zxcvbnResult = (0, core_1.zxcvbn)(credential.password);
139
+ if (zxcvbnResult.score >= 3) {
140
+ stats.strengthGood++;
141
+ }
142
+ else if (zxcvbnResult.score == 2) {
143
+ stats.strengthMedium++;
144
+ }
145
+ else {
146
+ // use strength low also as fallback, if zxcvbnResult is < 0
147
+ stats.strengthLow++;
148
+ }
149
+ }
150
+ }
151
+ }
152
+ // count all types of credentials (also hidden), if its encryption is broken
153
+ if (credential.hasUnspecifiedEncryptionError()) {
154
+ stats.encryptionBroken++;
155
+ }
156
+ }
157
+ return stats;
158
+ };
159
+ static isHidden(credential) {
160
+ return credential.hidden;
161
+ }
162
+ static isDeleted(credential) {
163
+ return credential.delete_time !== null && credential.delete_time > 0;
164
+ }
165
+ static isCompromised(credential) {
166
+ return credential.compromised !== null && credential.compromised != false;
167
+ }
168
+ static isExpired(credential, now = undefined) {
169
+ if (now === undefined) {
170
+ now = Date.now();
171
+ }
172
+ return credential.expire_time !== 0 && credential.expire_time * 1000 <= now;
173
+ }
174
+ static hasLowStrength(credential) {
175
+ if (credential.password == null) {
176
+ // do not categorize credential by strength if it has no primary password set
177
+ return false;
178
+ }
179
+ const zxcvbnResult = (0, core_1.zxcvbn)(credential.password);
180
+ return zxcvbnResult.score <= 1;
181
+ }
182
+ static hasMediumStrength(credential) {
183
+ if (credential.password == null) {
184
+ // do not categorize credential by strength if it has no primary password set
185
+ return false;
186
+ }
187
+ const zxcvbnResult = (0, core_1.zxcvbn)(credential.password);
188
+ return zxcvbnResult.score == 2;
189
+ }
190
+ static hasGoodStrength(credential) {
191
+ if (credential.password == null) {
192
+ // do not categorize credential by strength if it has no primary password set
193
+ return false;
194
+ }
195
+ const zxcvbnResult = (0, core_1.zxcvbn)(credential.password);
196
+ return zxcvbnResult.score >= 3;
197
+ }
198
+ static matchesFilterText(credential, filterText) {
199
+ filterText = filterText.toLowerCase();
200
+ if (credential.label != null && credential.label.toLowerCase().indexOf(filterText) > -1) {
201
+ return true;
202
+ }
203
+ else if (credential.description != null && credential.description.toLowerCase().indexOf(filterText) > -1) {
204
+ return true;
205
+ }
206
+ return false;
207
+ }
208
+ }
209
+ exports.CredentialFilterService = CredentialFilterService;
@@ -0,0 +1,7 @@
1
+ export declare class CustomMathsService {
2
+ static round: (num: any, digits: number) => string;
3
+ static calculateFromByte: (byte: any, roundDigits?: number) => string;
4
+ static byteToGb: (byte: any, roundDigits?: number) => string;
5
+ static byteToMb: (byte: any, roundDigits?: number) => string;
6
+ static getSecureRandomInt(min: any, max: any): any;
7
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CustomMathsService = void 0;
4
+ class CustomMathsService {
5
+ static round = (num, digits) => {
6
+ return parseFloat(num).toFixed(digits);
7
+ };
8
+ static calculateFromByte = (byte, roundDigits = 2) => {
9
+ byte = parseFloat(byte);
10
+ let result = '';
11
+ if (byte < 1024) {
12
+ result = this.round(byte, roundDigits) + ' Byte';
13
+ }
14
+ else if (byte >= 1024 && byte < Math.pow(1024, 2)) {
15
+ result = this.round(byte / 1024, roundDigits) + ' KB';
16
+ }
17
+ else if (byte >= Math.pow(1024, 2) && byte < Math.pow(1024, 3)) {
18
+ result = this.round(byte / Math.pow(1024, 2), roundDigits) + ' MB';
19
+ }
20
+ else if (byte >= Math.pow(1024, 3) && byte < Math.pow(1024, 4)) {
21
+ result = this.round(byte / Math.pow(1024, 3), roundDigits) + ' GB';
22
+ }
23
+ else if (byte >= Math.pow(1024, 4) && byte < Math.pow(1024, 5)) {
24
+ result = this.round(byte / Math.pow(1024, 4), roundDigits) + ' TB';
25
+ }
26
+ else if (byte >= Math.pow(1024, 5) && byte < Math.pow(1024, 6)) {
27
+ result = this.round(byte / Math.pow(1024, 5), roundDigits) + ' PB';
28
+ }
29
+ else if (byte >= Math.pow(1024, 6) && byte < Math.pow(1024, 7)) {
30
+ result = this.round(byte / Math.pow(1024, 6), roundDigits) + ' EB';
31
+ }
32
+ return result;
33
+ };
34
+ static byteToGb = (byte, roundDigits = 2) => {
35
+ return this.round(byte / Math.pow(1024, 3), roundDigits);
36
+ };
37
+ static byteToMb = (byte, roundDigits = 2) => {
38
+ return this.round(byte / Math.pow(1024, 2), roundDigits);
39
+ };
40
+ static getSecureRandomInt(min, max) {
41
+ // Create byte array and fill with 1 random number
42
+ let byteArray = new Uint8Array(1);
43
+ window.crypto.getRandomValues(byteArray);
44
+ const range = max - min + 1;
45
+ const max_range = 256;
46
+ if (byteArray[0] >= Math.floor(max_range / range) * range) {
47
+ return this.getSecureRandomInt(min, max);
48
+ }
49
+ return min + (byteArray[0] % range);
50
+ }
51
+ }
52
+ exports.CustomMathsService = CustomMathsService;
@@ -0,0 +1,10 @@
1
+ import type { LoggingHandlerInterface } from "../Interfaces/LoggingHandlerInterface";
2
+ export declare class DefaultLoggingService implements LoggingHandlerInterface {
3
+ onDebug(message: string): void;
4
+ onInfo(message: string): void;
5
+ onSuccess(message: string): void;
6
+ onWarning(message: string): void;
7
+ onError(message: string): void;
8
+ anyError(error: any): void;
9
+ onThrow(error: Error): void;
10
+ }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultLoggingService = void 0;
4
+ class DefaultLoggingService {
5
+ onDebug(message) {
6
+ console.debug(message);
7
+ }
8
+ onInfo(message) {
9
+ console.info(message);
10
+ }
11
+ onSuccess(message) {
12
+ console.log(message);
13
+ }
14
+ onWarning(message) {
15
+ console.warn(message);
16
+ }
17
+ onError(message) {
18
+ console.error(message);
19
+ }
20
+ anyError(error) {
21
+ console.error(error);
22
+ }
23
+ onThrow(error) {
24
+ throw error;
25
+ }
26
+ }
27
+ exports.DefaultLoggingService = DefaultLoggingService;
@@ -0,0 +1,12 @@
1
+ export declare class DownloadService {
2
+ private static defaultMime;
3
+ /**
4
+ * This download script will only work for web browsers
5
+ * @param data
6
+ * @param strFileName
7
+ * @param strMimeType
8
+ */
9
+ static download(data: any, strFileName: any, strMimeType: any): boolean | XMLHttpRequest;
10
+ private static dataUrlToBlob;
11
+ private static saver;
12
+ }
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ /*
3
+ Based on download.js v4.2, by dandavis; 2008-2016. [CCBY2] https://github.com/rndme/download
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DownloadService = void 0;
7
+ class DownloadService {
8
+ static defaultMime = "application/octet-stream";
9
+ /**
10
+ * This download script will only work for web browsers
11
+ * @param data
12
+ * @param strFileName
13
+ * @param strMimeType
14
+ */
15
+ static download(data, strFileName, strMimeType) {
16
+ let mimeType = strMimeType || DownloadService.defaultMime;
17
+ let payload = data;
18
+ let url = !strFileName && !strMimeType && payload;
19
+ let anchor = document.createElement("a");
20
+ let fileName = strFileName || "download";
21
+ let blob;
22
+ let reader;
23
+ if (String(this) === "true") { //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
24
+ payload = [payload, mimeType];
25
+ mimeType = payload[0];
26
+ payload = payload[1];
27
+ }
28
+ if (url && url.length < 2048) { // if no filename and no mime, assume a url was passed as the only argument
29
+ fileName = url.split("/").pop().split("?")[0];
30
+ anchor.href = url; // assign href prop to temp anchor
31
+ if (anchor.href.indexOf(url) !== -1) { // if the browser determines that it's a potentially valid url path:
32
+ var ajax = new XMLHttpRequest();
33
+ ajax.open("GET", url, true);
34
+ ajax.responseType = 'blob';
35
+ ajax.onload = function (e) {
36
+ DownloadService.download(e.target.response, fileName, DownloadService.defaultMime);
37
+ };
38
+ setTimeout(function () {
39
+ ajax.send();
40
+ }, 0); // allows setting custom ajax headers using the return:
41
+ return ajax;
42
+ } // end if valid url?
43
+ } // end if url?
44
+ //go ahead and download dataURLs right away
45
+ if (/^data:([\w+-]+\/[\w+.-]+)?[,;]/.test(payload)) {
46
+ if (payload.length > (1024 * 1024 * 1.999)) {
47
+ payload = DownloadService.dataUrlToBlob(payload);
48
+ mimeType = payload.type || DownloadService.defaultMime;
49
+ }
50
+ else {
51
+ return DownloadService.saver(payload, fileName, anchor);
52
+ }
53
+ }
54
+ blob = new Blob([payload], { type: mimeType });
55
+ if (self.URL) { // simple fast and modern way using Blob and URL:
56
+ DownloadService.saver(self.URL.createObjectURL(blob), fileName, anchor, true);
57
+ }
58
+ else {
59
+ // handle non-Blob()+non-URL browsers:
60
+ /*if (typeof blob === "string" || blob.constructor === toString) {
61
+ try {
62
+ return DownloadService.saver("data:" + mimeType + ";base64," + self.btoa(blob), fileName, anchor);
63
+ } catch (y) {
64
+ return DownloadService.saver("data:" + mimeType + "," + encodeURIComponent(blob), fileName, anchor);
65
+ }
66
+ }*/
67
+ // Blob but not URL support:
68
+ reader = new FileReader();
69
+ reader.onload = function (e) {
70
+ DownloadService.saver(this.result, fileName, anchor);
71
+ };
72
+ reader.readAsDataURL(blob);
73
+ }
74
+ return true;
75
+ }
76
+ ;
77
+ static dataUrlToBlob(strUrl) {
78
+ var parts = strUrl.split(/[:;,]/), type = parts[1], decoder = parts[2] == "base64" ? atob : decodeURIComponent, binData = decoder(parts.pop()), mx = binData.length, i = 0, uiArr = new Uint8Array(mx);
79
+ for (i; i < mx; ++i)
80
+ uiArr[i] = binData.charCodeAt(i);
81
+ return new Blob([uiArr], { type: type });
82
+ }
83
+ static saver(url, fileName, anchor, winMode = false) {
84
+ if ('download' in anchor) { //html5 A[download]
85
+ var element = document.createElement('a');
86
+ element.setAttribute('href', url);
87
+ element.setAttribute('download', fileName);
88
+ element.style.display = 'none';
89
+ document.body.appendChild(element);
90
+ element.click();
91
+ document.body.removeChild(element);
92
+ if (winMode === true) {
93
+ setTimeout(function () {
94
+ self.URL.revokeObjectURL(element.href);
95
+ }, 250);
96
+ }
97
+ return true;
98
+ }
99
+ // handle non-a[download] safari as best we can:
100
+ if (/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(navigator.userAgent)) {
101
+ url = url.replace(/^data:([\w\/\-\+\.]+)/, DownloadService.defaultMime);
102
+ if (!window.open(url)) { // popup blocked, offer direct download:
103
+ if (confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")) {
104
+ location.href = url;
105
+ }
106
+ }
107
+ return true;
108
+ }
109
+ //do iframe dataURL download (old ch+FF):
110
+ var f = document.createElement("iframe");
111
+ document.body.appendChild(f);
112
+ if (!winMode) { // force a mime that will download:
113
+ url = "data:" + url.replace(/^data:([\w\/\-\+\.]+)/, DownloadService.defaultMime);
114
+ }
115
+ f.src = url;
116
+ setTimeout(function () {
117
+ document.body.removeChild(f);
118
+ }, 333);
119
+ }
120
+ }
121
+ exports.DownloadService = DownloadService;
@@ -0,0 +1,22 @@
1
+ import { Secret } from "otpauth";
2
+ import { OTPConfigInterface } from "../Interfaces/Credential/OTPConfigInterface";
3
+ export declare class OTPService {
4
+ static mergeDefaultOTPConfig: (otp: OTPConfigInterface) => void;
5
+ static getSecretString: (secret: undefined | string | Secret) => string | undefined;
6
+ static getDataUrlFromCurrentOTPValues: (otp: OTPConfigInterface) => string;
7
+ /**
8
+ * Updates otp.qr_uri with a new QR code and data url based on the raw otp values.
9
+ * @param otp
10
+ */
11
+ static updateQRFromCurrentOTPValues: (otp: OTPConfigInterface) => void;
12
+ /**
13
+ * Returns the current token of the given OTP configuration.
14
+ * @param otp
15
+ */
16
+ static updateOTP: (otp: OTPConfigInterface) => string;
17
+ /**
18
+ * Parse input file asynchronous as QR code, extract the TOTP values and return the IOTPConfig, that's built from it.
19
+ * @param input
20
+ */
21
+ static parseOTPQrCodeFromInputFileData: (input: string | File | any) => Promise<OTPConfigInterface>;
22
+ }
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.OTPService = void 0;
30
+ const OTPAuth = __importStar(require("otpauth"));
31
+ const qrcode_generator_1 = __importDefault(require("qrcode-generator"));
32
+ const qrcode_parser_1 = __importDefault(require("qrcode-parser"));
33
+ class OTPService {
34
+ static mergeDefaultOTPConfig = (otp) => {
35
+ const defaults = {
36
+ algorithm: "SHA1",
37
+ period: 30,
38
+ digits: 6,
39
+ };
40
+ for (const key in defaults) {
41
+ if (otp[key] === undefined || otp[key] == null) {
42
+ otp[key] = defaults[key];
43
+ }
44
+ }
45
+ };
46
+ static getSecretString = (secret) => {
47
+ if (typeof secret == "object") {
48
+ return secret.utf8;
49
+ }
50
+ return secret;
51
+ };
52
+ static getDataUrlFromCurrentOTPValues = (otp) => {
53
+ const totp = new OTPAuth.TOTP({
54
+ issuer: otp.issuer,
55
+ label: otp.label,
56
+ algorithm: otp.algorithm,
57
+ digits: otp.digits,
58
+ period: otp.period,
59
+ secret: otp.secret
60
+ });
61
+ return decodeURIComponent(totp.toString());
62
+ };
63
+ /**
64
+ * Updates otp.qr_uri with a new QR code and data url based on the raw otp values.
65
+ * @param otp
66
+ */
67
+ static updateQRFromCurrentOTPValues = (otp) => {
68
+ if (otp.qr_uri === undefined) {
69
+ otp.qr_uri = {};
70
+ }
71
+ const typeNumberAutoDetect = 0;
72
+ const errorCorrectionLevel = 'L'; // L = 7%
73
+ const qr = (0, qrcode_generator_1.default)(typeNumberAutoDetect, errorCorrectionLevel);
74
+ otp.qr_uri.qrData = OTPService.getDataUrlFromCurrentOTPValues(otp);
75
+ qr.addData(otp.qr_uri.qrData);
76
+ qr.make();
77
+ const cellSize = 4;
78
+ const padding = 0;
79
+ const canvas = document.createElement("canvas");
80
+ canvas.width = canvas.height = qr.getModuleCount() * cellSize + padding * 2;
81
+ const context = canvas.getContext("2d");
82
+ qr.renderTo2dContext(context, cellSize);
83
+ otp.qr_uri.image = canvas.toDataURL("image/png");
84
+ canvas.remove();
85
+ };
86
+ /**
87
+ * Returns the current token of the given OTP configuration.
88
+ * @param otp
89
+ */
90
+ static updateOTP = (otp) => {
91
+ if (!otp || !otp.secret || otp.secret === "") {
92
+ return;
93
+ }
94
+ if (typeof otp.secret == "string" && otp.secret.includes(' ')) {
95
+ otp.secret = otp.secret.replaceAll(' ', '');
96
+ }
97
+ OTPService.mergeDefaultOTPConfig(otp);
98
+ const totp = new OTPAuth.TOTP({
99
+ issuer: otp.issuer,
100
+ label: otp.label,
101
+ algorithm: otp.algorithm,
102
+ digits: otp.digits,
103
+ period: otp.period,
104
+ secret: otp.secret
105
+ });
106
+ return totp.generate();
107
+ };
108
+ /**
109
+ * Parse input file asynchronous as QR code, extract the TOTP values and return the IOTPConfig, that's built from it.
110
+ * @param input
111
+ */
112
+ static parseOTPQrCodeFromInputFileData = async (input) => {
113
+ return await (0, qrcode_parser_1.default)(input).then((otpUrl) => {
114
+ const uri = new URL(otpUrl);
115
+ const type = (uri.href.indexOf('totp/') !== -1) ? 'totp' : 'hotp';
116
+ const label = uri.pathname.replace('//' + type + '/', '');
117
+ const otp = {
118
+ type: type,
119
+ label: decodeURIComponent(label),
120
+ qr_uri: {
121
+ qrData: decodeURIComponent(otpUrl),
122
+ image: input
123
+ },
124
+ issuer: uri.searchParams.get('issuer'),
125
+ secret: uri.searchParams.get('secret'),
126
+ algorithm: uri.searchParams.get('algorithm') ? uri.searchParams.get('algorithm') : "SHA1",
127
+ period: uri.searchParams.get('period') ? parseInt(uri.searchParams.get('period')) : 30,
128
+ digits: uri.searchParams.get('digits') ? parseInt(uri.searchParams.get('digits')) : 6,
129
+ };
130
+ return otp;
131
+ });
132
+ };
133
+ }
134
+ exports.OTPService = OTPService;
@@ -0,0 +1,10 @@
1
+ import { GenerateKeypairResponseInterface } from "../Interfaces/PassmanCrypto/GenerateKeypairResponseInterface";
2
+ import { RSAKeypairInterface } from "../Interfaces/PassmanCrypto/RSAKeypairInterface";
3
+ import { PEMRSAKeypairInterface } from "../Interfaces/PassmanCrypto/PEMRSAKeypairInterface";
4
+ export declare class PassmanCrypto {
5
+ static generateRSAKeypair: (keyLength?: number) => Promise<GenerateKeypairResponseInterface>;
6
+ static rsaKeyPairToPEM: (keypair: RSAKeypairInterface) => PEMRSAKeypairInterface;
7
+ private static readonly sjcl_encryption_config;
8
+ static encryptString: (plainText: string, key: string) => string;
9
+ static decryptString: (b64EncCiphertext: string, key: string) => string;
10
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PassmanCrypto = void 0;
7
+ const node_forge_1 = __importDefault(require("node-forge"));
8
+ const sjcl_1 = __importDefault(require("sjcl"));
9
+ class PassmanCrypto {
10
+ static generateRSAKeypair = (keyLength = 2048) => {
11
+ return new Promise(function (resolve, reject) {
12
+ // generate an RSA key pair asynchronously (uses web workers if available)
13
+ // use workers: -1 to run a fast core estimator to optimize # of workers
14
+ node_forge_1.default.pki.rsa.generateKeyPair({
15
+ bits: keyLength,
16
+ workers: 2
17
+ }, (error, keypair) => {
18
+ resolve({ error, keypair });
19
+ });
20
+ });
21
+ };
22
+ static rsaKeyPairToPEM = (keypair) => {
23
+ return {
24
+ privateKey: node_forge_1.default.pki.privateKeyToPem(keypair.privateKey),
25
+ publicKey: node_forge_1.default.pki.publicKeyToPem(keypair.publicKey)
26
+ };
27
+ };
28
+ static sjcl_encryption_config = {
29
+ adata: "",
30
+ iter: 1000,
31
+ ks: 256,
32
+ mode: 'ccm',
33
+ ts: 64,
34
+ //salt: [],
35
+ //iv: []
36
+ };
37
+ static encryptString = (plainText, key) => {
38
+ // todo: think about replacing aes-ccm from sjcl with the more modern and faster aes-gcm from forge
39
+ // see https://crypto.stackexchange.com/questions/6842/how-to-choose-between-aes-ccm-and-aes-gcm-for-storage-volume-encryption
40
+ // see https://github.com/digitalbazaar/forge#cipher
41
+ // todo: try to use aes-ccm from jscrypto instead of the very outdated sjcl
42
+ // see https://github.com/Hinaser/jscrypto/blob/master/API.md#aes
43
+ let rp = {};
44
+ const ct = sjcl_1.default.encrypt(key, plainText, PassmanCrypto.sjcl_encryption_config, rp);
45
+ return window.btoa(ct);
46
+ };
47
+ static decryptString = (b64EncCiphertext, key) => {
48
+ const ciphertext = window.atob(b64EncCiphertext);
49
+ try {
50
+ return sjcl_1.default.decrypt(key, ciphertext);
51
+ }
52
+ catch (e) {
53
+ throw e;
54
+ }
55
+ };
56
+ }
57
+ exports.PassmanCrypto = PassmanCrypto;