1 /* base64x-1.1.31 (c) 2012-2023 Kenji Urushima | kjur.github.io/jsrsasign/license 2 */ 3 /* 4 * base64x.js - Base64url and supplementary functions for Tom Wu's base64.js library 5 * 6 * Copyright (c) 2012-2023 Kenji Urushima (kenji.urushima@gmail.com) 7 * 8 * This software is licensed under the terms of the MIT License. 9 * https://kjur.github.io/jsrsasign/license 10 * 11 * The above copyright and license notice shall be 12 * included in all copies or substantial portions of the Software. 13 */ 14 15 /** 16 * @fileOverview 17 * @name base64x-1.1.js 18 * @author Kenji Urushima kenji.urushima@gmail.com 19 * @version jsrsasign 10.7.0 base64x 1.1.31 (2023-Mar-11) 20 * @since jsrsasign 2.1 21 * @license <a href="https://kjur.github.io/jsrsasign/license/">MIT License</a> 22 */ 23 24 var KJUR; 25 if (typeof KJUR == "undefined" || !KJUR) KJUR = {}; 26 if (typeof KJUR.lang == "undefined" || !KJUR.lang) KJUR.lang = {}; 27 28 /** 29 * String and its utility class <br/> 30 * This class provides some static utility methods for string. 31 * @class String and its utility class 32 * @author Kenji Urushima 33 * @version 1.0 (2016-Aug-05) 34 * @since base64x 1.1.7 jsrsasign 5.0.13 35 * @description 36 * <br/> 37 * This class provides static methods for string utility. 38 * <dl> 39 * <dt><b>STRING TYPE CHECKERS</b> 40 * <dd> 41 * <ul> 42 * <li>{@link KJUR.lang.String.isInteger} - check whether argument is an integer</li> 43 * <li>{@link KJUR.lang.String.isHex} - check whether argument is a hexadecimal string</li> 44 * <li>{@link KJUR.lang.String.isBase64} - check whether argument is a Base64 encoded string</li> 45 * <li>{@link KJUR.lang.String.isBase64URL} - check whether argument is a Base64URL encoded string</li> 46 * <li>{@link KJUR.lang.String.isIntegerArray} - check whether argument is an array of integers</li> 47 * <li>{@link KJUR.lang.String.isPrintable} - check whether argument is PrintableString accepted characters</li> 48 * <li>{@link KJUR.lang.String.isIA5} - check whether argument is IA5String accepted characters</li> 49 * <li>{@link KJUR.lang.String.isMail} - check whether argument is RFC 822 e-mail address format</li> 50 * </ul> 51 * </dl> 52 */ 53 KJUR.lang.String = function() {}; 54 55 /** 56 * Base64URL and supplementary functions for Tom Wu's base64.js library.<br/> 57 * This class is just provide information about global functions 58 * defined in 'base64x.js'. The 'base64x.js' script file provides 59 * global functions for converting following data each other. 60 * <ul> 61 * <li>(ASCII) String</li> 62 * <li>UTF8 String including CJK, Latin and other characters</li> 63 * <li>byte array</li> 64 * <li>hexadecimal encoded String</li> 65 * <li>Full URIComponent encoded String (such like "%69%94")</li> 66 * <li>Base64 encoded String</li> 67 * <li>Base64URL encoded String</li> 68 * </ul> 69 * All functions in 'base64x.js' are defined in {@link global__} and not 70 * in this class. 71 * 72 * @class Base64URL and supplementary functions for Tom Wu's base64.js library 73 * @author Kenji Urushima 74 * @version 1.1 (07 May 2012) 75 * @requires base64.js 76 * @see <a href="https://kjur.github.io/jsjws/">'jwjws'(JWS JavaScript Library) home page https://kjur.github.io/jsjws/</a> 77 * @see <a href="https://kjur.github.io/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page https://kjur.github.io/jsrsasign/</a> 78 */ 79 function Base64x() { 80 } 81 82 // ==== string / byte array ================================ 83 /** 84 * convert a string to an array of character codes 85 * @name stoBA 86 * @function 87 * @param {String} s 88 * @return {Array of Numbers} 89 */ 90 function stoBA(s) { 91 var a = new Array(); 92 for (var i = 0; i < s.length; i++) { 93 a[i] = s.charCodeAt(i); 94 } 95 return a; 96 } 97 98 /** 99 * convert an array of character codes to a string 100 * @name BAtos 101 * @function 102 * @param {Array of Numbers} a array of character codes 103 * @return {String} s 104 */ 105 function BAtos(a) { 106 var s = ""; 107 for (var i = 0; i < a.length; i++) { 108 s = s + String.fromCharCode(a[i]); 109 } 110 return s; 111 } 112 113 // ==== byte array / hex ================================ 114 /** 115 * convert an array of bytes(Number) to hexadecimal string.<br/> 116 * @name BAtohex 117 * @function 118 * @param {Array of Numbers} a array of bytes 119 * @return {String} hexadecimal string 120 */ 121 function BAtohex(a) { 122 var s = ""; 123 for (var i = 0; i < a.length; i++) { 124 var hex1 = a[i].toString(16); 125 if (hex1.length == 1) hex1 = "0" + hex1; 126 s = s + hex1; 127 } 128 return s; 129 } 130 131 // ==== string / hex ================================ 132 /** 133 * convert a ASCII string to a hexadecimal string of ASCII codes.<br/> 134 * NOTE: This can't be used for non ASCII characters. 135 * @name stohex 136 * @function 137 * @param {s} s ASCII string 138 * @return {String} hexadecimal string 139 */ 140 function stohex(s) { 141 return BAtohex(stoBA(s)); 142 } 143 144 // ==== string / base64 ================================ 145 /** 146 * convert a ASCII string to a Base64 encoded string.<br/> 147 * NOTE: This can't be used for non ASCII characters. 148 * @name stob64 149 * @function 150 * @param {s} s ASCII string 151 * @return {String} Base64 encoded string 152 */ 153 function stob64(s) { 154 return hex2b64(stohex(s)); 155 } 156 157 // ==== string / base64url ================================ 158 /** 159 * convert a ASCII string to a Base64URL encoded string.<br/> 160 * NOTE: This can't be used for non ASCII characters. 161 * @name stob64u 162 * @function 163 * @param {s} s ASCII string 164 * @return {String} Base64URL encoded string 165 */ 166 function stob64u(s) { 167 return b64tob64u(hex2b64(stohex(s))); 168 } 169 170 /** 171 * convert a Base64URL encoded string to a ASCII string.<br/> 172 * NOTE: This can't be used for Base64URL encoded non ASCII characters. 173 * @name b64utos 174 * @function 175 * @param {s} s Base64URL encoded string 176 * @return {String} ASCII string 177 */ 178 function b64utos(s) { 179 return BAtos(b64toBA(b64utob64(s))); 180 } 181 182 // ==== base64 / base64url ================================ 183 /** 184 * convert a Base64 encoded string to a Base64URL encoded string.<br/> 185 * @name b64tob64u 186 * @function 187 * @param {String} s Base64 encoded string 188 * @return {String} Base64URL encoded string 189 * @example 190 * b64tob64u("ab+c3f/==") → "ab-c3f_" 191 */ 192 function b64tob64u(s) { 193 s = s.replace(/\=/g, ""); 194 s = s.replace(/\+/g, "-"); 195 s = s.replace(/\//g, "_"); 196 return s; 197 } 198 199 /** 200 * convert a Base64URL encoded string to a Base64 encoded string.<br/> 201 * @name b64utob64 202 * @function 203 * @param {String} s Base64URL encoded string 204 * @return {String} Base64 encoded string 205 * @example 206 * b64utob64("ab-c3f_") → "ab+c3f/==" 207 */ 208 function b64utob64(s) { 209 if (s.length % 4 == 2) s = s + "=="; 210 else if (s.length % 4 == 3) s = s + "="; 211 s = s.replace(/-/g, "+"); 212 s = s.replace(/_/g, "/"); 213 return s; 214 } 215 216 // ==== hex / base64url ================================ 217 /** 218 * convert a hexadecimal string to a Base64URL encoded string.<br/> 219 * @name hextob64u 220 * @function 221 * @param {String} s hexadecimal string 222 * @return {String} Base64URL encoded string 223 * @description 224 * convert a hexadecimal string to a Base64URL encoded string. 225 * NOTE: If leading "0" is omitted and odd number length for 226 * hexadecimal leading "0" is automatically added. 227 */ 228 function hextob64u(s) { 229 if (s.length % 2 == 1) s = "0" + s; 230 return b64tob64u(hex2b64(s)); 231 } 232 233 /** 234 * convert a Base64URL encoded string to a hexadecimal string.<br/> 235 * @name b64utohex 236 * @function 237 * @param {String} s Base64URL encoded string 238 * @return {String} hexadecimal string 239 */ 240 function b64utohex(s) { 241 return b64tohex(b64utob64(s)); 242 } 243 244 // ==== utf8 / base64url ================================ 245 246 /** 247 * convert a UTF-8 encoded string including CJK or Latin to a Base64URL encoded string.<br/> 248 * @name utf8tob64u 249 * @function 250 * @param {String} s UTF-8 encoded string 251 * @return {String} Base64URL encoded string 252 * @since 1.1 253 * @example 254 * utf8tob64u("あ") → "44GC" 255 * utf8tob64u("aaa") → "YWFh" 256 */ 257 258 /** 259 * convert a Base64URL encoded string to a UTF-8 encoded string including CJK or Latin.<br/> 260 * @name b64utoutf8 261 * @function 262 * @param {String} s Base64URL encoded string 263 * @return {String} UTF-8 encoded string 264 * @since 1.1 265 * @example 266 * b64utoutf8("44GC") → "あ" 267 * b64utoutf8("YWFh") → "aaa" 268 */ 269 270 var utf8tob64u, b64utoutf8; 271 272 if (typeof Buffer === 'function') { 273 utf8tob64u = function (s) { 274 return b64tob64u(Buffer.from(s, 'utf8').toString('base64')); 275 }; 276 277 b64utoutf8 = function (s) { 278 return Buffer.from(b64utob64(s), 'base64').toString('utf8'); 279 }; 280 } else { 281 utf8tob64u = function (s) { 282 return hextob64u(uricmptohex(encodeURIComponentAll(s))); 283 }; 284 285 b64utoutf8 = function (s) { 286 return decodeURIComponent(hextouricmp(b64utohex(s))); 287 }; 288 } 289 290 // ==== utf8 / base64url ================================ 291 /** 292 * convert a UTF-8 encoded string including CJK or Latin to a Base64 encoded string.<br/> 293 * @name utf8tob64 294 * @function 295 * @param {String} s UTF-8 encoded string 296 * @return {String} Base64 encoded string 297 * @since 1.1.1 298 */ 299 function utf8tob64(s) { 300 return hex2b64(uricmptohex(encodeURIComponentAll(s))); 301 } 302 303 /** 304 * convert a Base64 encoded string to a UTF-8 encoded string including CJK or Latin.<br/> 305 * @name b64toutf8 306 * @function 307 * @param {String} s Base64 encoded string 308 * @return {String} UTF-8 encoded string 309 * @since 1.1.1 310 */ 311 function b64toutf8(s) { 312 return decodeURIComponent(hextouricmp(b64tohex(s))); 313 } 314 315 // ==== utf8 / hex ================================ 316 /** 317 * convert a UTF-8 encoded string including CJK or Latin to a hexadecimal encoded string.<br/> 318 * @name utf8tohex 319 * @function 320 * @param {String} s UTF-8 encoded string 321 * @return {String} hexadecimal encoded string 322 * @since 1.1.1 323 */ 324 function utf8tohex(s) { 325 return uricmptohex(encodeURIComponentAll(s)).toLowerCase(); 326 } 327 328 /** 329 * convert a hexadecimal encoded string to a UTF-8 encoded string including CJK or Latin.<br/> 330 * Note that when input is improper hexadecimal string as UTF-8 string, this function returns 331 * 'null'. 332 * @name hextoutf8 333 * @function 334 * @param {String} s hexadecimal encoded string 335 * @return {String} UTF-8 encoded string or null 336 * @since 1.1.1 337 */ 338 function hextoutf8(s) { 339 try { 340 return decodeURIComponent(hextouricmp(s)); 341 } catch(ex) { 342 return null; 343 } 344 } 345 346 // ==== iso8859-1 latin1 / utf8 =================== 347 /** 348 * convert a hexadecimal ISO 8859-1 latin string to UTF-8 string<br/> 349 * @name iso88591hextoutf8 350 * @function 351 * @param {String} h hexadecimal ISO 8859-1 latin string 352 * @return {String} UTF-8 string 353 * @since jsrsasign 10.5.12 base64x 1.1.25 354 * @see utf8toiso88591hex 355 * 356 * @example 357 * iso88591hextoutf8("41a9fa") → "A©ú" 358 */ 359 function iso88591hextoutf8(h) { 360 return hextoutf8(iso88591hextoutf8hex(h)); 361 } 362 363 /** 364 * convert UTF-8 string to a hexadecimal ISO 8859-1 latin string<br/> 365 * @name utf8toiso88591hex 366 * @function 367 * @param {String} s hexadecimal ISO 8859-1 latin string 368 * @return {String} UTF-8 string 369 * @since jsrsasign 10.5.12 base64x 1.1.25 370 * @see iso88591hextoutf8 371 * 372 * @example 373 * utf8toiso88591hex("A©ú") → "41a9fa" 374 */ 375 function utf8toiso88591hex(s) { 376 return utf8hextoiso88591hex(utf8tohex(s)); 377 } 378 379 /** 380 * convert a hexadecimal ISO 8859-1 latin string to UTF-8 hexadecimal string<br/> 381 * @name iso88591hextoutf8hex 382 * @function 383 * @param {String} h hexadecimal ISO 8859-1 latin string 384 * @return {String} UTF-8 hexadecimal string 385 * @since jsrsasign 10.5.12 base64x 1.1.25 386 * @see iso88591hextoutf8 387 * @see utf8hextoiso88591hex 388 * 389 * @example 390 * iso88591hextoutf8hex("41a9fa") → "41c2a9c3ba" 391 */ 392 function iso88591hextoutf8hex(h) { 393 var a = h.match(/.{1,2}/g); 394 var a2 = []; 395 for (var i = 0; i < a.length; i++) { 396 var di = parseInt(a[i], 16); 397 if (0xa1 <= di && di <= 0xbf) { 398 a2.push("c2"); 399 a2.push(a[i]); 400 } else if (0xc0 <= di && di <= 0xff) { 401 a2.push("c3"); 402 a2.push((di - 64).toString(16)); 403 } else { 404 a2.push(a[i]); 405 } 406 } 407 return a2.join(''); 408 } 409 410 /** 411 * convert UTF-8 string to a hexadecimal ISO 8859-1 latin string<br/> 412 * @name utf8hextoiso88591hex 413 * @function 414 * @param {String} h hexadecimal UTF-8 string 415 * @return {String} hexadecimal ISO 8859-1 latin string 416 * @since jsrsasign 10.5.12 base64x 1.1.25 417 * @see iso88591hextoutf8hex 418 * @see utf8toiso88591hex 419 * 420 * @example 421 * utf8hextoiso88591hex("41c2a9c3ba") → "41a9fa" 422 */ 423 function utf8hextoiso88591hex(h) { 424 var a = h.match(/.{1,2}/g); 425 var a2 = []; 426 for (var i = 0; i < a.length; i++) { 427 if (a[i] == 'c2') { 428 i++; 429 a2.push(a[i]); 430 } else if (a[i] == 'c3') { 431 i++; 432 var ci = a[i]; 433 var di = parseInt(a[i], 16) + 64; 434 a2.push(di.toString(16)); 435 } else { 436 a2.push(a[i]); 437 } 438 } 439 return a2.join(''); 440 } 441 442 // ==== rstr / hex ================================ 443 /** 444 * convert a hexadecimal encoded string to raw string including non printable characters.<br/> 445 * @name hextorstr 446 * @function 447 * @param {String} s hexadecimal encoded string 448 * @return {String} raw string 449 * @since 1.1.2 450 * @example 451 * hextorstr("610061") → "a\x00a" 452 */ 453 function hextorstr(sHex) { 454 var s = ""; 455 for (var i = 0; i < sHex.length - 1; i += 2) { 456 s += String.fromCharCode(parseInt(sHex.substr(i, 2), 16)); 457 } 458 return s; 459 } 460 461 /** 462 * convert a raw string including non printable characters to hexadecimal encoded string.<br/> 463 * @name rstrtohex 464 * @function 465 * @param {String} s raw string 466 * @return {String} hexadecimal encoded string 467 * @since 1.1.2 468 * @example 469 * rstrtohex("a\x00a") → "610061" 470 */ 471 function rstrtohex(s) { 472 var result = ""; 473 for (var i = 0; i < s.length; i++) { 474 result += ("0" + s.charCodeAt(i).toString(16)).slice(-2); 475 } 476 return result; 477 } 478 479 // ==== hex / b64nl ======================================= 480 481 /** 482 * convert a hexadecimal string to Base64 encoded string<br/> 483 * @name hextob64 484 * @function 485 * @param {String} s hexadecimal string 486 * @return {String} resulted Base64 encoded string 487 * @since base64x 1.1.3 488 * @description 489 * This function converts from a hexadecimal string to Base64 encoded 490 * string without new lines. 491 * @example 492 * hextob64("616161") → "YWFh" 493 */ 494 function hextob64(s) { 495 return hex2b64(s); 496 } 497 498 /** 499 * convert a hexadecimal string to Base64 encoded string with new lines<br/> 500 * @name hextob64nl 501 * @function 502 * @param {String} s hexadecimal string 503 * @return {String} resulted Base64 encoded string with new lines 504 * @since base64x 1.1.3 505 * @description 506 * This function converts from a hexadecimal string to Base64 encoded 507 * string with new lines for each 64 characters. This is useful for 508 * PEM encoded file. 509 * @example 510 * hextob64nl("123456789012345678901234567890123456789012345678901234567890") 511 * → 512 * MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4 // new line 513 * OTAxMjM0NTY3ODkwCg== 514 */ 515 function hextob64nl(s) { 516 return foldnl(hextob64(s), 64); 517 } 518 519 /** 520 * wrap string with new lines to fit in specified width<br/> 521 * @name foldnl 522 * @function 523 * @param {string} s string 524 * @param {number} n width 525 * @return {string} wrapped string with new lines 526 * @since jsrsasign 10.7.0 base64x 1.1.31 527 * @description 528 * This function wrap a string with new lines to fit in specified width. 529 * @example 530 * foldnl("1234567890", 6) 531 * → 532 * 123456 533 * 7890 534 */ 535 function foldnl(s, n) { 536 return s.replace(new RegExp('(.{' + n + '})', 'g'), "$1\r\n"); 537 } 538 539 /** 540 * convert a Base64 encoded string with new lines to a hexadecimal string<br/> 541 * @name b64nltohex 542 * @function 543 * @param {String} s Base64 encoded string with new lines 544 * @return {String} hexadecimal string 545 * @since base64x 1.1.3 546 * @description 547 * This function converts from a Base64 encoded 548 * string with new lines to a hexadecimal string. 549 * This is useful to handle PEM encoded file. 550 * This function removes any non-Base64 characters (i.e. not 0-9,A-Z,a-z,\,+,=) 551 * including new line. 552 * @example 553 * hextob64nl( 554 * "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4\r\n" + 555 * "OTAxMjM0NTY3ODkwCg==\r\n") 556 * → 557 * "123456789012345678901234567890123456789012345678901234567890" 558 */ 559 function b64nltohex(s) { 560 var b64 = s.replace(/[^0-9A-Za-z\/+=]*/g, ''); 561 var hex = b64tohex(b64); 562 return hex; 563 } 564 565 // ==== b64 / pem ========================================= 566 /** 567 * get PEM string from Base64 string 568 * @name b64topem 569 * @function 570 * @param {string} b64 Base64 string of PEM body 571 * @param {string} pemHeader PEM header string (ex. 'RSA PRIVATE KEY') 572 * @return {string} PEM formatted string of input data 573 * @since jsrasign 10.7.0 base64x 1.1.31 574 * @description 575 * This function converts a Base64 string to a PEM string with 576 * a specified header. Its line break will be CRLF("\r\n"). 577 * @example 578 * b64topem('YWFh', 'RSA PRIVATE KEY') → 579 * -----BEGIN PRIVATE KEY----- 580 * YWFh 581 * -----END PRIVATE KEY----- 582 */ 583 function b64topem(b64, pemHeader) { 584 return "-----BEGIN " + pemHeader + "-----\r\n" + 585 foldnl(b64, 64) + 586 "\r\n-----END " + pemHeader + "-----\r\n"; 587 } 588 589 590 591 // ==== hex / pem ========================================= 592 593 /** 594 * get PEM string from hexadecimal data and header string 595 * @name hextopem 596 * @function 597 * @param {String} dataHex hexadecimal string of PEM body 598 * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY') 599 * @return {String} PEM formatted string of input data 600 * @since jsrasign 7.2.1 base64x 1.1.12 601 * @description 602 * This function converts a hexadecimal string to a PEM string with 603 * a specified header. Its line break will be CRLF("\r\n"). 604 * @example 605 * hextopem('616161', 'RSA PRIVATE KEY') → 606 * -----BEGIN PRIVATE KEY----- 607 * YWFh 608 * -----END PRIVATE KEY----- 609 */ 610 function hextopem(dataHex, pemHeader) { 611 return "-----BEGIN " + pemHeader + "-----\r\n" + 612 foldnl(hextob64(dataHex), 64) + 613 "\r\n-----END " + pemHeader + "-----\r\n"; 614 } 615 616 /** 617 * get hexacedimal string from PEM format data<br/> 618 * @name pemtohex 619 * @function 620 * @param {String} s PEM formatted string 621 * @param {String} sHead PEM header string without BEGIN/END(OPTION) 622 * @return {String} hexadecimal string data of PEM contents 623 * @since jsrsasign 7.2.1 base64x 1.1.12 624 * 625 * @description 626 * This static method gets a hexacedimal string of contents 627 * from PEM format data. You can explicitly specify PEM header 628 * by sHead argument. 629 * Any space characters such as white space or new line 630 * will be omitted.<br/> 631 * NOTE: Now {@link KEYUTIL.getHexFromPEM} and {@link X509.pemToHex} 632 * have been deprecated since jsrsasign 7.2.1. <br/> 633 * Please use this method instead. 634 * NOTE2: From jsrsasign 8.0.14 this can process multi 635 * "BEGIN...END" section such as "EC PRIVATE KEY" with "EC PARAMETERS".<br/> 636 * 637 * @example 638 * pemtohex("-----BEGIN PUBLIC KEY...") → "3082..." 639 * pemtohex("-----BEGIN CERTIFICATE...", "CERTIFICATE") → "3082..." 640 * pemtohex(" \r\n-----BEGIN DSA PRIVATE KEY...") → "3082..." 641 * pemtohex("-----BEGIN EC PARAMETERS...----BEGIN EC PRIVATE KEY...." → "3082..." 642 */ 643 function pemtohex(s, sHead) { 644 if (s.indexOf("-----BEGIN ") == -1) 645 throw new Error("can't find PEM header"); 646 647 if (sHead !== undefined) { 648 s = s.replace(new RegExp('^[^]*-----BEGIN ' + sHead + '-----'), ''); 649 s = s.replace(new RegExp('-----END ' + sHead + '-----[^]*$'), ''); 650 } else { 651 s = s.replace(/^[^]*-----BEGIN [^-]+-----/, ''); 652 s = s.replace(/-----END [^-]+-----[^]*$/, ''); 653 } 654 return b64nltohex(s); 655 } 656 657 /** 658 * get Base64 string from PEM format data<br/> 659 * @name pemtob64 660 * @function 661 * @param {string} s PEM formatted string 662 * @return {string} Base64 string or null 663 * @since jsrsasign 10.7.0 base64x 1.1.31 664 * 665 * @description 666 * This static method gets a Base64 string of contents 667 * from PEM format data. 668 * When s is not PEM data, it returns null. 669 * 670 * @example 671 * pemtohex("-----BEGIN CERTIFICATE...", "CERTIFICATE") → "MIIBvTCC..." 672 */ 673 function pemtob64(s) { 674 if (s.indexOf("-----BEGIN ") == -1 || 675 s.indexOf("-----END ") == -1 ) return null; 676 s = s.replace(/^[\s\S]*?-----BEGIN [^-]+-----/m, ''); 677 s = s.replace(/-----END [\s\S]+$/m, ''); 678 s = s.replace(/\s+/g, ''); 679 return (s.match(/^[0-9a-zA-Z+/=]+$/)) ? s : null; 680 } 681 682 // ==== hex / ArrayBuffer ================================= 683 684 /** 685 * convert a hexadecimal string to an ArrayBuffer<br/> 686 * @name hextoArrayBuffer 687 * @function 688 * @param {String} hex hexadecimal string 689 * @return {ArrayBuffer} ArrayBuffer 690 * @since jsrsasign 6.1.4 base64x 1.1.8 691 * @description 692 * This function converts from a hexadecimal string to an ArrayBuffer. 693 * @example 694 * hextoArrayBuffer("fffa01") → ArrayBuffer of [255, 250, 1] 695 */ 696 function hextoArrayBuffer(hex) { 697 if (hex.length % 2 != 0) throw "input is not even length"; 698 if (hex.match(/^[0-9A-Fa-f]+$/) == null) throw "input is not hexadecimal"; 699 700 var buffer = new ArrayBuffer(hex.length / 2); 701 var view = new DataView(buffer); 702 703 for (var i = 0; i < hex.length / 2; i++) { 704 view.setUint8(i, parseInt(hex.substr(i * 2, 2), 16)); 705 } 706 707 return buffer; 708 } 709 710 // ==== ArrayBuffer / hex ================================= 711 712 /** 713 * convert an ArrayBuffer to a hexadecimal string<br/> 714 * @name ArrayBuffertohex 715 * @function 716 * @param {ArrayBuffer} buffer ArrayBuffer 717 * @return {String} hexadecimal string 718 * @since jsrsasign 6.1.4 base64x 1.1.8 719 * @description 720 * This function converts from an ArrayBuffer to a hexadecimal string. 721 * @example 722 * var buffer = new ArrayBuffer(3); 723 * var view = new DataView(buffer); 724 * view.setUint8(0, 0xfa); 725 * view.setUint8(1, 0xfb); 726 * view.setUint8(2, 0x01); 727 * ArrayBuffertohex(buffer) → "fafb01" 728 */ 729 function ArrayBuffertohex(buffer) { 730 var hex = ""; 731 var view = new DataView(buffer); 732 733 for (var i = 0; i < buffer.byteLength; i++) { 734 hex += ("00" + view.getUint8(i).toString(16)).slice(-2); 735 } 736 737 return hex; 738 } 739 740 // ==== zulu / int ================================= 741 /** 742 * GeneralizedTime or UTCTime string to milliseconds from Unix origin<br> 743 * @name zulutomsec 744 * @function 745 * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 746 * @return {Number} milliseconds from Unix origin time (i.e. Jan 1, 1970 0:00:00 UTC) 747 * @since jsrsasign 7.1.3 base64x 1.1.9 748 * @description 749 * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or 750 * UTCTime string (i.e. YYMMDDHHmmSSZ) to milliseconds from Unix origin time 751 * (i.e. Jan 1 1970 0:00:00 UTC). 752 * Argument string may have fraction of seconds and 753 * its length is one or more digits such as "20170410235959.1234567Z". 754 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 755 * If year "YY" is equal or greater than 50 then it is 19YY. 756 * @example 757 * zulutomsec( "071231235959Z") → 1199145599000 #Mon, 31 Dec 2007 23:59:59 GMT 758 * zulutomsec( "071231235959.1Z") → 1199145599100 #Mon, 31 Dec 2007 23:59:59 GMT 759 * zulutomsec( "071231235959.12345Z") → 1199145599123 #Mon, 31 Dec 2007 23:59:59 GMT 760 * zulutomsec("20071231235959Z") → 1199145599000 #Mon, 31 Dec 2007 23:59:59 GMT 761 * zulutomsec( "931231235959Z") → -410227201000 #Mon, 31 Dec 1956 23:59:59 GMT 762 */ 763 function zulutomsec(s) { 764 var year, month, day, hour, min, sec, msec, d; 765 var sYear, sFrac, sMsec, matchResult; 766 767 s = timetogen(s); 768 matchResult = s.match(/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(|\.\d+)Z$/); 769 770 if (matchResult) { 771 year = parseInt(matchResult[1]); 772 month = parseInt(matchResult[2]) - 1; 773 day = parseInt(matchResult[3]); 774 hour = parseInt(matchResult[4]); 775 min = parseInt(matchResult[5]); 776 sec = parseInt(matchResult[6]); 777 msec = 0; 778 779 sFrac = matchResult[7]; 780 if (sFrac !== "") { 781 sMsec = (sFrac.substr(1) + "00").substr(0, 3); // .12 -> 012 782 msec = parseInt(sMsec); 783 } 784 return Date.UTC(year, month, day, hour, min, sec, msec); 785 } 786 throw new Error("unsupported zulu format: " + s); 787 } 788 789 /** 790 * GeneralizedTime or UTCTime string to seconds from Unix origin<br> 791 * @name zulutosec 792 * @function 793 * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 794 * @return {Number} seconds from Unix origin time (i.e. Jan 1, 1970 0:00:00 UTC) 795 * @since jsrsasign 7.1.3 base64x 1.1.9 796 * @description 797 * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or 798 * UTCTime string (i.e. YYMMDDHHmmSSZ) to seconds from Unix origin time 799 * (i.e. Jan 1 1970 0:00:00 UTC). Argument string may have fraction of seconds 800 * however result value will be omitted. 801 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 802 * If year "YY" is equal or greater than 50 then it is 19YY. 803 * @example 804 * zulutosec( "071231235959Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT 805 * zulutosec( "071231235959.1Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT 806 * zulutosec("20071231235959Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT 807 */ 808 function zulutosec(s) { 809 return Math.round(zulutomsec(s) / 1000.0); 810 } 811 812 // ==== zulu / Date ================================= 813 814 /** 815 * GeneralizedTime or UTCTime string to Date object<br> 816 * @name zulutodate 817 * @function 818 * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 819 * @return {Date} Date object for specified time 820 * @since jsrsasign 7.1.3 base64x 1.1.9 821 * @description 822 * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or 823 * UTCTime string (i.e. YYMMDDHHmmSSZ) to Date object. 824 * Argument string may have fraction of seconds and 825 * its length is one or more digits such as "20170410235959.1234567Z". 826 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 827 * If year "YY" is equal or greater than 50 then it is 19YY. 828 * @example 829 * zulutodate( "071231235959Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT" 830 * zulutodate( "071231235959.1Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT" 831 * zulutodate("20071231235959Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT" 832 * zulutodate( "071231235959.34").getMilliseconds() → 340 833 */ 834 function zulutodate(s) { 835 return new Date(zulutomsec(s)); 836 } 837 838 /** 839 * Date object to zulu time string<br> 840 * @name datetozulu 841 * @function 842 * @param {Date} d Date object for specified time 843 * @param {Boolean} flagUTCTime if this is true year will be YY otherwise YYYY 844 * @param {Boolean} flagMilli if this is true result concludes milliseconds 845 * @return {String} GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 846 * @since jsrsasign 7.2.0 base64x 1.1.11 847 * @description 848 * This function converts from Date object to GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or 849 * UTCTime string (i.e. YYMMDDHHmmSSZ). 850 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 851 * If year "YY" is equal or greater than 50 then it is 19YY. 852 * If flagMilli is true its result concludes milliseconds such like 853 * "20170520235959.42Z". 854 * @example 855 * d = new Date(Date.UTC(2017,4,20,23,59,59,670)); 856 * datetozulu(d) → "20170520235959Z" 857 * datetozulu(d, true) → "170520235959Z" 858 * datetozulu(d, false, true) → "20170520235959.67Z" 859 */ 860 function datetozulu(d, flagUTCTime, flagMilli) { 861 var s; 862 var year = d.getUTCFullYear(); 863 if (flagUTCTime) { 864 if (year < 1950 || 2049 < year) 865 throw "not proper year for UTCTime: " + year; 866 s = ("" + year).slice(-2); 867 } else { 868 s = ("000" + year).slice(-4); 869 } 870 s += ("0" + (d.getUTCMonth() + 1)).slice(-2); 871 s += ("0" + d.getUTCDate()).slice(-2); 872 s += ("0" + d.getUTCHours()).slice(-2); 873 s += ("0" + d.getUTCMinutes()).slice(-2); 874 s += ("0" + d.getUTCSeconds()).slice(-2); 875 if (flagMilli) { 876 var milli = d.getUTCMilliseconds(); 877 if (milli !== 0) { 878 milli = ("00" + milli).slice(-3); 879 milli = milli.replace(/0+$/g, ""); 880 s += "." + milli; 881 } 882 } 883 s += "Z"; 884 return s; 885 } 886 887 /** 888 * GeneralizedTime or UTCTime string to GeneralizedTime<br> 889 * @name timetogen 890 * @function 891 * @param {string} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 892 * @return {string} GeneralizedTime 893 * @since jsrsasign 10.7.0 base64x 1.1.31 894 * @description 895 * This function converts UTCTime string (i.e. YYMMDDHHmmSSZ ) to 896 * GeneralizedTime (YYYYMMDDHHmmSSZ) when the argument 's' is UTCTime. 897 * Argument string may have fraction of seconds and 898 * its length is one or more digits such as "170410235959.1234567Z". 899 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 900 * If year "YY" is equal or greater than 50 then it is 19YY. 901 * @example 902 * timetogen( "071231235959Z") → "20071231235959Z" 903 * timetogen( "971231235959Z") → "19971231235959Z" 904 * timetogen("20071231235959Z") → "20071231235959Z" 905 * timetogen( "971231235959.123Z") → "19971231235959.123Z" 906 */ 907 function timetogen(s) { 908 if (s.match(/^[0-9]{12}Z$/) || s.match(/^[0-9]{12}[.][0-9]*Z$/)) { 909 return (s.match(/^[0-4]/)) ? "20" + s : "19" + s; 910 } 911 return s; 912 } 913 914 // ==== URIComponent / hex ================================ 915 /** 916 * convert a URLComponent string such like "%67%68" to a hexadecimal string.<br/> 917 * @name uricmptohex 918 * @function 919 * @param {String} s URIComponent string such like "%67%68" 920 * @return {String} hexadecimal string 921 * @since 1.1 922 */ 923 function uricmptohex(s) { 924 return s.replace(/%/g, ""); 925 } 926 927 /** 928 * convert a hexadecimal string to a URLComponent string such like "%67%68".<br/> 929 * @name hextouricmp 930 * @function 931 * @param {String} s hexadecimal string 932 * @return {String} URIComponent string such like "%67%68" 933 * @since 1.1 934 */ 935 function hextouricmp(s) { 936 return s.replace(/(..)/g, "%$1"); 937 } 938 939 // ==== hex / ipv6 ================================= 940 941 /** 942 * convert any IPv6 address to a 16 byte hexadecimal string 943 * @function 944 * @param s string of IPv6 address 945 * @return {String} 16 byte hexadecimal string of IPv6 address 946 * @description 947 * This function converts any IPv6 address representation string 948 * to a 16 byte hexadecimal string of address. 949 * @example 950 * 951 */ 952 function ipv6tohex(s) { 953 var msgMalformedAddress = "malformed IPv6 address"; 954 if (! s.match(/^[0-9A-Fa-f:]+$/)) 955 throw msgMalformedAddress; 956 957 // 1. downcase 958 s = s.toLowerCase(); 959 960 // 2. expand :: 961 var num_colon = s.split(':').length - 1; 962 if (num_colon < 2) throw msgMalformedAddress; 963 var colon_replacer = ':'.repeat(7 - num_colon + 2); 964 s = s.replace('::', colon_replacer); 965 966 // 3. fill zero 967 var a = s.split(':'); 968 if (a.length != 8) throw msgMalformedAddress; 969 for (var i = 0; i < 8; i++) { 970 a[i] = ("0000" + a[i]).slice(-4); 971 } 972 return a.join(''); 973 } 974 975 /** 976 * convert a 16 byte hexadecimal string to RFC 5952 canonicalized IPv6 address<br/> 977 * @name hextoipv6 978 * @function 979 * @param {String} s hexadecimal string of 16 byte IPv6 address 980 * @return {String} IPv6 address string canonicalized by RFC 5952 981 * @since jsrsasign 8.0.10 base64x 1.1.13 982 * @description 983 * This function converts a 16 byte hexadecimal string to 984 * <a href="https://tools.ietf.org/html/rfc5952">RFC 5952</a> 985 * canonicalized IPv6 address string. 986 * @example 987 * hextoipv6("871020010db8000000000000000000000004") &rarr "2001:db8::4" 988 * hextoipv6("871020010db8000000000000000000") &rarr raise exception 989 * hextoipv6("xyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyz") &rarr raise exception 990 */ 991 function hextoipv6(s) { 992 if (! s.match(/^[0-9A-Fa-f]{32}$/)) 993 throw new Error("malformed IPv6 address: " + s); 994 995 // 1. downcase 996 s = s.toLowerCase(); 997 998 // 2. split 4 > ["0123", "00a4", "0000", ..., "ffff"] 999 var a = s.match(/.{1,4}/g); 1000 1001 // 3. trim leading 0 for items and join > "123:a4:0:...:ffff" 1002 a = a.map(function(s){return s.replace(/^0+/, '')}); 1003 a = a.map(function(s){return s == '' ? '0' : s}); 1004 s = ':' + a.join(':') + ':'; 1005 1006 // 4. find shrinkable candidates :0:0:..:0: 1007 var aZero = s.match(/:(0:){2,}/g); 1008 1009 // 5. no shrinkable 1010 if (aZero == null) return s.slice(1, -1); 1011 1012 // 6. fix max length zero(:0:...:0:) 1013 var sMaxZero = aZero.sort().slice(-1)[0]; 1014 1015 // 7. replace shrinked 1016 s = s.replace(sMaxZero.substr(0, sMaxZero.length - 1), ':'); 1017 1018 // 8. trim leading ':' if not '::' 1019 if (s.substr(0, 2) != '::') s = s.substr(1); 1020 1021 // 9. trim tail ':' if not '::' 1022 if (s.substr(-2, 2) != '::') s = s.substr(0, s.length - 1); 1023 1024 return s; 1025 } 1026 1027 // ==== hex / ip ================================= 1028 1029 /** 1030 * convert a hexadecimal string to IP addresss<br/> 1031 * @name hextoip 1032 * @function 1033 * @param {String} s hexadecimal string of IP address 1034 * @return {String} IP address string 1035 * @since jsrsasign 8.0.10 base64x 1.1.13 1036 * @see hextoipv6 1037 * @see iptohex 1038 * 1039 * @description 1040 * This function converts a hexadecimal string of IPv4 or 1041 * IPv6 address to IPv4 or IPv6 address string. 1042 * If byte length is not 4 nor 16, this returns a 1043 * hexadecimal string without conversion. 1044 * <br/> 1045 * NOTE: From jsrsasign 10.5.17, CIDR subnet mask notation also supported. 1046 * 1047 * @example 1048 * hextoip("c0a80101") → "192.168.1.1" 1049 * hextoip("871020010db8000000000000000000000004") &rarr "2001:db8::4" 1050 * hextoip("c0a80100ffffff00") → "192.168.1.0/24" 1051 * hextoip("c0a801010203") → "c0a801010203" // wrong 6 bytes 1052 * hextoip("zzz")) → raise exception because of not hexadecimal 1053 */ 1054 function hextoip(s) { 1055 var malformedErr = new Error("malformed hex value"); 1056 if (! s.match(/^([0-9A-Fa-f][0-9A-Fa-f]){1,}$/)) 1057 throw malformedErr; 1058 if (s.length == 8) { // ipv4 1059 var ip; 1060 try { 1061 ip = parseInt(s.substr(0, 2), 16) + "." + 1062 parseInt(s.substr(2, 2), 16) + "." + 1063 parseInt(s.substr(4, 2), 16) + "." + 1064 parseInt(s.substr(6, 2), 16); 1065 return ip; 1066 } catch (ex) { 1067 throw malformedErr; 1068 } 1069 } else if (s.length == 16) { 1070 try { 1071 return hextoip(s.substr(0, 8)) + "/" + ipprefixlen(s.substr(8)); 1072 } catch (ex) { 1073 throw malformedErr; 1074 } 1075 } else if (s.length == 32) { 1076 return hextoipv6(s); 1077 } else if (s.length == 64) { 1078 try { 1079 return hextoipv6(s.substr(0, 32)) + "/" + ipprefixlen(s.substr(32)); 1080 } catch (ex) { 1081 throw malformedErr; 1082 } 1083 return 1084 } else { 1085 return s; 1086 } 1087 } 1088 1089 /* 1090 * convert subnet mask hex to ip address prefix length<br/> 1091 * @name ipprefixlen 1092 * @param {string} hMask hexadecimal string of ipv4/6 subnet mask (ex. "ffffff00" for v4 class C) 1093 * @return {nummber} ip address prefix length (ex. 24 for IPv4 class C) 1094 */ 1095 function ipprefixlen(hMask) { 1096 var malformedErr = new Error("malformed mask"); 1097 var bMask; 1098 try { 1099 bMask = new BigInteger(hMask, 16).toString(2); 1100 } catch(ex) { 1101 throw malformedErr; 1102 } 1103 if (! bMask.match(/^1*0*$/)) throw malformedErr; 1104 return bMask.replace(/0+$/, '').length; 1105 } 1106 1107 /** 1108 * convert IPv4/v6 addresss to a hexadecimal string<br/> 1109 * @name iptohex 1110 * @function 1111 * @param {String} s IPv4/v6 address string 1112 * @return {String} hexadecimal string of IP address 1113 * @since jsrsasign 8.0.12 base64x 1.1.14 1114 * @see hextoip 1115 * @see ipv6tohex 1116 * 1117 * @description 1118 * This function converts IPv4 or IPv6 address string to 1119 * a hexadecimal string of IPv4 or IPv6 address. 1120 * <br/> 1121 * NOTE: From jsrsasign 10.5.17, CIDR net mask notation also supported. 1122 * 1123 * @example 1124 * iptohex("192.168.1.1") → "c0a80101" 1125 * iptohex("2001:db8::4") → "871020010db8000000000000000000000004" 1126 * iptohex("192.168.1.1/24") → "c0a80101ffffff00" 1127 * iptohex("2001:db8::/120") → "871020010db8000000000000000000000000ffffffffffffffffffffffffffffffffff00" 1128 * iptohex("zzz")) → raise exception 1129 */ 1130 function iptohex(s) { 1131 var malformedErr = new Error("malformed IP address"); 1132 s = s.toLowerCase(s); 1133 1134 if (! s.match(/^[0-9a-f.:/]+$/) ) throw malformedErr; 1135 1136 if (s.match(/^[0-9.]+$/)) { 1137 var a = s.split("."); 1138 if (a.length !== 4) throw malformedErr; 1139 var hex = ""; 1140 try { 1141 for (var i = 0; i < 4; i++) { 1142 var d = parseInt(a[i]); 1143 hex += ("0" + d.toString(16)).slice(-2); 1144 } 1145 return hex; 1146 } catch(ex) { 1147 throw malformedErr; 1148 } 1149 } else if (s.match(/^[0-9.]+\/[0-9]+$/)) { 1150 var aItem = s.split("/"); 1151 return iptohex(aItem[0]) + ipnetmask(parseInt(aItem[1]), 32); 1152 } else if (s.match(/^[0-9a-f:]+$/) && s.indexOf(":") !== -1) { 1153 return ipv6tohex(s); 1154 } else if (s.match(/^[0-9a-f:]+\/[0-9]+$/) && s.indexOf(":") !== -1) { 1155 var aItem = s.split("/"); 1156 return ipv6tohex(aItem[0]) + ipnetmask(parseInt(aItem[1]), 128); 1157 } else { 1158 throw malformedErr; 1159 } 1160 } 1161 1162 /* 1163 * convert ip prefix length to net mask octets<br/> 1164 * @param {number} prefixlen ip prefix length value (ex. 24 for IPv4 class C) 1165 * @param {number} len ip address length (ex. 32 for IPv4 and 128 for IPv6) 1166 * @return {string} hexadecimal string of net mask octets 1167 * @example 1168 * ipnetmask(24, 32) → "ffffff00" 1169 * ipnetmask(120, 128) → "ffffffffffffffffffffffffffffff00" 1170 */ 1171 function ipnetmask(prefixlen, len) { 1172 if (len == 32 && prefixlen == 0) return "00000000"; // v4 1173 if (len == 128 && prefixlen == 0) return "00000000000000000000000000000000"; // v6 1174 var b = Array(prefixlen + 1).join("1") + Array(len - prefixlen + 1).join("0"); 1175 return new BigInteger(b, 2).toString(16); 1176 } 1177 1178 // ==== ucs2hex / utf8 ============================== 1179 1180 /** 1181 * convert UCS-2 hexadecimal stirng to UTF-8 string<br/> 1182 * @name ucs2hextoutf8 1183 * @function 1184 * @param {String} s hexadecimal string of UCS-2 string (ex. "0066") 1185 * @return {String} UTF-8 string 1186 * @since jsrsasign 10.1.13 base64x 1.1.20 1187 * @description 1188 * This function converts hexadecimal value of UCS-2 string to 1189 * UTF-8 string. 1190 * @example 1191 * ucs2hextoutf8("006600fc0072") &rarr "für" 1192 */ 1193 /* 1194 See: http://nomenclator.la.coocan.jp/unicode/ucs_utf.htm 1195 UCS-2 to UTF-8 1196 UCS-2 code point | UCS-2 bytes | UTF-8 bytes 1197 U+0000 .. U+007F | 00000000-0xxxxxxx | 0xxxxxxx (1 byte) 1198 U+0080 .. U+07FF | 00000xxx-xxyyyyyy | 110xxxxx 10yyyyyy (2 byte) 1199 U+0800 .. U+FFFF | xxxxyyyy-yyzzzzzz | 1110xxxx 10yyyyyy 10zzzzzz (3 byte) 1200 */ 1201 function ucs2hextoutf8(s) { 1202 function _conv(s) { 1203 var i1 = parseInt(s.substr(0, 2), 16); 1204 var i2 = parseInt(s.substr(2), 16); 1205 if (i1 == 0 & i2 < 0x80) { // 1 byte 1206 return String.fromCharCode(i2); 1207 } 1208 if (i1 < 8) { // 2 bytes 1209 var u1 = 0xc0 | ((i1 & 0x07) << 3) | ((i2 & 0xc0) >> 6); 1210 var u2 = 0x80 | (i2 & 0x3f); 1211 return hextoutf8(u1.toString(16) + u2.toString(16)); 1212 } 1213 // 3 bytes 1214 var u1 = 0xe0 | ((i1 & 0xf0) >> 4); 1215 var u2 = 0x80 | ((i1 & 0x0f) << 2) | ((i2 & 0xc0) >> 6); 1216 var u3 = 0x80 | (i2 & 0x3f); 1217 return hextoutf8(u1.toString(16) + u2.toString(16) + u3.toString(16)); 1218 } 1219 var a = s.match(/.{4}/g); 1220 var a2 = a.map(_conv); 1221 return a2.join(""); 1222 } 1223 1224 // ==== URIComponent ================================ 1225 /** 1226 * convert UTFa hexadecimal string to a URLComponent string such like "%67%68".<br/> 1227 * Note that these "<code>0-9A-Za-z!'()*-._~</code>" characters will not 1228 * converted to "%xx" format by builtin 'encodeURIComponent()' function. 1229 * However this 'encodeURIComponentAll()' function will convert 1230 * all of characters into "%xx" format. 1231 * @name encodeURIComponentAll 1232 * @function 1233 * @param {String} s hexadecimal string 1234 * @return {String} URIComponent string such like "%67%68" 1235 * @since 1.1 1236 */ 1237 function encodeURIComponentAll(u8) { 1238 var s = encodeURIComponent(u8); 1239 var s2 = ""; 1240 for (var i = 0; i < s.length; i++) { 1241 if (s[i] == "%") { 1242 s2 = s2 + s.substr(i, 3); 1243 i = i + 2; 1244 } else { 1245 s2 = s2 + "%" + stohex(s[i]); 1246 } 1247 } 1248 return s2; 1249 } 1250 1251 // ==== new lines ================================ 1252 /** 1253 * convert all DOS new line("\r\n") to UNIX new line("\n") in 1254 * a String "s". 1255 * @name newline_toUnix 1256 * @function 1257 * @param {String} s string 1258 * @return {String} converted string 1259 */ 1260 function newline_toUnix(s) { 1261 s = s.replace(/\r\n/mg, "\n"); 1262 return s; 1263 } 1264 1265 /** 1266 * convert all UNIX new line("\r\n") to DOS new line("\n") in 1267 * a String "s". 1268 * @name newline_toDos 1269 * @function 1270 * @param {String} s string 1271 * @return {String} converted string 1272 */ 1273 function newline_toDos(s) { 1274 s = s.replace(/\r\n/mg, "\n"); 1275 s = s.replace(/\n/mg, "\r\n"); 1276 return s; 1277 } 1278 1279 // ==== string type checker =================== 1280 1281 /** 1282 * check whether a string is an integer string or not<br/> 1283 * @name isInteger 1284 * @memberOf KJUR.lang.String 1285 * @function 1286 * @static 1287 * @param {String} s input string 1288 * @return {Boolean} true if a string "s" is an integer string otherwise false 1289 * @since base64x 1.1.7 jsrsasign 5.0.13 1290 * @example 1291 * KJUR.lang.String.isInteger("12345") → true 1292 * KJUR.lang.String.isInteger("123ab") → false 1293 */ 1294 KJUR.lang.String.isInteger = function(s) { 1295 if (s.match(/^[0-9]+$/)) { 1296 return true; 1297 } else if (s.match(/^-[0-9]+$/)) { 1298 return true; 1299 } else { 1300 return false; 1301 } 1302 }; 1303 1304 /** 1305 * check whether a string is an hexadecimal string or not (DEPRECATED)<br/> 1306 * @name isHex 1307 * @memberOf KJUR.lang.String 1308 * @function 1309 * @static 1310 * @param {String} s input string 1311 * @return {Boolean} true if a string "s" is an hexadecimal string otherwise false 1312 * @since base64x 1.1.7 jsrsasign 5.0.13 1313 * @deprecated from 10.0.6. please use {@link ishex} 1314 * @see ishex 1315 * @example 1316 * KJUR.lang.String.isHex("1234") → true 1317 * KJUR.lang.String.isHex("12ab") → true 1318 * KJUR.lang.String.isHex("12AB") → true 1319 * KJUR.lang.String.isHex("12ZY") → false 1320 * KJUR.lang.String.isHex("121") → false -- odd length 1321 */ 1322 KJUR.lang.String.isHex = function(s) { 1323 return ishex(s); 1324 }; 1325 1326 /** 1327 * check whether a string is an hexadecimal string or not<br/> 1328 * @name ishex 1329 * @function 1330 * @static 1331 * @param {String} s input string 1332 * @return {Boolean} true if a string "s" is an hexadecimal string otherwise false 1333 * @since base64x 1.1.7 jsrsasign 5.0.13 1334 * @example 1335 * ishex("1234") → true 1336 * ishex("12ab") → true 1337 * ishex("12AB") → true 1338 * ishex("12ZY") → false 1339 * ishex("121") → false -- odd length 1340 */ 1341 function ishex(s) { 1342 if (s.length % 2 == 0 && 1343 (s.match(/^[0-9a-f]+$/) || s.match(/^[0-9A-F]+$/))) { 1344 return true; 1345 } else { 1346 return false; 1347 } 1348 }; 1349 1350 /** 1351 * check whether a string is a base64 encoded string or not<br/> 1352 * Input string can conclude new lines or space characters. 1353 * @name isBase64 1354 * @memberOf KJUR.lang.String 1355 * @function 1356 * @static 1357 * @param {String} s input string 1358 * @return {Boolean} true if a string "s" is a base64 encoded string otherwise false 1359 * @since base64x 1.1.7 jsrsasign 5.0.13 1360 * @example 1361 * KJUR.lang.String.isBase64("YWE=") → true 1362 * KJUR.lang.String.isBase64("YW_=") → false 1363 * KJUR.lang.String.isBase64("YWE") → false -- length shall be multiples of 4 1364 */ 1365 KJUR.lang.String.isBase64 = function(s) { 1366 s = s.replace(/\s+/g, ""); 1367 if (s.match(/^[0-9A-Za-z+\/]+={0,3}$/) && s.length % 4 == 0) { 1368 return true; 1369 } else { 1370 return false; 1371 } 1372 }; 1373 1374 /** 1375 * check whether a string is a base64url encoded string or not<br/> 1376 * Input string can conclude new lines or space characters. 1377 * @name isBase64URL 1378 * @memberOf KJUR.lang.String 1379 * @function 1380 * @static 1381 * @param {String} s input string 1382 * @return {Boolean} true if a string "s" is a base64url encoded string otherwise false 1383 * @since base64x 1.1.7 jsrsasign 5.0.13 1384 * @example 1385 * KJUR.lang.String.isBase64URL("YWE") → true 1386 * KJUR.lang.String.isBase64URL("YW-") → true 1387 * KJUR.lang.String.isBase64URL("YW+") → false 1388 */ 1389 KJUR.lang.String.isBase64URL = function(s) { 1390 if (s.match(/[+/=]/)) return false; 1391 s = b64utob64(s); 1392 return KJUR.lang.String.isBase64(s); 1393 }; 1394 1395 1396 /** 1397 * check whether a string is a base64url encoded string and dot or not<br/> 1398 * Input string can conclude new lines or space characters. 1399 * @name isBase64URLDot 1400 * @function 1401 * @static 1402 * @param {String} s input string 1403 * @return {Boolean} true if a string "s" is a base64url encoded string and dot otherwise false 1404 * @since base64x 1.1.30 jsrsasign 10.5.25 1405 * @example 1406 * isBase64URLDot("YWE") → true 1407 * isBase64URLDot("YWE.YWE.YWE") → true 1408 * isBase64URLDot("YW-") → true 1409 * isBase64URLDot("YW+") → false 1410 */ 1411 function isBase64URLDot(s) { 1412 if (s.match(/^[0-9A-Za-z-_.]+$/)) return true; 1413 return false; 1414 } 1415 1416 /** 1417 * check whether a string is a string of integer array or not<br/> 1418 * Input string can conclude new lines or space characters. 1419 * @name isIntegerArray 1420 * @memberOf KJUR.lang.String 1421 * @function 1422 * @static 1423 * @param {String} s input string 1424 * @return {Boolean} true if a string "s" is a string of integer array otherwise false 1425 * @since base64x 1.1.7 jsrsasign 5.0.13 1426 * @example 1427 * KJUR.lang.String.isIntegerArray("[1,2,3]") → true 1428 * KJUR.lang.String.isIntegerArray(" [1, 2, 3 ] ") → true 1429 * KJUR.lang.String.isIntegerArray("[a,2]") → false 1430 */ 1431 KJUR.lang.String.isIntegerArray = function(s) { 1432 s = s.replace(/\s+/g, ""); 1433 if (s.match(/^\[[0-9,]+\]$/)) { 1434 return true; 1435 } else { 1436 return false; 1437 } 1438 }; 1439 1440 /** 1441 * check whether a string consists of PrintableString characters<br/> 1442 * @name isPrintable 1443 * @memberOf KJUR.lang.String 1444 * @function 1445 * @static 1446 * @param {String} s input string 1447 * @return {Boolean} true if a string "s" consists of PrintableString characters 1448 * @since jsrsasign 9.0.0 base64x 1.1.16 1449 * A PrintableString consists of following characters 1450 * <pre> 1451 * 0-9A-Za-z '()+,-./:=? 1452 * </pre> 1453 * This method returns false when other characters than above. 1454 * Otherwise it returns true. 1455 * @example 1456 * KJUR.lang.String.isPrintable("abc") → true 1457 * KJUR.lang.String.isPrintable("abc@") → false 1458 * KJUR.lang.String.isPrintable("あいう") → false 1459 */ 1460 KJUR.lang.String.isPrintable = function(s) { 1461 if (s.match(/^[0-9A-Za-z '()+,-./:=?]*$/) !== null) return true; 1462 return false; 1463 }; 1464 1465 /** 1466 * check whether a string consists of IAString characters<br/> 1467 * @name isIA5 1468 * @memberOf KJUR.lang.String 1469 * @function 1470 * @static 1471 * @param {String} s input string 1472 * @return {Boolean} true if a string "s" consists of IA5String characters 1473 * @since jsrsasign 9.0.0 base64x 1.1.16 1474 * A IA5String consists of following characters 1475 * <pre> 1476 * %x00-21/%x23-7F (i.e. ASCII characters excludes double quote(%x22) 1477 * </pre> 1478 * This method returns false when other characters than above. 1479 * Otherwise it returns true. 1480 * @example 1481 * KJUR.lang.String.isIA5("abc") → true 1482 * KJUR.lang.String.isIA5('"abc"') → false 1483 * KJUR.lang.String.isIA5("あいう") → false 1484 */ 1485 KJUR.lang.String.isIA5 = function(s) { 1486 if (s.match(/^[\x20-\x21\x23-\x7f]*$/) !== null) return true; 1487 return false; 1488 }; 1489 1490 /** 1491 * check whether a string is RFC 822 mail address<br/> 1492 * @name isMail 1493 * @memberOf KJUR.lang.String 1494 * @function 1495 * @static 1496 * @param {String} s input string 1497 * @return {Boolean} true if a string "s" RFC 822 mail address 1498 * @since jsrsasign 9.0.0 base64x 1.1.16 1499 * This static method will check string s is RFC 822 compliant mail address. 1500 * @example 1501 * KJUR.lang.String.isMail("abc") → false 1502 * KJUR.lang.String.isMail("abc@example") → false 1503 * KJUR.lang.String.isMail("abc@example.com") → true 1504 */ 1505 KJUR.lang.String.isMail = function(s) { 1506 if (s.match(/^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]{1,}\.[A-Za-z0-9]{1,}$/) !== null) return true; 1507 return false; 1508 }; 1509 1510 // ==== others ================================ 1511 1512 /** 1513 * canonicalize hexadecimal string of positive integer<br/> 1514 * @name hextoposhex 1515 * @function 1516 * @param {String} s hexadecimal string 1517 * @return {String} canonicalized hexadecimal string of positive integer 1518 * @since base64x 1.1.10 jsrsasign 7.1.4 1519 * @description 1520 * This method canonicalize a hexadecimal string of positive integer 1521 * for two's complement representation. 1522 * Canonicalized hexadecimal string of positive integer will be: 1523 * <ul> 1524 * <li>Its length is always even.</li> 1525 * <li>If odd length it will be padded with leading zero.<li> 1526 * <li>If it is even length and its first character is "8" or greater, 1527 * it will be padded with "00" to make it positive integer.</li> 1528 * </ul> 1529 * @example 1530 * hextoposhex("abcd") → "00abcd" 1531 * hextoposhex("1234") → "1234" 1532 * hextoposhex("12345") → "012345" 1533 */ 1534 function hextoposhex(s) { 1535 if (s.length % 2 == 1) return "0" + s; 1536 if (s.substr(0, 1) > "7") return "00" + s; 1537 return s; 1538 } 1539 1540 /** 1541 * convert string of integer array to hexadecimal string.<br/> 1542 * @name intarystrtohex 1543 * @function 1544 * @param {String} s string of integer array 1545 * @return {String} hexadecimal string 1546 * @since base64x 1.1.6 jsrsasign 5.0.2 1547 * @throws "malformed integer array string: *" for wrong input 1548 * @description 1549 * This function converts a string of JavaScript integer array to 1550 * a hexadecimal string. Each integer value shall be in a range 1551 * from 0 to 255 otherwise it raise exception. Input string can 1552 * have extra space or newline string so that they will be ignored. 1553 * 1554 * @example 1555 * intarystrtohex(" [123, 34, 101, 34, 58] ") 1556 * → 7b2265223a (i.e. '{"e":' as string) 1557 */ 1558 function intarystrtohex(s) { 1559 s = s.replace(/^\s*\[\s*/, ''); 1560 s = s.replace(/\s*\]\s*$/, ''); 1561 s = s.replace(/\s*/g, ''); 1562 try { 1563 var hex = s.split(/,/).map(function(element, index, array) { 1564 var i = parseInt(element); 1565 if (i < 0 || 255 < i) throw "integer not in range 0-255"; 1566 var hI = ("00" + i.toString(16)).slice(-2); 1567 return hI; 1568 }).join(''); 1569 return hex; 1570 } catch(ex) { 1571 throw "malformed integer array string: " + ex; 1572 } 1573 } 1574 1575 /** 1576 * find index of string where two string differs 1577 * @name strdiffidx 1578 * @function 1579 * @param {String} s1 string to compare 1580 * @param {String} s2 string to compare 1581 * @return {Number} string index of where character differs. Return -1 if same. 1582 * @since jsrsasign 4.9.0 base64x 1.1.5 1583 * @example 1584 * strdiffidx("abcdefg", "abcd4fg") -> 4 1585 * strdiffidx("abcdefg", "abcdefg") -> -1 1586 * strdiffidx("abcdefg", "abcdef") -> 6 1587 * strdiffidx("abcdefgh", "abcdef") -> 6 1588 */ 1589 var strdiffidx = function(s1, s2) { 1590 var n = s1.length; 1591 if (s1.length > s2.length) n = s2.length; 1592 for (var i = 0; i < n; i++) { 1593 if (s1.charCodeAt(i) != s2.charCodeAt(i)) return i; 1594 } 1595 if (s1.length != s2.length) return n; 1596 return -1; // same 1597 }; 1598 1599 // ==== hex / oid ================================= 1600 1601 /** 1602 * get hexadecimal value of object identifier from dot noted oid value 1603 * @name oidtohex 1604 * @function 1605 * @param {String} oidString dot noted string of object identifier 1606 * @return {String} hexadecimal value of object identifier 1607 * @since jsrsasign 10.1.0 base64x 1.1.18 1608 * @see hextooid 1609 * @see ASN1HEX.hextooidstr 1610 * @see KJUR.asn1.ASN1Util.oidIntToHex 1611 * @description 1612 * This static method converts from object identifier value string. 1613 * to hexadecimal string representation of it. 1614 * {@link hextooid} is a reverse function of this. 1615 * @example 1616 * oidtohex("2.5.4.6") → "550406" 1617 */ 1618 function oidtohex(oidString) { 1619 var itox = function(i) { 1620 var h = i.toString(16); 1621 if (h.length == 1) h = '0' + h; 1622 return h; 1623 }; 1624 1625 var roidtox = function(roid) { 1626 var h = ''; 1627 var bi = parseInt(roid, 10); 1628 var b = bi.toString(2); 1629 1630 var padLen = 7 - b.length % 7; 1631 if (padLen == 7) padLen = 0; 1632 var bPad = ''; 1633 for (var i = 0; i < padLen; i++) bPad += '0'; 1634 b = bPad + b; 1635 for (var i = 0; i < b.length - 1; i += 7) { 1636 var b8 = b.substr(i, 7); 1637 if (i != b.length - 7) b8 = '1' + b8; 1638 h += itox(parseInt(b8, 2)); 1639 } 1640 return h; 1641 }; 1642 1643 try { 1644 if (! oidString.match(/^[0-9.]+$/)) return null; 1645 1646 var h = ''; 1647 var a = oidString.split('.'); 1648 var i0 = parseInt(a[0], 10) * 40 + parseInt(a[1], 10); 1649 h += itox(i0); 1650 a.splice(0, 2); 1651 for (var i = 0; i < a.length; i++) { 1652 h += roidtox(a[i]); 1653 } 1654 return h; 1655 } catch(ex) { 1656 return null; 1657 } 1658 }; 1659 1660 /** 1661 * get oid string from hexadecimal value of object identifier<br/> 1662 * @name hextooid 1663 * @function 1664 * @param {String} h hexadecimal value of object identifier 1665 * @return {String} dot noted string of object identifier (ex. "1.2.3.4") 1666 * @since jsrsasign 10.1.0 base64x 1.1.18 1667 * @see oidtohex 1668 * @see ASN1HEX.hextooidstr 1669 * @see KJUR.asn1.ASN1Util.oidIntToHex 1670 * @description 1671 * This static method converts from hexadecimal object identifier value 1672 * to dot noted OID value (ex. "1.2.3.4"). 1673 * {@link oidtohex} is a reverse function of this. 1674 * @example 1675 * hextooid("550406") → "2.5.4.6" 1676 */ 1677 function hextooid(h) { 1678 if (! ishex(h)) return null; 1679 try { 1680 var a = []; 1681 1682 // a[0], a[1] 1683 var hex0 = h.substr(0, 2); 1684 var i0 = parseInt(hex0, 16); 1685 a[0] = new String(Math.floor(i0 / 40)); 1686 a[1] = new String(i0 % 40); 1687 1688 // a[2]..a[n] 1689 var hex1 = h.substr(2); 1690 var b = []; 1691 for (var i = 0; i < hex1.length / 2; i++) { 1692 b.push(parseInt(hex1.substr(i * 2, 2), 16)); 1693 } 1694 var c = []; 1695 var cbin = ""; 1696 for (var i = 0; i < b.length; i++) { 1697 if (b[i] & 0x80) { 1698 cbin = cbin + strpad((b[i] & 0x7f).toString(2), 7); 1699 } else { 1700 cbin = cbin + strpad((b[i] & 0x7f).toString(2), 7); 1701 c.push(new String(parseInt(cbin, 2))); 1702 cbin = ""; 1703 } 1704 } 1705 1706 var s = a.join("."); 1707 if (c.length > 0) s = s + "." + c.join("."); 1708 return s; 1709 } catch(ex) { 1710 return null; 1711 } 1712 }; 1713 1714 /** 1715 * string padding<br/> 1716 * @name strpad 1717 * @function 1718 * @param {String} s input string 1719 * @param {Number} len output string length 1720 * @param {String} padchar padding character (default is "0") 1721 * @return {String} padded string 1722 * @since jsrsasign 10.1.0 base64x 1.1.18 1723 * @example 1724 * strpad("1234", 10, "0") → "0000001234" 1725 * strpad("1234", 10, " ") → " 1234" 1726 * strpad("1234", 10) → "0000001234" 1727 */ 1728 var strpad = function(s, len, padchar) { 1729 if (padchar == undefined) padchar = "0"; 1730 if (s.length >= len) return s; 1731 return new Array(len - s.length + 1).join(padchar) + s; 1732 }; 1733 1734 // ==== bitstr hex / int ================================= 1735 1736 /** 1737 * convert from hexadecimal string of ASN.1 BitString value with unused bit to integer value<br/> 1738 * @name bitstrtoint 1739 * @function 1740 * @param {String} h hexadecimal string of ASN.1 BitString value with unused bit 1741 * @return {Number} positive integer value of the BitString 1742 * @since jsrsasign 10.1.3 base64x 1.1.19 1743 * @see inttobitstr 1744 * @see KJUR.asn1.DERBitString 1745 * @see ASN1HEX.getInt 1746 * 1747 * @description 1748 * This function converts from hexadecimal string of ASN.1 BitString 1749 * value with unused bit to its integer value. <br/> 1750 * When an improper hexadecimal string of BitString value 1751 * is applied, this returns -1. 1752 * 1753 * @example 1754 * // "03c8" → 0xc8 unusedbit=03 → 11001000b unusedbit=03 → 11001b → 25 1755 * bitstrtoint("03c8") → 25 1756 * // "02fff8" → 0xfff8 unusedbit=02 → 1111111111111000b unusedbit=02 1757 * // 11111111111110b → 16382 1758 * bitstrtoint("02fff8") → 16382 1759 * bitstrtoint("05a0") → 5 (=101b) 1760 * bitstrtoint("ff00") → -1 // for improper BitString value 1761 * bitstrtoint("05a0").toString(2) → "101" 1762 * bitstrtoint("07a080").toString(2) → "101000001" 1763 */ 1764 function bitstrtoint(h) { 1765 if (h.length % 2 != 0) return -1; 1766 h = h.toLowerCase(); 1767 if (h.match(/^[0-9a-f]+$/) == null) return -1; 1768 try { 1769 var hUnusedbit = h.substr(0, 2); 1770 if (hUnusedbit == "00") 1771 return parseInt(h.substr(2), 16); 1772 var iUnusedbit = parseInt(hUnusedbit, 16); 1773 if (iUnusedbit > 7) return -1; 1774 var hValue = h.substr(2); 1775 var bValue = parseInt(hValue, 16).toString(2); 1776 if (bValue == "0") bValue = "00000000"; 1777 bValue = bValue.slice(0, 0 - iUnusedbit); 1778 var iValue = parseInt(bValue, 2); 1779 if (iValue == NaN) return -1; 1780 return iValue; 1781 } catch(ex) { 1782 return -1; 1783 } 1784 }; 1785 1786 /** 1787 * convert from integer value to hexadecimal string of ASN.1 BitString value with unused bit<br/> 1788 * @name inttobitstr 1789 * @function 1790 * @param {Number} n integer value of ASN.1 BitString 1791 * @return {String} hexadecimal string of ASN.1 BitString value with unused bit 1792 * @since jsrsasign 10.1.3 base64x 1.1.19 1793 * @see bitstrtoint 1794 * @see KJUR.asn1.DERBitString 1795 * @see ASN1HEX.getInt 1796 * 1797 * @description 1798 * This function converts from an integer value to 1799 * hexadecimal string of ASN.1 BitString value 1800 * with unused bit. <br/> 1801 * When "n" is not non-negative number, this returns null 1802 * 1803 * @example 1804 * // 25 → 11001b → 11001000b unusedbit=03 → 0xc8 unusedbit=03 → "03c8" 1805 * inttobitstr(25) → "03c8" 1806 * inttobitstr(-3) → null 1807 * inttobitstr("abc") → null 1808 * inttobitstr(parseInt("11001", 2)) → "03c8" 1809 * inttobitstr(parseInt("101", 2)) → "05a0" 1810 * inttobitstr(parseInt("101000001", 2)) → "07a080" 1811 */ 1812 function inttobitstr(n) { 1813 if (typeof n != "number") return null; 1814 if (n < 0) return null; 1815 var bValue = Number(n).toString(2); 1816 var iUnusedbit = 8 - bValue.length % 8; 1817 if (iUnusedbit == 8) iUnusedbit = 0; 1818 bValue = bValue + strpad("", iUnusedbit, "0"); 1819 var hValue = parseInt(bValue, 2).toString(16); 1820 if (hValue.length % 2 == 1) hValue = "0" + hValue; 1821 var hUnusedbit = "0" + iUnusedbit; 1822 return hUnusedbit + hValue; 1823 }; 1824 1825 // ==== bitstr hex / binary string ======================= 1826 1827 /** 1828 * convert from hexadecimal string of ASN.1 BitString value with unused bit to binary string<br/> 1829 * @name bitstrtobinstr 1830 * @function 1831 * @param {string} h hexadecimal string of ASN.1 BitString value with unused bit 1832 * @return {string} binary string 1833 * @since jsrsasign 10.5.4 base64x 1.1.21 1834 * @see binstrtobitstr 1835 * @see inttobitstr 1836 * 1837 * @description 1838 * This function converts from hexadecimal string of ASN.1 BitString 1839 * value with unused bit to its integer value. <br/> 1840 * When an improper hexadecimal string of BitString value 1841 * is applied, this returns null. 1842 * 1843 * @example 1844 * bitstrtobinstr("05a0") → "101" 1845 * bitstrtobinstr("0520") → "001" 1846 * bitstrtobinstr("07a080") → "101000001" 1847 * bitstrtobinstr(502) → null // non ASN.1 BitString value 1848 * bitstrtobinstr("ff00") → null // for improper BitString value 1849 */ 1850 function bitstrtobinstr(h) { 1851 if (typeof h != "string") return null; 1852 if (h.length % 2 != 0) return null; 1853 if (! h.match(/^[0-9a-f]+$/)) return null; 1854 try { 1855 var unusedBits = parseInt(h.substr(0, 2), 16); 1856 if (unusedBits < 0 || 7 < unusedBits) return null 1857 1858 var value = h.substr(2); 1859 var bin = ""; 1860 for (var i = 0; i < value.length; i += 2) { 1861 var hi = value.substr(i, 2); 1862 var bi = parseInt(hi, 16).toString(2); 1863 bi = ("0000000" + bi).slice(-8); 1864 bin += bi; 1865 } 1866 return bin.substr(0, bin.length - unusedBits); 1867 } catch(ex) { 1868 return null; 1869 } 1870 } 1871 1872 /** 1873 * convert from binary string to hexadecimal string of ASN.1 BitString value with unused bit<br/> 1874 * @name binstrtobitstr 1875 * @function 1876 * @param {string} s binary string (ex. "101") 1877 * @return {string} hexadecimal string of ASN.1 BitString value with unused bit 1878 * @since jsrsasign 10.5.4 base64x 1.1.21 1879 * @see bitstrtobinstr 1880 * @see inttobitstr 1881 * @see KJUR.asn1.DERBitString 1882 * 1883 * @description 1884 * This function converts from an binary string (ex. "101") to 1885 * hexadecimal string of ASN.1 BitString value 1886 * with unused bit (ex. "05a0"). <br/> 1887 * When "s" is not binary string, this returns null. 1888 * 1889 * @example 1890 * binstrtobitstr("101") → "05a0" 1891 * binstrtobitstr("001") → "0520" 1892 * binstrtobitstr("11001") → "03c8" 1893 * binstrtobitstr("101000001") → "07a080" 1894 * binstrtobitstr(101) → null // not number 1895 * binstrtobitstr("xyz") → null // not binary string 1896 */ 1897 function binstrtobitstr(s) { 1898 if (typeof s != "string") return null; 1899 if (s.match(/^[01]+$/) == null) return null; 1900 try { 1901 var n = parseInt(s, 2); 1902 return inttobitstr(n); 1903 } catch(ex) { 1904 return null; 1905 } 1906 } 1907 1908 // ======================================================= 1909 /** 1910 * convert array of names to bit string<br/> 1911 * @name namearraytobinstr 1912 * @function 1913 * @param {array} namearray array of name string 1914 * @param {object} namedb associative array of name and value 1915 * @return {string} binary string (ex. "110001") 1916 * @since jsrsasign 10.5.21 base64x 1.1.27 1917 * @see KJUR.asn1.x509.KeyUsage 1918 * @see KJUR.asn1.tsp.PKIFailureInfo 1919 * 1920 * @description 1921 * This function converts from an array of names to 1922 * a binary string. DB value bit will be set. 1923 * Note that ordering of namearray items 1924 * will be ignored. 1925 * 1926 * @example 1927 * db = { a: 0, b: 3, c: 8, d: 9, e: 17, f: 19 }; 1928 * namearraytobinstr(['a', 'c', 'd'], db) &rarr: '1000000011' 1929 * namearraytobinstr(['c', 'b'], db) &rarr: '000100001' 1930 */ 1931 function namearraytobinstr (namearray, namedb) { 1932 var d = 0; 1933 for (var i = 0; i < namearray.length; i++) { 1934 d |= 1 << namedb[namearray[i]]; 1935 } 1936 1937 var s = d.toString(2); 1938 var r = ""; 1939 for (var i = s.length - 1; i >=0; i--) { 1940 r += s[i]; 1941 } 1942 return r; 1943 } 1944 1945 // ======================================================= 1946 /** 1947 * set class inheritance<br/> 1948 * @name extendClass 1949 * @function 1950 * @param {Function} subClass sub class to set inheritance 1951 * @param {Function} superClass super class to inherit 1952 * @since jsrsasign 10.3.0 base64x 1.1.21 1953 * 1954 * @description 1955 * This function extends a class and set an inheritance 1956 * for member variables and methods. 1957 * 1958 * @example 1959 * var Animal = function() { 1960 * this.hello = function(){console.log("Hello")}; 1961 * this.name="Ani"; 1962 * }; 1963 * var Dog = function() { 1964 * Dog.superclass.constructor.call(this); 1965 * this.vow = function(){console.log("Vow wow")}; 1966 * this.tail=true; 1967 * }; 1968 * extendClass(Dog, Animal); 1969 */ 1970 function extendClass(subClass, superClass) { 1971 var F = function() {}; 1972 F.prototype = superClass.prototype; 1973 subClass.prototype = new F(); 1974 subClass.prototype.constructor = subClass; 1975 subClass.superclass = superClass.prototype; 1976 1977 if (superClass.prototype.constructor == Object.prototype.constructor) { 1978 superClass.prototype.constructor = superClass; 1979 } 1980 }; 1981 1982