PageSourceSearch

https://inbank.lv/scripts/vendor/dokobit/hwcrypto.js

js inbank.lv collected 2026-10-08 12:07:26 UTC 21,077 bytes, 555 lines download raw bytes

1/* eslint-disable */
2// JavaScript library as described in
3// https://github.com/open-eid/hwcrypto.js
4var hwcrypto = (function hwcrypto() {
5    'use strict';
6    var chromeExtensionName = null;
7    var npapiPluginName = null;
8    var nativeHostVersion = null;
9    var isignDebug = function(x) {
10        // console.log(x);
11    };
12    var pluginAvailable = false;
13    isignDebug("hwcrypto.js activated");
14    // Fix up IE8
15    window.addEventListener = window.addEventListener || window.attachEvent;
16    // Returns "true" if a plugin is present for the MIME
17    function hasPluginFor(mime) {
18        if(hwcrypto.pluginAvailable){
19            return true;
20        }
21
22        return navigator.mimeTypes && mime in navigator.mimeTypes;
23    }
24    // Checks if a function is present (used for Chrome)
25    function hasExtensionFor(cls) {
26        try{
27            if (typeof parent[cls] === "function"){
28                window[cls] = parent[cls];
29            }
30        }catch(e){
31            //ignore if can't access parent
32        }
33        if (typeof window[cls] === "function") return true;
34        return false;
35    }
36
37    function _hex2array(str) {
38        if(typeof str == 'string') {
39            var len = Math.floor(str.length / 2);
40            var ret = new Uint8Array(len);
41            for (var i = 0; i < len; i++) {
42                ret[i] = parseInt(str.substr(i * 2, 2), 16);
43            }
44            return ret;
45        }
46    }
47
48    function _array2hex(args) {
49        var ret = "";
50        for(var i = 0; i < args.length; i++) ret += (args[i] < 16 ? "0" : "") + args[i].toString(16);
51        return ret.toLowerCase();
52    }
53
54    function _mimeid(mime) {
55        return "hwc" + mime.replace('/', '').replace('-', '');
56    }
57
58    function loadPluginFor(mime) {
59            var element = _mimeid(mime);
60            if(document.getElementById(element)) {
61                isignDebug("Plugin element already loaded");
62                return document.getElementById(element);
63            }
64            isignDebug('Loading plugin for ' + mime + ' into ' + element);
65            // Must insert tag as string (not as an Element object) so that IE9 can access plugin methods
66            var objectTag = '<object id="' + element + '" type="' + mime + '" style="width: 1px; height: 1px; position: absolute; visibility: hidden;"></object>';
67            var div = document.createElement("div");
68            div.setAttribute("id", 'pluginLocation' + element);
69            document.body.appendChild(div);
70            // Must not manipulate body's innerHTML directly, otherwise previous Element references get lost
71            document.getElementById('pluginLocation' + element).innerHTML = objectTag;
72            return document.getElementById(element);
73        }
74        // Important constants
75
76    var chromeExtensionNames = {
77        'lt': 'IsignChromeSigning',
78        'fi': 'IsignChromeSigning',
79        'lv': 'eParakstsTokenSigning',
80        'ee': 'TokenSigning',
81        'e-residency': 'TokenSigning',
82        'be': 'IsignChromeSigning',
83        'is': 'IsignChromeSigning'
84    };
85    var npapiPluginNames = {
86        'lt': null,
87        'fi': null,
88        'lv': 'application/x-eparaksts',
89        'ee': 'application/x-digidoc',
90        'e-residency': 'application/x-digidoc',
91        'be': null,
92        'is': null
93    };
94    // Some error strings
95    var USER_CANCEL = "user_cancel";
96    var NO_CERTIFICATES = "no_certificates";
97    var INVALID_ARGUMENT = "invalid_argument";
98    var TECHNICAL_ERROR = "technical_error";
99    var NO_IMPLEMENTATION = "no_implementation";
100    var NOT_ALLOWED = "not_allowed";
101    // Probe all existing backends in a failsafe manner.
102    function probe() {
103            fields.calculateHash = false;
104            var msg = 'probe() detected ';
105            // First try Chrome extensions
106            if(hasExtensionFor(window.hwcrypto.chromeExtensionName)) {
107                isignDebug(msg + window.hwcrypto.chromeExtensionName);
108                if(window.hwcrypto.chromeExtensionName != chromeExtensionNames['lt']){
109                    fields.calculateHash = true;
110                    extensionLoaded();
111                }else{
112                    window.hwcrypto.getVersion().then(function(response) {
113//                        if(typeof response.nativeHostVersion == "undefined"){
114//                            updateRequired();
115//                            return;
116//                        }
117                        if(response.nativeHostVersion){
118                            nativeHostVersion = response.nativeHostVersion;
119                        }
120                        extensionLoaded();
121                    }, function(error) {
122                        extensionUnavailable();
123                    });
124                }
125
126                return;
127            }
128
129
130            if(window.hwcrypto.npapiPluginName != null) {
131                _testAndUse(DigiDocPlugin).then(function(result) {
132                    if (result) {
133                        isignDebug(msg + window.hwcrypto.npapiPluginName);
134                        hwcrypto.pluginAvailable = true;
135                        fields.calculateHash = true;
136                        extensionLoaded();
137                    } else {
138                        extensionUnavailable();
139                    }
140                });
141                return;
142            }else{
143                extensionUnavailable();
144            }
145        }
146        // TODO: remove
147//    window.addEventListener('load', function(event) {
148//        // There's a timeout because chrome content script needs to be loaded
149//        probe();
150//    });
151    // Backend for DigiDoc plugin
152    function DigiDocPlugin() {
153            this._name = "NPAPI/BHO for application/x-digidoc";
154            var p = loadPluginFor(window.hwcrypto.npapiPluginName);
155            // keeps track of detected certificates and their ID-s
156            var certificate_ids = {};
157
158            function code2str(err) {
159                isignDebug("Error: " + err + " with: " + p.errorMessage);
160                switch(parseInt(err)) {
161                    case 1:
162                        return USER_CANCEL;
163                    case 2:
164                        return INVALID_ARGUMENT;
165                    case 17:
166                        // invalid hash length
167                        return INVALID_ARGUMENT;
168                    case 19:
169                        return NOT_ALLOWED;
170                    default:
171                        isignDebug("Unknown error: " + err + " with: " + p.errorMessage);
172                        return TECHNICAL_ERROR;
173                }
174            }
175
176            function code2err(err) {
177                return new Error(code2str(err));
178            }
179            this.check = function() {
180                return new Promise(function(resolve, reject) {
181                    // IE8 cannot access the newly inserted plugin object before the end of call queue
182                    setTimeout(function() {
183                        resolve(typeof p.version !== "undefined");
184                    }, 0);
185                });
186            };
187            this.getVersion = function() {
188                return new Promise(function(resolve, reject) {
189                    var v = p.version;
190                    resolve(v);
191                });
192            };
193            this.getCertificate = function(options) {
194                // Ignore everything except language
195                if(options && options.lang) {
196                    p.pluginLanguage = options.lang;
197                }
198                return new Promise(function(resolve, reject) {
199                    try {
200                        var v = p.getCertificate();
201                        if(parseInt(p.errorCode) !== 0) {
202                            reject(code2err(p.errorCode));
203                        } else {
204                            // Store plugin-internal ID
205                            certificate_ids[v.cert] = v.id;
206                            resolve({
207                                hex: v.cert
208                            });
209                        }
210                    } catch(ex) {
211                        isignDebug(ex);
212                        reject(code2err(p.errorCode));
213                    }
214                });
215            };
216            this.sign = function(cert, hash, options) {
217                return new Promise(function(resolve, reject) {
218                    // get the ID of the certificate
219                    var cid = certificate_ids[cert.hex];
220                    if(cid) {
221                        try {
222                            //var v = p.sign(cid, hash, 'en'); // FIXME: only BHO requires language but does not use it
223                            var language = options.lang || 'en';
224                            //p.pluginLanguage = language;
225                            var v = p.sign(cid, hash.hex, language);
226                            resolve({
227                                hex: v
228                            });
229                        } catch(ex) {
230                            isignDebug(JSON.stringify(ex));
231                            reject(code2err(p.errorCode));
232                        }
233                    } else {
234                        isignDebug("invalid certificate: " + cert);
235                        reject(new Error(INVALID_ARGUMENT));
236                    }
237                });
238            };
239        }
240        // Backend for Digidoc Chrome Extension
241    function DigiDocExtension() {
242        this._name = "Chrome native messaging extension";
243        var p = null;
244        var _this = this;
245        this.check = function() {
246            return new Promise(function(resolve, reject) {
247                if (!hasExtensionFor(window.hwcrypto.chromeExtensionName)) {
248                    return resolve(false);
249                }
250                // FIXME: remove this from content script!
251                p = new window[window.hwcrypto.chromeExtensionName]();
252                if (p) {
253                    resolve(true);
254                } else {
255                    resolve(false);
256                }
257            });
258        };
259        this.getVersion = function() {
260            return p.getVersion();
261        };
262        this.getCertificate = function(options) {
263            return p.getCertificate(options);
264        };
265        this.sign = function(cert, hash, options) {
266            return p.sign(cert, hash, options);
267        };
268    }
269
270    // Dummy
271    function NoBackend() {
272        this._name = "No implementation";
273        this.check = function() {
274            return new Promise(function(resolve, reject) {
275                resolve(true);
276            });
277        };
278        this.getVersion = function() {
279            return Promise.reject(new Error(NO_IMPLEMENTATION));
280        };
281        this.getCertificate = function() {
282            return Promise.reject(new Error(NO_IMPLEMENTATION));
283        };
284        this.sign = function() {
285            return Promise.reject(new Error(NO_IMPLEMENTATION));
286        };
287    }
288    // Active backend
289    var _backend = null;
290    // To be exposed
291    var fields = {};
292
293    function _testAndUse(Backend) {
294        return new Promise(function(resolve, reject) {
295            var b = new Backend();
296            b.check().then(function(isLoaded) {
297                if (isLoaded) {
298                    isignDebug("Using backend: " + b._name);
299                    _backend = b;
300                    resolve(true);
301                } else {
302                    isignDebug(b._name + " check() failed");
303                    resolve(false);
304                }
305            });
306        });
307    }
308
309    function browserSupportsIsignExtension(){
310        var userAgent = navigator.userAgent.toLowerCase();
311
312        if(userAgent.match(/opera|opr\//)){
313            return false;
314        }
315
316        if(userAgent.indexOf('chrome') > -1){
317            return true;
318        }
319
320        if(userAgent.indexOf('firefox') > -1){
321            var matches = userAgent.match(/firefox\/([0-9\.]+)/);
322            if(matches.length > 1 && parseInt(matches[1]) >= 50){
323                return true;
324            }
325        }
326
327        return false;
328    }
329
330    function _autodetect(force) {
331        return new Promise(function(resolve, reject) {
332            isignDebug("Autodetecting best backend");
333            if (typeof force === 'undefined') {
334                force = false;
335            }
336            if (_backend !== null && !force) {
337                return resolve(true);
338            }
339
340            function tryDigiDocPlugin() {
341                _testAndUse(DigiDocPlugin).then(function(result) {
342                    if (result) {
343                        resolve(true);
344                    } else {
345                        resolve(_testAndUse(NoBackend));
346                    }
347                });
348            }
349
350            // IE BHO
351            if (navigator.userAgent.indexOf("MSIE") != -1 || navigator.userAgent.indexOf("Trident") != -1) {
352                isignDebug("Assuming IE BHO, testing");
353                return tryDigiDocPlugin();
354            }
355
356            // Chrome extension or NPAPI
357            if (browserSupportsIsignExtension() && hasExtensionFor(window.hwcrypto.chromeExtensionName)) {
358                _testAndUse(DigiDocExtension).then(function(result) {
359                    if (result) {
360                        resolve(true);
361                    } else {
362                        tryDigiDocPlugin();
363                    }
364                });
365                return;
366            }
367
368            // Other browsers with NPAPI support
369            if (window.hwcrypto.npapiPluginName != null && hasPluginFor(window.hwcrypto.npapiPluginName)) {
370                return tryDigiDocPlugin();
371            }
372
373            // No backend supported
374            resolve(_testAndUse(NoBackend));
375        });
376    }
377    // Use a specific backend or autodetect
378    fields.use = function(backend) {
379        return new Promise(function(resolve, reject) {
380            if (typeof backend === "undefined" || backend === 'auto') {
381                _autodetect().then(function(result) { resolve(result);});
382            } else {
383                if (backend === "chrome") {
384                    resolve(_testAndUse(DigiDocExtension));
385                } else if (backend === "npapi") {
386                    resolve(_testAndUse(DigiDocPlugin));
387                } else {
388                    resolve(false); // unknown backend
389                }
390            }
391        });
392    };
393    // Give debugging information.
394    fields.debug = function() {
395        return new Promise(function(resolve, reject) {
396            var hwversion = "hwcrypto.js 0.0.10";
397            _autodetect().then(function(result) {
398                _backend.getVersion().then(function(version) {
399                    resolve(hwversion + " with " + _backend._name + " " + version);
400                }, function(error) {
401                    resolve(hwversion + " with failing backend " + _backend._name);
402                });
403            });
404        });
405    };
406    fields.getVersion = function() {
407        return _autodetect().then(function(result) {
408            return _backend.getVersion().then(function(result) {
409                return result;
410            });
411        });
412    };
413    // Get a certificate
414    fields.getCertificate = function(options) {
415        if(typeof options !== 'object') {
416            isignDebug("getCertificate options parameter must be an object");
417            return Promise.reject(new Error(INVALID_ARGUMENT));
418        }
419        // If options does not specify a language, set to 'en'
420        if(options && !options.lang) {
421            options.lang = 'en';
422        }
423        if (options && !options.certificatePurpose) {
424            options.certificatePurpose = "sign";
425        }
426        if (options && !options.bulkSigning) {
427            options.bulkSigning = false;
428        }
429        if (options && !options.isInitial) {
430            options.isInitial = false;
431        }
432        if (options && !options.policyIds) {
433            options.policyIds = [];
434        }
435        return _autodetect().then(function(result) {
436            // FIXME: dummy security check in website context
437//            if (location.protocol !== 'https:' && location.protocol !== 'file:') {
438//                return Promise.reject(new Error(NOT_ALLOWED));
439//            }
440            return _backend.getCertificate(options).then(function(certificate) {
441                // Add binary value as well
442                if (certificate.hardwareLabel && nativeHostVersion == '1.1.0' && typeof updateRequired === 'function'){
443                    updateRequired();
444                    return {'hex': ''};
445                }
446                if (certificate.hex && !certificate.encoded)
447                    certificate.encoded = _hex2array(certificate.hex);
448                return certificate;
449            });
450        });
451    };
452    // Sign a hash
453    fields.sign = function(cert, hash, options) {
454        if (arguments.length < 2)
455            return Promise.reject(new Error(INVALID_ARGUMENT));
456        // If options does not specify a language, set to 'en'
457        if(options && !options.lang) {
458            options.lang = 'en';
459        }
460        // Hash type and value must be present
461        if (!hash.type || (!hash.value && !hash.hex))
462            return Promise.reject(new Error(INVALID_ARGUMENT));
463
464        // Convert Hash to hex and vice versa.
465        // TODO: All backends currently expect the presence of Hex.
466        if (hash.hex && !hash.value) {
467            isignDebug("DEPRECATED: hash.hex as argument to sign() is deprecated, use hash.value instead");
468            hash.value = _hex2array(hash.hex);
469        }
470        if (hash.value && !hash.hex)
471            hash.hex = _array2hex(hash.value);
472
473        return _autodetect().then(function(result) {
474            // FIXME: dummy security check in website context
475//            if(location.protocol !== 'https:' && location.protocol !== 'file:') {
476//                return Promise.reject(new Error(NOT_ALLOWED));
477//            }
478            return _backend.sign(cert, hash, options).then(function(signature) {
479                // Add binary value as well
480                // TODO: all backends return hex currently
481                if (signature.hex && !signature.value)
482                    signature.value = _hex2array(signature.hex);
483                return signature;
484            });
485        });
486    };
487    fields.reset = function(){
488        _backend = null;
489    };
490    fields.probe = probe;
491    fields.hasExtensionFor = hasExtensionFor;
492    fields.hasPluginFor = hasPluginFor;
493    fields.NO_IMPLEMENTATION = NO_IMPLEMENTATION;
494    fields.USER_CANCEL = USER_CANCEL;
495    fields.NOT_ALLOWED = NOT_ALLOWED;
496    fields.NO_CERTIFICATES = NO_CERTIFICATES;
497    fields.TECHNICAL_ERROR = TECHNICAL_ERROR;
498    fields.INVALID_ARGUMENT = INVALID_ARGUMENT;
499    fields.calculateHash = false;
500    fields.chromeExtensionNames = chromeExtensionNames;
501    fields.npapiPluginNames = npapiPluginNames;
502    fields.missingDriversUrls = {
503        'lt': 'https://www.isign.io/lt/tvarkykliu-atsisiuntimai',
504        'en': 'https://www.isign.io/driver-downloads',
505        'et': 'https://www.isign.io/driver-downloads',
506        'ru': 'https://www.isign.io/driver-downloads',
507        'is': 'https://www.audkenni.is/en/electronic-certificates/nexus-hugbunadur-en/',
508    };
509    fields.missingSoftwareUrls = {
510        'lt': {
511            'lt': 'https://www.isign.io/lt/atsisiuntimai',
512            'en': 'https://www.isign.io/downloads',
513            'et': 'https://www.isign.io/downloads',
514            'ru': 'https://www.isign.io/downloads'
515        },
516        'fi': {
517            'lt': 'https://www.isign.io/lt/atsisiuntimai',
518            'en': 'https://www.isign.io/downloads',
519            'et': 'https://www.isign.io/downloads',
520            'ru': 'https://www.isign.io/downloads'
521        },
522        'lv': {
523            'lt': 'https://www.eparaksts.lv/en/',
524            'en': 'https://www.eparaksts.lv/en/',
525            'et': 'https://www.eparaksts.lv/en/',
526            'ru': 'https://www.eparaksts.lv/ru/',
527            'lv': 'https://www.eparaksts.lv/lv/'
528        },
529        'ee': {
530            'lt': 'https://installer.id.ee/?lang=eng',
531            'en': 'https://installer.id.ee/?lang=eng',
532            'et': 'https://installer.id.ee/',
533            'ru': 'https://installer.id.ee/?lang=rus'
534        },
535        'e-residency': {
536            'lt': 'https://installer.id.ee/?lang=eng',
537            'en': 'https://installer.id.ee/?lang=eng',
538            'et': 'https://installer.id.ee/',
539            'ru': 'https://installer.id.ee/?lang=rus'
540        },
541        'be': {
542            'lt': 'https://www.isign.io/lt/atsisiuntimai',
543            'en': 'https://www.isign.io/downloads',
544            'et': 'https://www.isign.io/downloads',
545            'ru': 'https://www.isign.io/downloads'
546        },
547        'is': {
548            'lt': 'https://www.isign.io/lt/atsisiuntimai',
549            'en': 'https://www.isign.io/downloads',
550            'et': 'https://www.isign.io/downloads',
551            'ru': 'https://www.isign.io/downloads'
552        },
553    };
554    return fields;
555}());

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.