isIdentityCard.js 13 KB

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