1/* 2 * This is hwcrypto.js 0.0.10 generated on 2015-04-17 3 * 4 * Modified by Tran Ha on 29/03/2016 5 * Copyright (c) 2016 VNPT-CA. All rights reserved. 6 * 7 */ 8if (!window.atob) { 9 var tableStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 10 var table = tableStr.split(""); 11 12 window.atob = function(base64) { 13 if (/(=[^=]+|={3,})$/.test(base64)) throw new Error("String contains an invalid character"); 14 base64 = base64.replace(/=/g, ""); 15 var n = base64.length & 3; 16 if (n === 1) throw new Error("String contains an invalid character"); 17 for (var i = 0, j = 0, len = base64.length / 4, bin = []; i < len; ++i) { 18 var a = tableStr.indexOf(base64[j++] || "A"), 19 b = tableStr.indexOf(base64[j++] || "A"); 20 var c = tableStr.indexOf(base64[j++] || "A"), 21 d = tableStr.indexOf(base64[j++] || "A"); 22 if ((a | b | c | d) < 0) throw new Error("String contains an invalid character"); 23 bin[bin.length] = ((a << 2) | (b >> 4)) & 255; 24 bin[bin.length] = ((b << 4) | (c >> 2)) & 255; 25 bin[bin.length] = ((c << 6) | d) & 255; 26 }; 27 return String.fromCharCode.apply(null, bin).substr(0, bin.length + n - 4); 28 }; 29 30 window.btoa = function(bin) { 31 for (var i = 0, j = 0, len = bin.length / 3, base64 = []; i < len; ++i) { 32 var a = bin.charCodeAt(j++), 33 b = bin.charCodeAt(j++), 34 c = bin.charCodeAt(j++); 35 if ((a | b | c) > 255) throw new Error("String contains an invalid character"); 36 base64[base64.length] = table[a >> 2] + table[((a << 4) & 63) | (b >> 4)] + 37 (isNaN(b) ? "=" : table[((b << 2) & 63) | (c >> 6)]) + 38 (isNaN(b + c) ? "=" : table[c & 63]); 39 } 40 return base64.join(""); 41 }; 42 43} 44 45function hexToBase64(str) { 46 return btoa(String.fromCharCode.apply(null, 47 str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))); 48} 49 50function hexToPem(s) { 51 var b = hexToBase64(s); 52 var pem = b.match(/.{1,64}/g).join("\n"); 53 return "-----BEGIN CERTIFICATE-----\n" + pem + "\n-----END CERTIFICATE-----"; 54} 55 56/* EDIT BY TRAN HA (use src/hwcrypto.js) */ 57var hwcrypto = function hwcrypto() { 58 "use strict"; 59 var _debug = function(x) {}; 60 _debug("hwcrypto.js activated"); 61 62 // Get browser name 63 var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; 64 var isChrome = !!window.chrome && !isOpera; 65 var isFirefox = typeof InstallTrigger !== 'undefined'; 66 67 function hasAddonForFirefox() { 68 return new Promise(function(resolve, reject) { 69 var listener = function(result) { 70 window.parent.removeEventListener('message', listener, false); 71 if (result.data === "ok") { 72 console.log("HAS ADDON"); 73 resolve("ok"); 74 } else { 75 console.log("REJECT BY BROWSER"); 76 reject("undefined"); 77 } 78 } 79 window.parent.addEventListener('message', listener, false); 80 var event = document.createEvent('CustomEvent'); 81 event.initCustomEvent("addon_require_message", true, true, { 82 type: "TEST", 83 lang: "", 84 cert: "", 85 hash: "", 86 nonce: "" 87 }); 88 window.parent.document.dispatchEvent(event); 89 90 setTimeout(function() { 91 reject("undefined"); 92 }, 2000); 93 }); 94 } 95 96 top.window.addEventListener = top.window.addEventListener || top.window.attachEvent; 97 98 function hasPluginFor(mime) { 99 if (navigator.mimeTypes && mime in navigator.mimeTypes) { 100 return true; 101 } 102 return false; 103 } 104 105 function hasExtensionFor(cls) { 106 if (typeof top.window[cls] === "function") return true; 107 if (typeof window[cls] === "function") return true; 108 return false; 109 } 110 111 function _hex2array(str) { 112 if (typeof str == "string") { 113 var len = Math.floor(str.length / 2); 114 var ret = new Uint8Array(len); 115 for (var i = 0; i < len; i++) { 116 ret[i] = parseInt(str.substr(i * 2, 2), 16); 117 } 118 return ret; 119 } 120 } 121 122 function _array2hex(args) { 123 var ret = ""; 124 for (var i = 0; i < args.length; i++) ret += (args[i] < 16 ? "0" : "") + args[i].toString(16); 125 return ret.toLowerCase(); 126 } 127 128 function _mimeid(mime) { 129 return "hwc" + mime.replace("/", "").replace("-", ""); 130 } 131 132 function loadPluginFor(mime) { 133 var element = _mimeid(mime); 134 if (document.getElementById(element)) { 135 _debug("Plugin element already loaded"); 136 return document.getElementById(element); 137 } 138 _debug("Loading plugin for " + mime + " into " + element); 139 var objectTag = '<object id="' + element + '" type="' + mime + '" style="width: 1px; height: 1px; position: absolute; visibility: hidden;"></object>'; 140 var div = document.createElement("div"); 141 div.setAttribute("id", "pluginLocation" + element); 142 document.body.appendChild(div); 143 document.getElementById("pluginLocation" + element).innerHTML = objectTag; 144 return document.getElementById(element); 145 } 146 var digidoc_mime = "application/x-digidoc"; 147 var digidoc_chrome = "TokenSigning"; 148 var USER_CANCEL = "user_cancel"; 149 var NO_CERTIFICATES = "no_certificates";
150 var INVALID_ARGUMENT = "invalid_argument"; 151 var TECHNICAL_ERROR = "technical_error"; 152 var NO_IMPLEMENTATION = "no_implementation"; 153 var NOT_ALLOWED = "not_allowed"; 154 155 function probe() { 156 var msg = "probe() detected "; 157 if (hasExtensionFor(digidoc_chrome)) { 158 _debug(msg + digidoc_chrome); 159 } 160 if (hasPluginFor(digidoc_mime)) { 161 _debug(msg + digidoc_mime); 162 } 163 } 164 top.window.addEventListener("load", function(event) { 165 probe(); 166 }); 167 168 function DigiDocPlugin() { 169 this._name = "NPAPI/BHO for application/x-digidoc"; 170 var p = loadPluginFor(digidoc_mime); 171 var certificate_ids = {}; 172 173 function code2str(err) { 174 _debug("Error: " + err + " with: " + p.errorMessage); 175 switch (parseInt(err)) { 176 case 1: 177 return USER_CANCEL; 178 case 2: 179 return INVALID_ARGUMENT; 180 case 17: 181 return INVALID_ARGUMENT; 182 case 19: 183 return NOT_ALLOWED; 184 default: 185 _debug("Unknown error: " + err + " with: " + p.errorMessage); 186 return TECHNICAL_ERROR; 187 } 188 } 189 190 function code2err(err) { 191 return new Error(code2str(err)); 192 } 193 this.check = function() { 194 return new Promise(function(resolve, reject) { 195 setTimeout(function() { 196 resolve(typeof p.version !== "undefined"); 197 }, 0); 198 }); 199 }; 200 this.getVersion = function() { 201 return new Promise(function(resolve, reject) { 202 var v = p.version; 203 resolve(v); 204 }); 205 }; 206 207 this.selectCertSerial = function(options) { 208 if (options && options.lang) { 209 p.pluginLanguage = options.lang; 210 } 211 return new Promise(function(resolve, reject) { 212 try { 213 var v = p.selectCertSerial(); 214 if (parseInt(p.errorCode) !== 0) { 215 reject(code2err(p.errorCode)); 216 } else { 217 certificate_ids[v.cert] = v.id; 218 resolve({ 219 hex: v 220 }); 221 } 222 } catch (ex) { 223 _debug(ex); 224 reject(code2err(p.errorCode)); 225 } 226 }); 227 }; 228 this.signHashData = function(cert, hash, options) { 229 return new Promise(function(resolve, reject) { 230 var cid = certificate_ids[cert.hex]; 231 if (cid) { 232 try { 233 var language = options.lang || "en"; 234 var v = p.signHashData(cid, hash.hex, language); 235 resolve({ 236 hex: v 237 }); 238 } catch (ex) { 239 _debug(JSON.stringify(ex)); 240 reject(code2err(p.errorCode)); 241 } 242 } else { 243 _debug("invalid certificate: " + cert); 244 reject(new Error(INVALID_ARGUMENT)); 245 } 246 }); 247 }; 248 249 250 this.signXMLData = function(hash, options) { 251 return new Promise(function(resolve, reject) { 252 try { 253 var language = options.lang || "en"; 254 var v = p.signXMLData(hash.value, language); 255 resolve({ 256 hex: v 257 }); 258 } catch (ex) { 259 _debug(JSON.stringify(ex)); 260 reject(code2err(p.errorCode)); 261 } 262 }); 263 }; 264 265 } 266 267 function DigiDocExtension() { 268 this._name = "Chrome native messaging extension"; 269 var p = null; 270 this.check = function() { 271 return new Promise(function(resolve, reject) { 272 if (!hasExtensionFor(digidoc_chrome)) { 273 return resolve(false); 274 } 275 p = new top.window[digidoc_chrome](); 276 if (p) { 277 resolve(true); 278 } else { 279 resolve(false); 280 } 281 }); 282 }; 283 this.getVersion = function() { 284 return p.getVersion(); 285 }; 286 this.selectCertSerial = function(options) { 287 return p.selectCertSerial(options); 288 }; 289 this.signHashData = function(cert, hash, options) { 290 return p.signHashData(cert, hash, options); 291 }; 292 this.signXMLData = function(hash, options) { 293 return p.signXMLData(hash, options); 294 }; 295 } 296 297 function NoBackend() { 298 this._name = "No implementation"; 299 this.check = function() { 300 return new Promise(function(resolve, reject) { 301 resolve(true); 302 }); 303 }; 304 this.getVersion = function() { 305 return Promise.reject(new Error(NO_IMPLEMENTATION)); 306 }; 307 this.selectCertSerial = function() { 308 return Promise.reject(new Error(NO_IMPLEMENTATION)); 309 }; 310 this.signHashData = function() { 311 return Promise.reject(new Error(NO_IMPLEMENTATION)); 312 }; 313 this.signXMLData = function() { 314 return Promise.reject(new Error(NO_IMPLEMENTATION)); 315 }; 316 } 317 var _backend = null; 318 var fields = {}; 319 320 function _testAndUse(Backend) { 321 return new Promise(function(resolve, reject) { 322 var b = new Backend(); 323 b.check().then(function(isLoaded) { 324 if (isLoaded) { 325 _debug("Using backend: " + b._name); 326 _backend = b; 327 resolve(true); 328 } else { 329 _debug(b._name + " check() failed"); 330 resolve(false); 331 } 332 }); 333 }); 334 } 335 336 function _autodetect(force) { 337 return new Promise(function(resolve, reject) { 338 _debug("Autodetecting best backend"); 339 if (typeof force === "undefined") { 340 force = false;
341 } 342 if (_backend !== null && !force) { 343 return resolve(true); 344 } 345 346 function tryDigiDocPlugin() { 347 _testAndUse(DigiDocPlugin).then(function(result) { 348 if (result) { 349 resolve(true); 350 } else { 351 resolve(_testAndUse(NoBackend)); 352 } 353 }); 354 } 355 if (navigator.userAgent.indexOf("MSIE") != -1 || navigator.userAgent.indexOf("Trident") != -1) { 356 _debug("Assuming IE BHO, testing"); 357 return tryDigiDocPlugin(); 358 } 359 if (navigator.userAgent.indexOf("Chrome") != -1 && hasExtensionFor(digidoc_chrome)) { 360 _testAndUse(DigiDocExtension).then(function(result) { 361 if (result) { 362 resolve(true); 363 } else { 364 tryDigiDocPlugin(); 365 } 366 }); 367 return; 368 } 369 370 if (navigator.userAgent.indexOf("Firefox") != -1) { 371 _testAndUse(DigiDocExtension).then(function(result) { 372 if (result) { 373 resolve(true); 374 } else { 375 tryDigiDocPlugin(); 376 } 377 }); 378 return; 379 } 380 381 if (hasPluginFor(digidoc_mime)) { 382 return tryDigiDocPlugin(); 383 } 384 resolve(_testAndUse(NoBackend)); 385 }); 386 } 387 fields.use = function(backend) { 388 return new Promise(function(resolve, reject) { 389 if (typeof backend === "undefined" || backend === "auto") { 390 _autodetect().then(function(result) { 391 resolve(result); 392 }); 393 } else { 394 if (backend === "chrome") { 395 resolve(_testAndUse(DigiDocExtension)); 396 } else if (backend === "npapi") { 397 resolve(_testAndUse(DigiDocPlugin)); 398 } else { 399 resolve(false); 400 } 401 } 402 }); 403 }; 404 405 fields.debug = function() { 406 return new Promise(function(resolve, reject) { 407 var hwversion = "hwcrypto.js 0.0.10"; 408 _autodetect().then(function(result) { 409 _backend.getVersion().then(function(version) { 410 resolve(hwversion + " with " + _backend._name + " " + version); 411 }, function(error) { 412 resolve(hwversion + " with failing backend " + _backend._name); 413 }); 414 }); 415 }); 416 }; 417 418 fields.selectCertSerial = function(options) { 419 if (typeof options !== "object") { 420 _debug("getSerialCert options parameter must be an object"); 421 return Promise.reject(new Error(INVALID_ARGUMENT)); 422 } 423 if (options && !options.lang) { 424 options.lang = "en"; 425 } 426 427 if (isChrome) { 428 return _autodetect().then(function(result) { 429 return _backend.selectCertSerial(options).then(function(certificate) { 430 if (certificate.hex && !certificate.encoded) certificate.encoded = _hex2array(certificate.hex); 431 return certificate; 432 }); 433 }); 434 } else if (isFirefox) { 435 return new Promise(function(resolve, reject) { 436 hasAddonForFirefox().then(function(response) { 437 var event = document.createEvent('CustomEvent'); 438 event.initCustomEvent("addon_require_message", true, true, { 439 type: "SERIAL_CERT", 440 lang: options.lang, 441 cert: "", 442 hash: "", 443 nonce: "260906" 444 }); 445 window.parent.document.dispatchEvent(event); 446 var listener = function(result) { 447 window.parent.removeEventListener('message', listener, false); 448 var end_result = JSON.parse(result.data); 449 if (end_result.result === 'ok') { 450 resolve(({ 451 hex: end_result, 452 value: end_result 453 })); 454 } else { 455 reject(end_result); 456 } 457 }; 458 window.parent.addEventListener('message', listener, false); 459 }, function(err) { 460 reject(new Error(NO_IMPLEMENTATION)); 461 }); 462 }); 463 } else { 464 reject(new Error("unsupported_browser")); 465 } 466 }; 467 468 fields.signXMLData = function(hash, options) { 469 if (arguments.length < 2) return Promise.reject(new Error(INVALID_ARGUMENT)); 470 if (options && !options.lang) { 471 options.lang = "en"; 472 } 473 if (!hash.type || !hash.value && !hash.hex) return Promise.reject(new Error(INVALID_ARGUMENT)); 474 if (hash.hex && !hash.value) hash.value = hash.hex; 475 if (hash.value && !hash.hex) hash.hex = hash.value; 476 477 if (isChrome) { 478 return _autodetect().then(function(result) { 479 return _backend.signXMLData(hash, options).then(function(signature) { 480 if (signature.hex && !signature.value) signature.value = _hex2array(signature.hex); 481 return signature; 482 }); 483 }); 484 } else if (isFirefox) { 485 return new Promise(function(resolve, reject) { 486 hasAddonForFirefox().then(function(response) { 487 var event = window.parent.document.createEvent('CustomEvent'); 488 event.initCustomEvent("addon_require_message", true, true, { 489 type: "SIGN", 490 lang: "en", 491 cert: "", 492 hash: hash, 493 nonce: "25251325" 494 }); 495 window.parent.document.dispatchEvent(event); 496 var endlistener = function(result) { 497 window.parent.removeEventListener('message', endlistener, false); 498 var end_result = JSON.parse(result.data); 499 if (end_result.result === 'ok') { 500 resolve(({ 501 hex: end_result, 502 value: end_result 503 })); 504 } else { 505 reject(end_result); 506 } 507 } 508 window.parent.addEventListener('message', endlistener, false); 509 }, function(err) { 510 reject(new Error(NO_IMPLEMENTATION)); 511 }); 512 }); 513 } else { 514 reject(new Error("unsupported_browser")); 515 } 516 }; 517 518 fields.signHashData = function(cert, hash, options) { 519 if (arguments.length < 2) return Promise.reject(new Error(INVALID_ARGUMENT)); 520 if (options && !options.lang) { 521 options.lang = "en"; 522 } 523 if (!hash.type || !hash.value && !hash.hex) return Promise.reject(new Error(INVALID_ARGUMENT)); 524 if (hash.hex && !hash.value) hash.value = hash.hex; 525 if (hash.value && !hash.hex) hash.hex = hash.value; 526 if (isChrome) { 527 528 return new Promise(function(resolve, reject) { 529 setTimeout(function() { 530 resolve(_autodetect().then(function(result) { 531 return _backend.signHashData(cert, hash, options).then(function(signature) { 532 if (signature.hex && !signature.value) signature.value = _hex2array(signature.hex); 533 return signature; 534 }); 535 })); 536 }, 700); 537 }); 538 539 /* 540 // Original hwcrypto method; do not remove 541 return _autodetect().then(function(result) { 542 return _backend.signHashData(cert, hash, options).then(function(signature) { 543 if (signature.hex && !signature.value) signature.value = _hex2array(signature.hex); 544 return signature; 545 }); 546 }); 547 */ 548 } else if (isFirefox) { 549 return new Promise(function(resolve, reject) { 550 hasAddonForFirefox().then(function(response) { 551 var event = window.parent.document.createEvent('CustomEvent'); 552 event.initCustomEvent("addon_require_message", true, true, { 553 type: "SIGN", 554 lang: "en", 555 cert: cert, 556 hash: hash, 557 nonce: "190119" 558 }); 559 window.parent.document.dispatchEvent(event); 560 var endlistener = function(result) { 561 window.parent.removeEventListener('message', endlistener, false); 562 var end_result = JSON.parse(result.data); 563 if (end_result.result === 'ok') { 564 resolve(({ 565 hex: end_result, 566 value: end_result 567 })); 568 } else { 569 reject(end_result); 570 } 571 } 572 window.parent.addEventListener('message', endlistener, false); 573 }, function(err) { 574 reject(new Error(NO_IMPLEMENTATION)); 575 }); 576 }); 577 } else { 578 reject(new Error("unsupported_browser")); 579 } 580 }; 581 582 fields.NO_IMPLEMENTATION = NO_IMPLEMENTATION; 583 fields.USER_CANCEL = USER_CANCEL; 584 fields.NOT_ALLOWED = NOT_ALLOWED; 585 fields.NO_CERTIFICATES = NO_CERTIFICATES; 586 fields.TECHNICAL_ERROR = TECHNICAL_ERROR; 587 fields.INVALID_ARGUMENT = INVALID_ARGUMENT; 588 return fields; 589}();
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.