@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.
- package/README.md +9 -0
- package/lib/BrowserStorage.d.ts +39 -0
- package/lib/BrowserStorage.js +137 -0
- package/lib/Exception/ConfigurationError.d.ts +6 -0
- package/lib/Exception/ConfigurationError.js +11 -0
- package/lib/Exception/FormFieldError.d.ts +4 -0
- package/lib/Exception/FormFieldError.js +2 -0
- package/lib/Interfaces/Credential/CredentialInterface.d.ts +33 -0
- package/lib/Interfaces/Credential/CredentialInterface.js +2 -0
- package/lib/Interfaces/Credential/CustomFieldInterface.d.ts +6 -0
- package/lib/Interfaces/Credential/CustomFieldInterface.js +2 -0
- package/lib/Interfaces/Credential/EncryptedCredentialInterface.d.ts +31 -0
- package/lib/Interfaces/Credential/EncryptedCredentialInterface.js +2 -0
- package/lib/Interfaces/Credential/IconInterface.d.ts +4 -0
- package/lib/Interfaces/Credential/IconInterface.js +2 -0
- package/lib/Interfaces/Credential/OTPConfigInterface.d.ts +14 -0
- package/lib/Interfaces/Credential/OTPConfigInterface.js +2 -0
- package/lib/Interfaces/Credential/TagInterface.d.ts +3 -0
- package/lib/Interfaces/Credential/TagInterface.js +2 -0
- package/lib/Interfaces/CredentialFilterService/FilterStatsInterface.d.ts +10 -0
- package/lib/Interfaces/CredentialFilterService/FilterStatsInterface.js +2 -0
- package/lib/Interfaces/File/DeleteFilesRequestBodyInterface.d.ts +3 -0
- package/lib/Interfaces/File/DeleteFilesRequestBodyInterface.js +2 -0
- package/lib/Interfaces/File/DeleteFilesResponseInterface.d.ts +4 -0
- package/lib/Interfaces/File/DeleteFilesResponseInterface.js +2 -0
- package/lib/Interfaces/File/FileInterface.d.ts +9 -0
- package/lib/Interfaces/File/FileInterface.js +2 -0
- package/lib/Interfaces/File/FileUploadResponseInterface.d.ts +9 -0
- package/lib/Interfaces/File/FileUploadResponseInterface.js +2 -0
- package/lib/Interfaces/LoggingHandlerInterface.d.ts +9 -0
- package/lib/Interfaces/LoggingHandlerInterface.js +2 -0
- package/lib/Interfaces/NextcloudServer/NextcloudServerInterface.d.ts +6 -0
- package/lib/Interfaces/NextcloudServer/NextcloudServerInterface.js +2 -0
- package/lib/Interfaces/PassmanCrypto/GenerateKeypairResponseInterface.d.ts +5 -0
- package/lib/Interfaces/PassmanCrypto/GenerateKeypairResponseInterface.js +2 -0
- package/lib/Interfaces/PassmanCrypto/PEMRSAKeypairInterface.d.ts +4 -0
- package/lib/Interfaces/PassmanCrypto/PEMRSAKeypairInterface.js +2 -0
- package/lib/Interfaces/PassmanCrypto/RSAKeypairInterface.d.ts +5 -0
- package/lib/Interfaces/PassmanCrypto/RSAKeypairInterface.js +2 -0
- package/lib/Interfaces/PasswordGeneratorService/PasswordGeneratorConfigurationInterface.d.ts +9 -0
- package/lib/Interfaces/PasswordGeneratorService/PasswordGeneratorConfigurationInterface.js +2 -0
- package/lib/Interfaces/ReEncryptionService/ReEncryptionProgressInterface.d.ts +7 -0
- package/lib/Interfaces/ReEncryptionService/ReEncryptionProgressInterface.js +2 -0
- package/lib/Interfaces/ReEncryptionService/ReEncryptionStageProgressInterface.d.ts +5 -0
- package/lib/Interfaces/ReEncryptionService/ReEncryptionStageProgressInterface.js +2 -0
- package/lib/Interfaces/Revision/RevisionInterface.d.ts +8 -0
- package/lib/Interfaces/Revision/RevisionInterface.js +2 -0
- package/lib/Interfaces/ShareService/ACLInterface.d.ts +15 -0
- package/lib/Interfaces/ShareService/ACLInterface.js +2 -0
- package/lib/Interfaces/ShareService/CredentialShareRequestInterface.d.ts +16 -0
- package/lib/Interfaces/ShareService/CredentialShareRequestInterface.js +2 -0
- package/lib/Interfaces/Vault/VaultInterface.d.ts +15 -0
- package/lib/Interfaces/Vault/VaultInterface.js +2 -0
- package/lib/Interfaces/Vault/VaultResponseInterface.d.ts +15 -0
- package/lib/Interfaces/Vault/VaultResponseInterface.js +2 -0
- package/lib/LocalPassmanStore.d.ts +4 -0
- package/lib/LocalPassmanStore.js +14 -0
- package/lib/Model/Credential.d.ts +173 -0
- package/lib/Model/Credential.js +594 -0
- package/lib/Model/File.d.ts +15 -0
- package/lib/Model/File.js +55 -0
- package/lib/Model/NextcloudServer.d.ts +27 -0
- package/lib/Model/NextcloudServer.js +108 -0
- package/lib/Model/Revision.d.ts +21 -0
- package/lib/Model/Revision.js +33 -0
- package/lib/Model/SharingACL.d.ts +28 -0
- package/lib/Model/SharingACL.js +48 -0
- package/lib/Model/Vault.d.ts +38 -0
- package/lib/Model/Vault.js +265 -0
- package/lib/PassmanClient.d.ts +20 -0
- package/lib/PassmanClient.js +80 -0
- package/lib/Service/CredentialFilterService.d.ts +24 -0
- package/lib/Service/CredentialFilterService.js +209 -0
- package/lib/Service/CustomMathsService.d.ts +7 -0
- package/lib/Service/CustomMathsService.js +52 -0
- package/lib/Service/DefaultLoggingService.d.ts +10 -0
- package/lib/Service/DefaultLoggingService.js +27 -0
- package/lib/Service/DownloadService.d.ts +12 -0
- package/lib/Service/DownloadService.js +121 -0
- package/lib/Service/OTPService.d.ts +22 -0
- package/lib/Service/OTPService.js +134 -0
- package/lib/Service/PassmanCrypto.d.ts +10 -0
- package/lib/Service/PassmanCrypto.js +57 -0
- package/lib/Service/PasswordGeneratorService.d.ts +6 -0
- package/lib/Service/PasswordGeneratorService.js +73 -0
- package/lib/Service/ReEncryptionService.d.ts +23 -0
- package/lib/Service/ReEncryptionService.js +318 -0
- package/lib/Service/ShareService.d.ts +15 -0
- package/lib/Service/ShareService.js +56 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- 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;
|