Subversion Repositories oidplus

Rev

Rev 751 | Go to most recent revision | View as "text/javascript" | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1.  
  2. /**
  3.  * WEID<=>OID Converter
  4.  * (c) Webfan.de, ViaThinkSoft
  5.  * Revision 2022-02-22
  6.  **/
  7.  
  8. // What is a WEID?
  9. //     A WEID (WEhowski IDentifier) is an alternative representation of an
  10. //     OID (Object IDentifier) defined by Till Wehowski.
  11. //     In OIDs, arcs are in decimal base 10. In WEIDs, the arcs are in base 36.
  12. //     Also, each WEID has a check digit at the end (called WeLohn Check Digit).
  13. //
  14. // Changes in the December 2021 definition by Daniel Marschall:
  15. //     - There are several classes of WEIDs which have different OID bases:
  16. //           "Class C" WEID:  weid:EXAMPLE-3      (base .1.3.6.1.4.1.37553.8.)
  17. //                            oid:1.3.6.1.4.1.37553.8.32488192274
  18. //           "Class B" WEID:  weid:pen:SX0-7PR-6  (base .1.3.6.1.4.1.)
  19. //                            oid:1.3.6.1.4.1.37476.9999
  20. //           "Class A" WEID:  weid:root:2-RR-2    (base .)
  21. //                            oid:2.999
  22. //     - The namespace (weid:, weid:pen:, weid:root:) is now case insensitive.
  23. //     - Padding with '0' characters is valid (e.g. weid:000EXAMPLE-3)
  24. //       The paddings do not count into the WeLuhn check-digit.
  25.  
  26. // Requires "mikemcl/bignumber.js" library
  27.  
  28. var WeidOidConverter = {
  29.  
  30.         weLuhnCheckDigit: function(str) {
  31.                 // Padding zeros don't count to the check digit (December 2021)
  32.                 var ary = str.split('-');
  33.                 ary.forEach((o,i,a) => {
  34.                         a[i] = a[i].replace(/^0+/, '');
  35.                 } );
  36.                 str = ary.join('-');
  37.  
  38.                 // remove separators from the WEID string
  39.                 var wrkstr = str.replaceAll('-', '');
  40.  
  41.                 // Replace 'a' with '10', 'b' with '1', etc.
  42.                 for (var i=0; i<26; i++) {
  43.                         wrkstr = wrkstr.toLowerCase().replaceAll(String.fromCharCode('a'.charCodeAt(0)+i).toLowerCase(), (10+i));
  44.                 }
  45.  
  46.                 // At the end, wrkstr should only contain digits! Verify it!
  47.                 if (!wrkstr.match(/^\d+$/)) return false;
  48.  
  49.                 // Now do the standard Luhn algorithm
  50.                 var nbdigits = wrkstr.length;
  51.                 var parity = nbdigits & 1; // mod 2
  52.                 var sum = 0;
  53.                 for (var n=nbdigits-1; n>=0; n--) {
  54.                         var digit = parseInt(wrkstr.substr(n,1));
  55.                         if ((n & 1) != parity) digit *= 2;
  56.                         if (digit > 9) digit -= 9;
  57.                         sum += digit;
  58.                 }
  59.                 return (sum%10) == 0 ? 0 : 10-(sum%10);
  60.         },
  61.  
  62.         // Translates a WEID to an OID
  63.         // "weid:EXAMPLE-3" becomes "1.3.6.1.4.1.37553.8.32488192274"
  64.         // If it failed (e.g. wrong namespace, wrong checksum, etc.) then false is returned.
  65.         // If the weid ends with '?', the checksum will be added
  66.         // Return value is an array with the elements "oid" and "weid".
  67.         // Example:
  68.         //     weid2oid("weid:EXAMPLE-?").weid == "weid:EXAMPLE-3"
  69.         //     weid2oid("weid:EXAMPLE-?").oid  == "1.3.6.1.4.1.37553.8.32488192274"
  70.         weid2oid: function(weid) {
  71.                 var p = weid.lastIndexOf(':');
  72.                 var namespace = weid.substr(0, p+1);
  73.                 var rest = weid.substr(p+1);
  74.  
  75.                 namespace = namespace.toLowerCase(); // namespace is case insensitive
  76.                 if (namespace == 'weid:') {
  77.                         // Class C
  78.                         var base = '1-3-6-1-4-1-SZ5-8';
  79.                 } else if (namespace == 'weid:pen:') {
  80.                         // Class B
  81.                         var base = '1-3-6-1-4-1';
  82.                 } else if (namespace == 'weid:root:') {
  83.                         // Class A
  84.                         var base = '';
  85.                 } else {
  86.                         // Wrong namespace
  87.                         return false;
  88.                 }
  89.  
  90.                 weid = rest;
  91.  
  92.                 var elements = ((base != '') ? base.split('-') : []).concat(weid.split('-'));
  93.                 var actual_checksum = elements.pop();
  94.                 var expected_checksum = weLuhnCheckDigit(elements.join('-'));
  95.                 if (actual_checksum != '?') {
  96.                         if (actual_checksum != expected_checksum) return false; // wrong checksum
  97.                 } else {
  98.                         // If checksum is '?', it will be replaced by the actual checksum,
  99.                         // e.g. weid:EXAMPLE-? becomes weid:EXAMPLE-3
  100.                         weid = weid.replace('?', expected_checksum);
  101.                 }
  102.                 elements.forEach((o,i,a) => {
  103.                         a[i] = BigNumber(a[i],36).toString(10).toUpperCase();
  104.                 });
  105.                 var oidstr = elements.join('.');
  106.  
  107.                 weid = namespace.toLowerCase() + weid.toUpperCase(); // add namespace again
  108.  
  109.                 return { "weid": weid, "oid" : oidstr };
  110.         },
  111.  
  112.         // Converts an OID to WEID
  113.         // "1.3.6.1.4.1.37553.8.32488192274" becomes "weid:EXAMPLE-3"
  114.         oid2weid: function(oid) {
  115.                 if (oid.substr(0,1) == '.') oid = oid.substr(1); // remove leading dot
  116.  
  117.                 if (oid != '') {
  118.                         var elements = oid.split('.');
  119.                         elements.forEach((o,i,a) => {
  120.                                 var x = BigNumber(a[i],10);
  121.                                 a[i] = x.toString(36).toUpperCase();
  122.                         });
  123.                         var weidstr = elements.join("-");
  124.                 } else {
  125.                         var weidstr = '';
  126.                 }
  127.  
  128.                 var is_class_c = (weidstr.startsWith('1-3-6-1-4-1-SZ5-8-') || (weidstr == '1-3-6-1-4-1-SZ5-8'));
  129.                 var is_class_b = (weidstr.startsWith('1-3-6-1-4-1-') || (weidstr == '1-3-6-1-4-1'));
  130.                 var is_class_a = !is_class_b && !is_class_c;
  131.  
  132.                 var checksum = weLuhnCheckDigit(weidstr);
  133.  
  134.                 if (is_class_c) {
  135.                         weidstr = weidstr.substr('1-3-6-1-4-1-SZ5-8-'.length);
  136.                         var namespace = 'weid:';
  137.                 } else if (is_class_b) {
  138.                         weidstr = weidstr.substr('1-3-6-1-4-1-'.length);
  139.                         var namespace = 'weid:pen:';
  140.                 } else if (is_class_a) {
  141.                         // weidstr stays
  142.                         var namespace = 'weid:root:';
  143.                 } else {
  144.                         // should not happen
  145.                         console.error("oid2weid: Cannot detect namespace");
  146.                         return false;
  147.                 }
  148.  
  149.                 return namespace + (weidstr == '' ? checksum : weidstr + '-' + checksum);
  150.         }
  151.  
  152. }
  153.