function executar(count = 1, formatted = true, state = 'SP') {
const ELECTORAL_STATES = [
['01', 'SP'], ['02', 'MG'], ['03', 'RJ'], ['04', 'RS'], ['05', 'BA'],
['06', 'PR'], ['07', 'CE'], ['08', 'PE'], ['09', 'SC'], ['10', 'GO'],
['11', 'MA'], ['12', 'PB'], ['13', 'PA'], ['14', 'ES'], ['15', 'PI'],
['16', 'RN'], ['17', 'AL'], ['18', 'MT'], ['19', 'MS'], ['20', 'DF'],
['21', 'SE'], ['22', 'AM'], ['23', 'RO'], ['24', 'AC'], ['25', 'AP'],
['26', 'RR'], ['27', 'TO'], ['28', 'Exterior'],
];
function weightedSum(base, weights, alphanumeric = false) {
return [...base].reduce((sum, character, index) => sum + (alphanumeric ? character.charCodeAt(0) - 48 : Number(character)) * weights[index], 0);
}
function mod11(base, weights, alphanumeric = false) {
const remainder = weightedSum(base, weights, alphanumeric) % 11;
return remainder < 2 ? 0 : 11 - remainder;
}
function assertBase(base, length, alphanumeric = false) {
if (base.length !== length || !(alphanumeric ? /^[0-9A-Z]+$/ : /^\d+$/).test(base)) {
throw new Error(`A base deve ter ${length} ${alphanumeric ? 'caracteres de 0 a 9 ou A a Z' : 'dígitos'}.`);
}
}
function cpfChecksum(base) {
assertBase(base, 9);
const first = mod11(base, [10, 9, 8, 7, 6, 5, 4, 3, 2]);
return `${first}${mod11(base + first, [11, 10, 9, 8, 7, 6, 5, 4, 3, 2])}`;
}
function cnpjChecksum(base) {
assertBase(base, 12, true);
const first = mod11(base, [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2], true);
return `${first}${mod11(base + first, [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2], true)}`;
}
function rgChecksum(base) {
assertBase(base, 8);
const digit = (11 - weightedSum(base, [2, 3, 4, 5, 6, 7, 8, 9]) % 11) % 11;
return digit === 10 ? 'X' : String(digit);
}
function cnhChecksum(base) {
assertBase(base, 9);
const remainder = weightedSum(base, [9, 8, 7, 6, 5, 4, 3, 2, 1]) % 11;
const first = remainder === 10 ? 0 : remainder;
const secondRemainder = weightedSum(base, [1, 2, 3, 4, 5, 6, 7, 8, 9]) % 11;
const second = secondRemainder === 10 ? 0 : secondRemainder - (remainder === 10 ? 2 : 0);
// Evita bases que levam a um resultado negativo nas regras legadas de CNH.
return second < 0 ? null : `${first}${second}`;
}
function electoralChecksum(base) {
assertBase(base, 10);
const state = base.slice(8);
if (!ELECTORAL_STATES.some(([code]) => code === state))
throw new Error('Selecione uma UF eleitoral válida.');
const digit = (remainder) => remainder === 10 ? 0 : remainder === 0 && (state === '01' || state === '02') ? 1 : remainder;
const first = digit(weightedSum(base.slice(0, 8), [2, 3, 4, 5, 6, 7, 8, 9]) % 11);
return `${first}${digit(weightedSum(state + first, [7, 8, 9]) % 11)}`;
}
function pisChecksum(base) {
assertBase(base, 10);
return String(mod11(base, [3, 2, 9, 8, 7, 6, 5, 4, 3, 2]));
}
function renavamChecksum(base) {
assertBase(base, 10);
return String(mod11(base, [3, 2, 9, 8, 7, 6, 5, 4, 3, 2]));
}
function completeStateRegistration(base, state) {
if (state === 'SP') {
assertBase(base, 10);
const first = weightedSum(base.slice(0, 8), [1, 3, 4, 5, 6, 7, 8, 10]) % 11 % 10;
const partial = base.slice(0, 8) + first + base.slice(8);
return partial + (weightedSum(partial, [3, 2, 10, 9, 8, 7, 6, 5, 4, 3, 2]) % 11 % 10);
}
if (state === 'MG') {
assertBase(base, 11);
const expanded = base.slice(0, 3) + '0' + base.slice(3);
const sum = [...expanded].reduce((total, character, index) => {
const product = Number(character) * (index % 2 + 1);
return total + Math.floor(product / 10) + product % 10;
}, 0);
const first = (10 - sum % 10) % 10;
return base + first + mod11(base + first, [3, 2, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2]);
}
if (state === 'RJ') {
assertBase(base, 7);
return base + mod11(base, [2, 7, 6, 5, 4, 3, 2]);
}
throw new Error('UF não suportada. Escolha SP, MG ou RJ.');
}
function certificateChecksum(base) {
assertBase(base, 30);
const firstRemainder = weightedSum(base, Array.from({ length: 30 }, (_, index) => (index + 2) % 11)) % 11;
const first = firstRemainder === 10 ? 1 : firstRemainder;
const second = weightedSum(base + first, Array.from({ length: 31 }, (_, index) => (index + 1) % 11)) % 11;
return `${first}${second === 10 ? 1 : second}`;
}
function randomInt(maximum) {
const values = new Uint32Array(1);
const limit = Math.floor(0x100000000 / maximum) * maximum;
do {
crypto.getRandomValues(values);
} while (values[0] >= limit);
return values[0] % maximum;
}
function randomCharacters(length, alphabet = '0123456789') {
return Array.from({ length }, () => alphabet[randomInt(alphabet.length)]).join('');
}
function formatDocument(kind, value, state = 'SP') {
switch (kind) {
case 'cpf': return value.replace(/^(\d{3})(\d{3})(\d{3})(\d{2})$/, '$1.$2.$3-$4');
case 'cnpj': return value.replace(/^(.{2})(.{3})(.{3})(.{4})(\d{2})$/, '$1.$2.$3/$4-$5');
case 'rg': return value.replace(/^(\d{2})(\d{3})(\d{3})([\dX])$/, '$1.$2.$3-$4');
case 'titulo-eleitor': return value.replace(/^(\d{4})(\d{4})(\d{4})$/, '$1 $2 $3');
case 'pis-pasep': return value.replace(/^(\d{3})(\d{5})(\d{2})(\d)$/, '$1.$2.$3-$4');
case 'inscricao-estadual':
if (state === 'SP')
return value.replace(/^(\d{3})(\d{3})(\d{3})(\d{3})$/, '$1.$2.$3.$4');
if (state === 'MG')
return value.replace(/^(\d{3})(\d{3})(\d{3})(\d{4})$/, '$1.$2.$3/$4');
return value.replace(/^(\d{2})(\d{3})(\d{2})(\d)$/, '$1.$2.$3-$4');
case 'certidao': return value.replace(/^(\d{6})(\d{2})(\d{2})(\d{4})(\d)(\d{5})(\d{3})(\d{7})(\d{2})$/, '$1 $2 $3 $4 $5 $6 $7 $8-$9');
default: return value;
}
}
function generateDocument(kind, options = {}) {
const state = options.state ?? 'SP';
let value;
for (;;) {
switch (kind) {
case 'cpf': {
const base = randomCharacters(9);
value = base + cpfChecksum(base);
break;
}
case 'cnpj': {
const alphabet = options.cnpjFormat === 'alphanumeric' ? '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' : '0123456789';
let root = randomCharacters(8, alphabet);
if (options.cnpjFormat === 'alphanumeric' && !/[A-Z]/.test(root))
root = randomCharacters(1, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') + root.slice(1);
const base = root + '0001';
value = base + cnpjChecksum(base);
break;
}
case 'rg': {
const base = randomCharacters(8);
value = base + rgChecksum(base);
break;
}
case 'cnh': {
const base = randomCharacters(9);
const checksum = cnhChecksum(base);
if (checksum === null)
continue;
value = base + checksum;
break;
}
case 'titulo-eleitor': {
const base = randomCharacters(8) + (options.electoralState ?? '01');
value = base + electoralChecksum(base);
break;
}
case 'pis-pasep': {
const base = '1' + randomCharacters(9);
value = base + pisChecksum(base);
break;
}
case 'inscricao-estadual': {
// MG: código municipal 062 e ordem de estabelecimento 00.
const base = state === 'MG' ? '062' + randomCharacters(6) + '00' : state === 'RJ' ? randomCharacters(7) : randomCharacters(10);
value = completeStateRegistration(base, state);
break;
}
case 'renavam': {
const base = '00' + randomCharacters(8);
value = base + renavamChecksum(base);
break;
}
case 'certidao': {
const year = options.year ?? new Date().getFullYear();
if (!Number.isInteger(year) || year < 1900 || year > new Date().getFullYear())
throw new Error('Informe um ano entre 1900 e o ano atual.');
const type = options.certificateType ?? '1';
if (!['1', '2', '4'].includes(type))
throw new Error('Tipo de certidão inválido.');
// CNS aleatório: não há consulta à existência de uma serventia.
const base = String(randomInt(999999) + 1).padStart(6, '0') + '0155' + year + type
+ String(randomInt(99999) + 1).padStart(5, '0')
+ String(randomInt(300) + 1).padStart(3, '0')
+ String(randomInt(9999999) + 1).padStart(7, '0');
value = base + certificateChecksum(base);
break;
}
default: throw new Error('Documento não suportado.');
}
if (/^(.)\1+$/.test(value))
continue;
return options.formatted ? formatDocument(kind, value, state) : value;
}
}
if (!Number.isInteger(count) || count < 1 || count > 100)
throw new Error('Quantidade: de 1 a 100');
if (typeof formatted !== 'boolean')
throw new Error('Máscara deve ser booleana');
const values = new Set();
for (let attempts = 0; values.size < count && attempts < count * 20; attempts++) {
values.add(generateDocument('inscricao-estadual', { formatted, state }));
}
if (values.size !== count)
throw new Error('Não foi possível completar o lote sem repetições');
return [...values].join('\n');
}
import secrets
def executar(count=1, uf='SP', formatted=True):
if type(count) is not int or not 1 <= count <= 100:
raise ValueError('Quantidade: de 1 a 100')
if type(formatted) is not bool: raise ValueError('Máscara deve ser booleana')
def generate():
results = []
def random_chars(n, alphabet='0123456789'):
return ''.join((secrets.choice(alphabet) for _ in range(n)))
def weighted_sum(base, weights, alpha=False):
return sum(((ord(c) - 48 if alpha else int(c)) * w for (c, w) in zip(base, weights)))
def dv(base, weights, alpha=False):
r = weighted_sum(base, weights, alpha) % 11
return 0 if r < 2 else 11 - r
if uf == 'SP':
base = random_chars(10)
d1 = str(weighted_sum(base[:8], [1, 3, 4, 5, 6, 7, 8, 10]) % 11 % 10)
partial = base[:8] + d1 + base[8:]
result = partial + str(weighted_sum(partial, [3, 2, 10, 9, 8, 7, 6, 5, 4, 3, 2]) % 11 % 10)
elif uf == 'MG':
base = '062' + random_chars(6) + '00'
expanded = base[:3] + '0' + base[3:]
total = 0
for (i, c) in enumerate(expanded):
n = int(c) * (i % 2 + 1)
total += n // 10 + n % 10
d1 = str((10 - total % 10) % 10)
result = base + d1 + str(dv(base + d1, [3, 2, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2]))
elif uf == 'RJ':
base = random_chars(7)
result = base + str(dv(base, [2, 7, 6, 5, 4, 3, 2]))
else:
raise ValueError('UF não suportada')
results.append(result)
return results[0] if len(results) == 1 else results
values = []
for _ in range(count * 30):
value = generate()
if formatted:
sizes, separators = ([3,3,3,3], ['.','.','.']) if uf == 'SP' else ([3,3,3,4], ['.','.','/']) if uf == 'MG' else ([2,3,2,1], ['.','.','-'])
cursor, parts = 0, []
for index, size in enumerate(sizes):
parts.append(value[cursor:cursor + size]); cursor += size
if index < len(separators): parts.append(separators[index])
value = ''.join(parts)
if value not in values: values.append(value)
if len(values) == count: break
if len(values) != count: raise ValueError('Não foi possível completar o lote sem repetições')
return '\n'.join(values)
<?php
function executar($count = 1, $uf = 'SP', $formatted = true) {
if (!is_int($count) || $count < 1 || $count > 100) throw new InvalidArgumentException('Quantidade: de 1 a 100');
if (!is_bool($formatted)) throw new InvalidArgumentException('Máscara deve ser booleana');
$generate = function () use ($uf) {
$results = [];
$random_chars = function($n, $alphabet = "0123456789") use (&$random_chars, &$weighted_sum, &$dv) {
$value = "";
for ($i = 0; $i < $n; $i++) {
$value .= $alphabet[random_int(0, strlen($alphabet) - 1)];
}
return $value;
};
$weighted_sum = function($base, $weights, $alpha = false) use (&$random_chars, &$weighted_sum, &$dv) {
$sum = 0;
foreach (str_split($base) as $i => $c) {
$sum += ($alpha ? ord($c) - 48 : (int) $c) * $weights[$i];
}
return $sum;
};
$dv = function($base, $weights, $alpha = false) use (&$random_chars, &$weighted_sum, &$dv) {
$r = $weighted_sum($base, $weights, $alpha) % 11;
return $r < 2 ? 0 : 11 - $r;
};
// SP, MG ou RJ: regra geral.
if ($uf === "SP") {
$base = $random_chars(10);
$d1 = $weighted_sum(substr($base,0,8), [1,3,4,5,6,7,8,10]) % 11 % 10;
$partial = substr($base,0,8) . $d1 . substr($base,8);
$result = $partial . ($weighted_sum($partial, [3,2,10,9,8,7,6,5,4,3,2]) % 11 % 10);
} elseif ($uf === "MG") {
$base = "062" . $random_chars(6) . "00";
$expanded = substr($base,0,3) . "0" . substr($base,3);
$total = 0;
foreach (str_split($expanded) as $i => $c) {
$n = (int) $c * ($i % 2 + 1);
$total += intdiv($n,10) + $n % 10;
}
$d1 = (10 - $total % 10) % 10;
$result = $base . $d1 . $dv($base . $d1, [3,2,11,10,9,8,7,6,5,4,3,2]);
} elseif ($uf === "RJ") {
$base = $random_chars(7);
$result = $base . $dv($base, [2,7,6,5,4,3,2]);
} else { throw new Exception("UF não suportada"); }
$results[] = $result;
return count($results) === 1 ? $results[0] : $results;
};
$values = [];
for ($attempts = 0; count($values) < $count && $attempts < $count * 30; $attempts++) {
$value = $generate();
if ($formatted) {
[$sizes, $separators] = $uf === 'SP' ? [[3,3,3,3], ['.','.','.']] : ($uf === 'MG' ? [[3,3,3,4], ['.','.','/']] : [[2,3,2,1], ['.','.','-']]);
$cursor = 0; $parts = [];
foreach ($sizes as $index => $size) { $parts[] = substr($value,$cursor,$size); $cursor += $size; if (isset($separators[$index])) $parts[] = $separators[$index]; }
$value = implode('', $parts);
}
if (!in_array($value, $values, true)) $values[] = $value;
}
if (count($values) !== $count) throw new RuntimeException('Não foi possível completar o lote sem repetições');
return implode("\n", $values);
}