diff --git a/README.md b/README.md
index a64ca450f..d8ca90eb9 100644
--- a/README.md
+++ b/README.md
@@ -174,6 +174,7 @@ Validator | Description
**isVAT(str, countryCode)** | check if the string is a [valid VAT number][VAT Number] if validation is available for the given country code matching [ISO 3166-1 alpha-2][ISO 3166-1 alpha-2].
`countryCode` is one of `['AL', 'AR', 'AT', 'AU', 'BE', 'BG', 'BO', 'BR', 'BY', 'CA', 'CH', 'CL', 'CO', 'CR', 'CY', 'CZ', 'DE', 'DK', 'DO', 'EC', 'EE', 'EL', 'ES', 'FI', 'FR', 'GB', 'GT', 'HN', 'HR', 'HU', 'ID', 'IE', 'IL', 'IN', 'IS', 'IT', 'KZ', 'LT', 'LU', 'LV', 'MK', 'MT', 'MX', 'NG', 'NI', 'NL', 'NO', 'NZ', 'PA', 'PE', 'PH', 'PL', 'PT', 'PY', 'RO', 'RS', 'RU', 'SA', 'SE', 'SI', 'SK', 'SM', 'SV', 'TR', 'UA', 'UY', 'UZ', 'VE']`.
**isWhitelisted(str, chars)** | check if the string consists only of characters that appear in the whitelist `chars`.
**matches(str, pattern [, modifiers])** | check if the string matches the pattern.
Either `matches('foo', /foo/i)` or `matches('foo', 'foo', 'i')`.
+**isCPF(str)** | check if the string follows the rules defined by the Brazilian Federal Revenue Service for CPF verification digit calculation.
## Sanitizers
diff --git a/src/index.js b/src/index.js
index c47674595..20baffb54 100644
--- a/src/index.js
+++ b/src/index.js
@@ -130,6 +130,8 @@ import isStrongPassword from './lib/isStrongPassword';
import isVAT from './lib/isVAT';
+import isCPF from './lib/isCPF';
+
const version = '13.15.0';
const validator = {
@@ -245,6 +247,7 @@ const validator = {
isLicensePlate,
isVAT,
ibanLocales,
+ isCPF,
};
export default validator;
diff --git a/src/lib/isCPF.js b/src/lib/isCPF.js
new file mode 100644
index 000000000..d9ddf789f
--- /dev/null
+++ b/src/lib/isCPF.js
@@ -0,0 +1,52 @@
+import assertString from './util/assertString';
+
+const isMask = /[.-]/g;
+const repeatedDigitsRegex = /^(\d)\1{10}$/;
+
+export default function isCPF(cpf) {
+ assertString(cpf);
+
+ let cleanedCPF = String(cpf);
+
+ if (isMask.test(cleanedCPF)) {
+ cleanedCPF = cleanedCPF.replace(isMask, '');
+ }
+
+ if (cleanedCPF.length !== 11) return false;
+ if (repeatedDigitsRegex.test(cleanedCPF)) return false;
+
+ const paramD1 = {
+ 10: 0, 9: 1, 8: 2, 7: 3, 6: 4, 5: 5, 4: 6, 3: 7, 2: 8,
+ };
+ const paramD2 = {
+ 11: 0, 10: 1, 9: 2, 8: 3, 7: 4, 6: 5, 5: 6, 4: 7, 3: 8, 2: 9,
+ };
+ let firstNineCharacters = cleanedCPF.slice(0, 9);
+ let d1 = 0;
+ let d2 = 0;
+
+ for (let i = 10; i >= 2; i--) {
+ if (Number.isNaN(Number(firstNineCharacters[paramD1[i]]))) return false;
+ d1 += Number(firstNineCharacters[paramD1[i]]) * i;
+ }
+
+ if (d1 % 11 < 2) {
+ d1 = 0;
+ } else {
+ d1 = 11 - (d1 % 11);
+ }
+
+ firstNineCharacters += String(d1);
+
+ for (let i = 11; i >= 2; i--) {
+ d2 += Number(firstNineCharacters[paramD2[i]]) * i;
+ }
+
+ if (d2 % 11 < 2) {
+ d2 = 0;
+ } else {
+ d2 = 11 - (d2 % 11);
+ }
+
+ return cleanedCPF.slice(-2) === `${d1}${d2}`;
+}
diff --git a/test/validators.test.js b/test/validators.test.js
index d6e948a41..e8dcf2b00 100644
--- a/test/validators.test.js
+++ b/test/validators.test.js
@@ -15440,4 +15440,63 @@ describe('Validators', () => {
],
});
});
+ it('should validate a CPF', () => {
+ test({
+ validator: 'isCPF',
+ valid: [
+ '157.099.548-61',
+ '55734947598',
+ '601.425.558-35',
+ '54945762139',
+ '367.181.238-97',
+ '43849941922',
+ '979.893.929-84',
+ '98273014037',
+ '666.030.947-03',
+ '40668005130',
+ '506.999.755-65',
+ '98798876465',
+ '816.611.889-07',
+ '52991780002',
+ '037.039.807-61',
+ '62281573370',
+ '055.751.255-72',
+ '03085770860',
+ '286.860.021-29',
+ '24234579793',
+ ],
+ invalid: [
+ '296.231.440-69',
+ '62424843039',
+ '477.887.094-96',
+ '41526890821',
+ '861.803.242-00',
+ '57751926579',
+ '034.928.141-63',
+ '66437339822',
+ '178.714.111-57',
+ '27507501358',
+ '769.259.949-19',
+ '43661169739',
+ '646.438.057-95',
+ '49403410474',
+ '113.512.907-25',
+ '81322401108',
+ '458.825.895-23',
+ '92472311425',
+ '585.251.576-48',
+ '00002283074',
+ '796.940.600-52',
+ '08228682581',
+ '906.765.489-12',
+ '31437427245',
+ '045.504.051-45',
+ '21383151886',
+ '519.213.751-90',
+ '06712261581',
+ '884.593.736-07',
+ '42188048376',
+ ],
+ });
+ });
});