diff --git a/docs/utils/cnsValidator.md b/docs/utils/cnsValidator.md
new file mode 100644
index 0000000..ee30370
--- /dev/null
+++ b/docs/utils/cnsValidator.md
@@ -0,0 +1,74 @@
+# CnsValidator
+
+Utilitário para validar CNS com e sem máscara.
+
+## Instalação e Importação
+
+```typescript
+import { cnsValidator } from '@sysvale/foundry';
+```
+
+## Função
+
+### `cnsValidator()`
+
+Valida CNS com e sem máscara, indicando se os mesmos são válidos.
+
+#### Sintaxes
+
+```typescript
+cnsValidator(value: string): boolean
+```
+
+#### Parâmetros
+
+**Assinatura 1:**
+
+- **`value`** (`string`): CNS (com ou sem máscara) a ser validado
+
+
+
+#### Retorno
+
+`boolean` - Resultado da validação, `true` para CNS válido e `false` para inválido
+
+
+
+#### Exemplos
+
+**Usando CNS com máscara:**
+
+```typescript
+cnsValidator('728 1376 2535 3587'); // → true
+
+cnsValidator('111 1111 1111 1111'); // → false
+```
+
+
+
+**Usando CNS sem máscara:**
+
+```typescript
+cnsValidator('728137625353587'); // → true
+
+cnsValidator('111111111111111'); // → false
+```
+
+
+
+#### Tratamento de Erros
+
+A função lança um erro quando os parâmetros obrigatórios não são fornecidos:
+
+```typescript
+// ❌ Erro: tipagem do parâmetro é inválida
+cnsValidator(728137625353587);
+// → Error: O tipo do parâmetro passado é inválido.
+
+// ✅ Correto
+cnsValidator('728137625353587');
+```
+
+## Notas
+
+- A função é **type-safe**
diff --git a/docs/utils/index.md b/docs/utils/index.md
index c15b6b9..1db465b 100644
--- a/docs/utils/index.md
+++ b/docs/utils/index.md
@@ -23,3 +23,9 @@ Função para sanitizar dados de formulário e aplicar transformações antes de
Função para validar CPFs com e sem máscara.
- [Documentação](./cpfValidator.md)
+
+### cnsValidator()
+
+Função para validar CNS com e sem máscara.
+
+- [Documentação](./cnsValidator.md)
diff --git a/package.json b/package.json
index 9ce040e..8c70325 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@sysvale/foundry",
- "version": "1.6.0",
+ "version": "1.7.0",
"description": "A forge for composables, helpers, and front-end utilities.",
"type": "module",
"main": "./dist/foundry.cjs.js",
diff --git a/src/index.ts b/src/index.ts
index d4501ee..92d318e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,6 +2,7 @@ export * from './utils/pluralize';
export * from './utils/commaline';
export * from './utils/sanitizeForm';
export * from './utils/cpfValidator';
+export * from './utils/cnsValidator';
export { maskCpf, removeCpfMask } from './formatters/cpf';
export { maskCns, removeCnsMask } from './formatters/cns';
export { maskPhone, removePhoneMask } from './formatters/phone';
diff --git a/src/utils/cnsValidator.ts b/src/utils/cnsValidator.ts
new file mode 100644
index 0000000..5f5961e
--- /dev/null
+++ b/src/utils/cnsValidator.ts
@@ -0,0 +1,128 @@
+function checkCnsValue(value: string) {
+ let pis;
+ let rest;
+ let sum;
+
+ pis = value.substring(0, 15);
+
+ if (pis === '') {
+ return false;
+ }
+
+ if (
+ value.substring(0, 1) !== '7' &&
+ value.substring(0, 1) !== '8' &&
+ value.substring(0, 1) !== '9'
+ ) {
+ return false;
+ }
+
+ sum =
+ parseInt(pis.substring(0, 1), 10) * 15 +
+ parseInt(pis.substring(1, 2), 10) * 14 +
+ parseInt(pis.substring(2, 3), 10) * 13 +
+ parseInt(pis.substring(3, 4), 10) * 12 +
+ parseInt(pis.substring(4, 5), 10) * 11 +
+ parseInt(pis.substring(5, 6), 10) * 10 +
+ parseInt(pis.substring(6, 7), 10) * 9 +
+ parseInt(pis.substring(7, 8), 10) * 8 +
+ parseInt(pis.substring(8, 9), 10) * 7 +
+ parseInt(pis.substring(9, 10), 10) * 6 +
+ parseInt(pis.substring(10, 11), 10) * 5 +
+ parseInt(pis.substring(11, 12), 10) * 4 +
+ parseInt(pis.substring(12, 13), 10) * 3 +
+ parseInt(pis.substring(13, 14), 10) * 2 +
+ parseInt(pis.substring(14, 15), 10) * 1;
+
+ rest = sum % 11;
+
+ if (!rest) {
+ return true;
+ }
+
+ return false;
+}
+
+function checkCnsFirstElevenDigits(value: string) {
+ let sum = 0;
+ let rest = 0;
+ let validatorDigit = 0;
+ let pis = '';
+ let result = '';
+ const cnsSize = value.length;
+
+ if (cnsSize !== 15) {
+ return false;
+ }
+
+ pis = value.substring(0, 11);
+ sum =
+ Number(pis.substring(0, 1)) * 15 +
+ Number(pis.substring(1, 2)) * 14 +
+ Number(pis.substring(2, 3)) * 13 +
+ Number(pis.substring(3, 4)) * 12 +
+ Number(pis.substring(4, 5)) * 11 +
+ Number(pis.substring(5, 6)) * 10 +
+ Number(pis.substring(6, 7)) * 9 +
+ Number(pis.substring(7, 8)) * 8 +
+ Number(pis.substring(8, 9)) * 7 +
+ Number(pis.substring(9, 10)) * 6 +
+ Number(pis.substring(10, 11)) * 5;
+ rest = sum % 11;
+ validatorDigit = 11 - rest;
+
+ if (validatorDigit === 11) {
+ validatorDigit = 0;
+ }
+
+ if (validatorDigit === 10) {
+ sum =
+ Number(pis.substring(0, 1)) * 15 +
+ Number(pis.substring(1, 2)) * 14 +
+ Number(pis.substring(2, 3)) * 13 +
+ Number(pis.substring(3, 4)) * 12 +
+ Number(pis.substring(4, 5)) * 11 +
+ Number(pis.substring(5, 6)) * 10 +
+ Number(pis.substring(6, 7)) * 9 +
+ Number(pis.substring(7, 8)) * 8 +
+ Number(pis.substring(8, 9)) * 7 +
+ Number(pis.substring(9, 10)) * 6 +
+ Number(pis.substring(10, 11)) * 5 +
+ 2;
+ rest = sum % 11;
+ validatorDigit = 11 - rest;
+ result = `${pis}001${String(validatorDigit)}`;
+ } else {
+ result = `${pis}000${String(validatorDigit)}`;
+ }
+
+ if (value !== result) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Valida CNS com e sem máscara.
+ *
+ * @param { string } value
+ * @returns { boolean }
+ */
+export function cnsValidator(value: string) {
+ if (typeof value !== 'string') {
+ throw new Error('O tipo do parâmetro passado é inválido.');
+ }
+
+ const unmaskedValue = value.replace(/\D/g, '');
+
+ if (unmaskedValue.length !== 15) {
+ return false;
+ }
+
+ if ([1, 2].indexOf(parseInt(unmaskedValue.substring(0, 1))) != -1) {
+ return checkCnsFirstElevenDigits(unmaskedValue);
+ }
+
+ return checkCnsValue(unmaskedValue);
+}
diff --git a/tests/cnsValidator.test.ts b/tests/cnsValidator.test.ts
new file mode 100644
index 0000000..be7fe35
--- /dev/null
+++ b/tests/cnsValidator.test.ts
@@ -0,0 +1,40 @@
+import { describe, expect, test } from 'vitest';
+import { cnsValidator } from '../src/utils/cnsValidator';
+
+describe('cnsValidator()', () => {
+ test('retorna false quando string vazia é passada', () => {
+ expect(cnsValidator('')).toBe(false);
+ });
+
+ test('retorna false quando cns inválido com máscara é passado', () => {
+ expect(cnsValidator('111 1111 1111 1111')).toBe(false);
+ });
+
+ test('retorna true quando cns válido com máscara é passado', () => {
+ expect(cnsValidator('728 1376 2535 3587')).toBe(true);
+ });
+
+ test('retorna false quando cns inválido sem máscara é passado', () => {
+ expect(cnsValidator('111111111111111')).toBe(false);
+ });
+
+ test('retorna true quando cns válido sem máscara é passado', () => {
+ expect(cnsValidator('728137625353587')).toBe(true);
+ });
+
+ test('retorna false quando cns possui menos que 15 dígitos', () => {
+ expect(cnsValidator('11111111111')).toBe(false);
+ });
+
+ test('retorna false quando cns possui mais que 15 dígitos', () => {
+ expect(cnsValidator('7281376253535879')).toBe(false);
+ });
+
+ test('retorna false quando cns possui uma letra', () => {
+ expect(cnsValidator('11111111111111a')).toBe(false);
+ });
+
+ test('lança erro quando parâmetro é do tipo number', () => {
+ expect(() => cnsValidator(12341789324)).toThrowError();
+ });
+});