解密 CPF 算法

为了举例说明这个过程,让我们生成一个有效的 CPF,计算一个假设数字 111,444,777-XX 的校验位。

计算第一个校验位

CPF 的第一个校验位使用以下算法计算。

1)分配一帧中的前 9 位数字,将权重 10, 9, 8, 7, 6, 5, 4, 3, 2 从左到右放置在下方,如下图所示:

1 1 1 4 4 4 7 7 7
10 9 8 7 6 5 4 3 2

2)将每一列的值相乘:

1 1 1 4 4 4 7 7 7
10 9 8 7 6 5 4 3 2
10 9 8 28 24 20 28 21 14

3)计算结果之和 (10+9+...+21+14) = 162

4)得到的结果(162)将除以11。仅将整数值视为商,除法的余数将负责计算第一个校验位。

让我们继续: 162 除以 11 我们得到 14 作为商,8 作为除法的余数。如果除法的余数小于 2,我们的第一个校验位变为 0(零),否则得到的值从 11 中减去,这就是我们的情况。所以我们的校验位是11-8,也就是3(三)。所以我们已经有了部分 CPF,请查看:111.444.777-3 X。

计算第二个校验位

1)对于第二位的计算,将使用已计算的第一个校验位。我们将建立一个与上一个相似的表,只是这次我们将使用第二行中的值 11,10,9,8,7,6,5,4,3,2,因为我们合并了一个此计算的更多数字。看:

1 1 1 4 4 4 7 7 7 3
11 10 9 8 7 6 5 4 3 2

2)下一步,我们将按照计算第一个校验位的情况,将每一列的值相乘,并将得到的结果求和:(11+10+...+21 +6) = 204。

1 1 1 4 4 4 7 7 7 3
11 10 9 8 7 6 5 4 3 2
11 10 9 32 28 24 35 28 21 6

3)我们再次执行模块 11 的计算,我们将总和除以 11 并考虑除法的余数。

让我们继续: 204 除以 11 我们得到 18 作为商,6 作为除法的余数。

4)如果除法的余数小于2,则该值自动变为0,否则(如我们的例子)需要从11中减去得到的值才能得到校验位。所以 11-6=5,这是我们的第二个校验位。

在这种情况下,我们到达计算的末尾,发现我们假设的 CPF 的校验位是数字35,因此 CPF 看起来像这样:111,444,777-35

本网站提供的cpf 生成器基于此算法工作。

生成有效 CPF 的例程最初抽取 9 个数字。第一个校验位被计算并集成到 9 个初始数字中。按照教导继续计算第二个校验位。最后,CPF 创建者发出一个有效的 CPF 编号。

生成有效的 CNPJ 的工作方式类似。如果您有兴趣,请参阅有关cnpj 算法的更多信息。

CPF算法的实现

function validarCPF(cpf) {
	cpf = cpf.replace(/[^\d]+/g,'');
	if(cpf == '') return false;
	// Elimina CPFs invalidos conhecidos
	if (cpf.length != 11 ||
		cpf == "00000000000" ||
		cpf == "11111111111" ||
		cpf == "22222222222" ||
		cpf == "33333333333" ||
		cpf == "44444444444" ||
		cpf == "55555555555" ||
		cpf == "66666666666" ||
		cpf == "77777777777" ||
		cpf == "88888888888" ||
		cpf == "99999999999")
			return false;
	// Valida 1o digito
	add = 0;
	for (i=0; i < 9; i ++)
		add += parseInt(cpf.charAt(i)) * (10 - i);
		rev = 11 - (add % 11);
		if (rev == 10 || rev == 11)
			rev = 0;
		if (rev != parseInt(cpf.charAt(9)))
			return false;
	// Valida 2o digito
	add = 0;
	for (i = 0; i < 10; i ++)
		add += parseInt(cpf.charAt(i)) * (11 - i);
	rev = 11 - (add % 11);
	if (rev == 10 || rev == 11)
		rev = 0;
	if (rev != parseInt(cpf.charAt(10)))
		return false;
	return true;
}