isIdentityCard.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = isIdentityCard;
  6. var _assertString = _interopRequireDefault(require("./util/assertString"));
  7. var _isInt = _interopRequireDefault(require("./isInt"));
  8. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  9. var validators = {
  10. PL: function PL(str) {
  11. (0, _assertString.default)(str);
  12. var weightOfDigits = {
  13. 1: 1,
  14. 2: 3,
  15. 3: 7,
  16. 4: 9,
  17. 5: 1,
  18. 6: 3,
  19. 7: 7,
  20. 8: 9,
  21. 9: 1,
  22. 10: 3,
  23. 11: 0
  24. };
  25. if (str != null && str.length === 11 && (0, _isInt.default)(str, {
  26. allow_leading_zeroes: true
  27. })) {
  28. var digits = str.split('').slice(0, -1);
  29. var sum = digits.reduce(function (acc, digit, index) {
  30. return acc + Number(digit) * weightOfDigits[index + 1];
  31. }, 0);
  32. var modulo = sum % 10;
  33. var lastDigit = Number(str.charAt(str.length - 1));
  34. if (modulo === 0 && lastDigit === 0 || lastDigit === 10 - modulo) {
  35. return true;
  36. }
  37. }
  38. return false;
  39. },
  40. ES: function ES(str) {
  41. (0, _assertString.default)(str);
  42. var DNI = /^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/;
  43. var charsValue = {
  44. X: 0,
  45. Y: 1,
  46. Z: 2
  47. };
  48. var controlDigits = ['T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E']; // sanitize user input
  49. var sanitized = str.trim().toUpperCase(); // validate the data structure
  50. if (!DNI.test(sanitized)) {
  51. return false;
  52. } // validate the control digit
  53. var number = sanitized.slice(0, -1).replace(/[X,Y,Z]/g, function (char) {
  54. return charsValue[char];
  55. });
  56. return sanitized.endsWith(controlDigits[number % 23]);
  57. },
  58. FI: function FI(str) {
  59. // https://dvv.fi/en/personal-identity-code#:~:text=control%20character%20for%20a-,personal,-identity%20code%20calculated
  60. (0, _assertString.default)(str);
  61. if (str.length !== 11) {
  62. return false;
  63. }
  64. if (!str.match(/^\d{6}[\-A\+]\d{3}[0-9ABCDEFHJKLMNPRSTUVWXY]{1}$/)) {
  65. return false;
  66. }
  67. var checkDigits = '0123456789ABCDEFHJKLMNPRSTUVWXY';
  68. var idAsNumber = parseInt(str.slice(0, 6), 10) * 1000 + parseInt(str.slice(7, 10), 10);
  69. var remainder = idAsNumber % 31;
  70. var checkDigit = checkDigits[remainder];
  71. return checkDigit === str.slice(10, 11);
  72. },
  73. IN: function IN(str) {
  74. var DNI = /^[1-9]\d{3}\s?\d{4}\s?\d{4}$/; // multiplication table
  75. var d = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 0, 6, 7, 8, 9, 5], [2, 3, 4, 0, 1, 7, 8, 9, 5, 6], [3, 4, 0, 1, 2, 8, 9, 5, 6, 7], [4, 0, 1, 2, 3, 9, 5, 6, 7, 8], [5, 9, 8, 7, 6, 0, 4, 3, 2, 1], [6, 5, 9, 8, 7, 1, 0, 4, 3, 2], [7, 6, 5, 9, 8, 2, 1, 0, 4, 3], [8, 7, 6, 5, 9, 3, 2, 1, 0, 4], [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]; // permutation table
  76. var p = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]]; // sanitize user input
  77. var sanitized = str.trim(); // validate the data structure
  78. if (!DNI.test(sanitized)) {
  79. return false;
  80. }
  81. var c = 0;
  82. var invertedArray = sanitized.replace(/\s/g, '').split('').map(Number).reverse();
  83. invertedArray.forEach(function (val, i) {
  84. c = d[c][p[i % 8][val]];
  85. });
  86. return c === 0;
  87. },
  88. IR: function IR(str) {
  89. if (!str.match(/^\d{10}$/)) return false;
  90. str = "0000".concat(str).substr(str.length - 6);
  91. if (parseInt(str.substr(3, 6), 10) === 0) return false;
  92. var lastNumber = parseInt(str.substr(9, 1), 10);
  93. var sum = 0;
  94. for (var i = 0; i < 9; i++) {
  95. sum += parseInt(str.substr(i, 1), 10) * (10 - i);
  96. }
  97. sum %= 11;
  98. return sum < 2 && lastNumber === sum || sum >= 2 && lastNumber === 11 - sum;
  99. },
  100. IT: function IT(str) {
  101. if (str.length !== 9) return false;
  102. if (str === 'CA00000AA') return false; // https://it.wikipedia.org/wiki/Carta_d%27identit%C3%A0_elettronica_italiana
  103. return str.search(/C[A-Z][0-9]{5}[A-Z]{2}/i) > -1;
  104. },
  105. NO: function NO(str) {
  106. var sanitized = str.trim();
  107. if (isNaN(Number(sanitized))) return false;
  108. if (sanitized.length !== 11) return false;
  109. if (sanitized === '00000000000') return false; // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer
  110. var f = sanitized.split('').map(Number);
  111. var k1 = (11 - (3 * f[0] + 7 * f[1] + 6 * f[2] + 1 * f[3] + 8 * f[4] + 9 * f[5] + 4 * f[6] + 5 * f[7] + 2 * f[8]) % 11) % 11;
  112. var k2 = (11 - (5 * f[0] + 4 * f[1] + 3 * f[2] + 2 * f[3] + 7 * f[4] + 6 * f[5] + 5 * f[6] + 4 * f[7] + 3 * f[8] + 2 * k1) % 11) % 11;
  113. if (k1 !== f[9] || k2 !== f[10]) return false;
  114. return true;
  115. },
  116. TH: function TH(str) {
  117. if (!str.match(/^[1-8]\d{12}$/)) return false; // validate check digit
  118. var sum = 0;
  119. for (var i = 0; i < 12; i++) {
  120. sum += parseInt(str[i], 10) * (13 - i);
  121. }
  122. return str[12] === ((11 - sum % 11) % 10).toString();
  123. },
  124. LK: function LK(str) {
  125. var old_nic = /^[1-9]\d{8}[vx]$/i;
  126. var new_nic = /^[1-9]\d{11}$/i;
  127. if (str.length === 10 && old_nic.test(str)) return true;else if (str.length === 12 && new_nic.test(str)) return true;
  128. return false;
  129. },
  130. 'he-IL': function heIL(str) {
  131. var DNI = /^\d{9}$/; // sanitize user input
  132. var sanitized = str.trim(); // validate the data structure
  133. if (!DNI.test(sanitized)) {
  134. return false;
  135. }
  136. var id = sanitized;
  137. var sum = 0,
  138. incNum;
  139. for (var i = 0; i < id.length; i++) {
  140. incNum = Number(id[i]) * (i % 2 + 1); // Multiply number by 1 or 2
  141. sum += incNum > 9 ? incNum - 9 : incNum; // Sum the digits up and add to total
  142. }
  143. return sum % 10 === 0;
  144. },
  145. 'ar-LY': function arLY(str) {
  146. // Libya National Identity Number NIN is 12 digits, the first digit is either 1 or 2
  147. var NIN = /^(1|2)\d{11}$/; // sanitize user input
  148. var sanitized = str.trim(); // validate the data structure
  149. if (!NIN.test(sanitized)) {
  150. return false;
  151. }
  152. return true;
  153. },
  154. 'ar-TN': function arTN(str) {
  155. var DNI = /^\d{8}$/; // sanitize user input
  156. var sanitized = str.trim(); // validate the data structure
  157. if (!DNI.test(sanitized)) {
  158. return false;
  159. }
  160. return true;
  161. },
  162. 'zh-CN': function zhCN(str) {
  163. var provincesAndCities = ['11', // 北京
  164. '12', // 天津
  165. '13', // 河北
  166. '14', // 山西
  167. '15', // 内蒙古
  168. '21', // 辽宁
  169. '22', // 吉林
  170. '23', // 黑龙江
  171. '31', // 上海
  172. '32', // 江苏
  173. '33', // 浙江
  174. '34', // 安徽
  175. '35', // 福建
  176. '36', // 江西
  177. '37', // 山东
  178. '41', // 河南
  179. '42', // 湖北
  180. '43', // 湖南
  181. '44', // 广东
  182. '45', // 广西
  183. '46', // 海南
  184. '50', // 重庆
  185. '51', // 四川
  186. '52', // 贵州
  187. '53', // 云南
  188. '54', // 西藏
  189. '61', // 陕西
  190. '62', // 甘肃
  191. '63', // 青海
  192. '64', // 宁夏
  193. '65', // 新疆
  194. '71', // 台湾
  195. '81', // 香港
  196. '82', // 澳门
  197. '91' // 国外
  198. ];
  199. var powers = ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2'];
  200. var parityBit = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
  201. var checkAddressCode = function checkAddressCode(addressCode) {
  202. return provincesAndCities.includes(addressCode);
  203. };
  204. var checkBirthDayCode = function checkBirthDayCode(birDayCode) {
  205. var yyyy = parseInt(birDayCode.substring(0, 4), 10);
  206. var mm = parseInt(birDayCode.substring(4, 6), 10);
  207. var dd = parseInt(birDayCode.substring(6), 10);
  208. var xdata = new Date(yyyy, mm - 1, dd);
  209. if (xdata > new Date()) {
  210. return false; // eslint-disable-next-line max-len
  211. } else if (xdata.getFullYear() === yyyy && xdata.getMonth() === mm - 1 && xdata.getDate() === dd) {
  212. return true;
  213. }
  214. return false;
  215. };
  216. var getParityBit = function getParityBit(idCardNo) {
  217. var id17 = idCardNo.substring(0, 17);
  218. var power = 0;
  219. for (var i = 0; i < 17; i++) {
  220. power += parseInt(id17.charAt(i), 10) * parseInt(powers[i], 10);
  221. }
  222. var mod = power % 11;
  223. return parityBit[mod];
  224. };
  225. var checkParityBit = function checkParityBit(idCardNo) {
  226. return getParityBit(idCardNo) === idCardNo.charAt(17).toUpperCase();
  227. };
  228. var check15IdCardNo = function check15IdCardNo(idCardNo) {
  229. var check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo);
  230. if (!check) return false;
  231. var addressCode = idCardNo.substring(0, 2);
  232. check = checkAddressCode(addressCode);
  233. if (!check) return false;
  234. var birDayCode = "19".concat(idCardNo.substring(6, 12));
  235. check = checkBirthDayCode(birDayCode);
  236. if (!check) return false;
  237. return true;
  238. };
  239. var check18IdCardNo = function check18IdCardNo(idCardNo) {
  240. var check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo);
  241. if (!check) return false;
  242. var addressCode = idCardNo.substring(0, 2);
  243. check = checkAddressCode(addressCode);
  244. if (!check) return false;
  245. var birDayCode = idCardNo.substring(6, 14);
  246. check = checkBirthDayCode(birDayCode);
  247. if (!check) return false;
  248. return checkParityBit(idCardNo);
  249. };
  250. var checkIdCardNo = function checkIdCardNo(idCardNo) {
  251. var check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo);
  252. if (!check) return false;
  253. if (idCardNo.length === 15) {
  254. return check15IdCardNo(idCardNo);
  255. }
  256. return check18IdCardNo(idCardNo);
  257. };
  258. return checkIdCardNo(str);
  259. },
  260. 'zh-TW': function zhTW(str) {
  261. var ALPHABET_CODES = {
  262. A: 10,
  263. B: 11,
  264. C: 12,
  265. D: 13,
  266. E: 14,
  267. F: 15,
  268. G: 16,
  269. H: 17,
  270. I: 34,
  271. J: 18,
  272. K: 19,
  273. L: 20,
  274. M: 21,
  275. N: 22,
  276. O: 35,
  277. P: 23,
  278. Q: 24,
  279. R: 25,
  280. S: 26,
  281. T: 27,
  282. U: 28,
  283. V: 29,
  284. W: 32,
  285. X: 30,
  286. Y: 31,
  287. Z: 33
  288. };
  289. var sanitized = str.trim().toUpperCase();
  290. if (!/^[A-Z][0-9]{9}$/.test(sanitized)) return false;
  291. return Array.from(sanitized).reduce(function (sum, number, index) {
  292. if (index === 0) {
  293. var code = ALPHABET_CODES[number];
  294. return code % 10 * 9 + Math.floor(code / 10);
  295. }
  296. if (index === 9) {
  297. return (10 - sum % 10 - Number(number)) % 10 === 0;
  298. }
  299. return sum + Number(number) * (9 - index);
  300. }, 0);
  301. }
  302. };
  303. function isIdentityCard(str, locale) {
  304. (0, _assertString.default)(str);
  305. if (locale in validators) {
  306. return validators[locale](str);
  307. } else if (locale === 'any') {
  308. for (var key in validators) {
  309. // https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes
  310. // istanbul ignore else
  311. if (validators.hasOwnProperty(key)) {
  312. var validator = validators[key];
  313. if (validator(str)) {
  314. return true;
  315. }
  316. }
  317. }
  318. return false;
  319. }
  320. throw new Error("Invalid locale '".concat(locale, "'"));
  321. }
  322. module.exports = exports.default;
  323. module.exports.default = exports.default;