DevOps

Geradores de Senhas Seguras: Implementações em 5 Linguagens de Programação Já leu

6 min de leitura

Geradores de Senhas Seguras: Implementações em 5 Linguagens de Programação
A geração de senhas fortes é um dos pilares da segurança da informação. Uma senha robusta deve conter letras maiúsculas, minúsculas, números e caracteres especi

A geração de senhas fortes é um dos pilares da segurança da informação. Uma senha robusta deve conter letras maiúsculas, minúsculas, números e caracteres especiais, com comprimento adequado (neste caso, 12 caracteres).

Neste artigo, apresentamos 15 implementações diferentes de geradores de senhas distribuídas em cinco linguagens populares: Go, Rust, JavaScript, PHP e Python. Para cada linguagem foram desenvolvidas três abordagens distintas, demonstrando diferentes técnicas e níveis de segurança:

  1. Abordagem simples – Seleção aleatória direta de um pool de caracteres.
  2. Abordagem com garantia de composição – Garante pelo menos um caractere de cada tipo.
  3. Abordagem criptograficamente segura – Utiliza geradores de números aleatórios criptográficos.

Go (Golang)

1. Seleção simples de um pool de caracteres

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())
	pool := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()"
	for i := 0; i < 5; i++ {
		password := ""
		for j := 0; j < 12; j++ {
			index := rand.Intn(len(pool))
			password += string(pool[index])
		}
		fmt.Println(password)
	}
}

2. Garantia de pelo menos um caractere de cada tipo

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano())
	upper := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	lower := "abcdefghijklmnopqrstuvwxyz"
	digit := "0123456789"
	special := "!@#$%^&*()"
	pool := upper + lower + digit + special

	for i := 0; i < 5; i++ {
		positions := rand.Perm(12)
		password := make([]byte, 12)
		password[positions[0]] = upper[rand.Intn(len(upper))]
		password[positions[1]] = lower[rand.Intn(len(lower))]
		password[positions[2]] = digit[rand.Intn(len(digit))]
		password[positions[3]] = special[rand.Intn(len(special))]

		for j := 0; j < 12; j++ {
			if password[j] == 0 {
				password[j] = pool[rand.Intn(len(pool))]
			}
		}
		fmt.Println(string(password))
	}
}

3. Versão criptograficamente segura com crypto/rand

package main

import (
	"crypto/rand"
	"fmt"
	"math/big"
)

func main() {
	pool := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()"
	poolLen := big.NewInt(int64(len(pool)))

	for i := 0; i < 5; i++ {
		password := ""
		for j := 0; j < 12; j++ {
			n, _ := rand.Int(rand.Reader, poolLen)
			password += string(pool[n.Int64()])
		}
		fmt.Println(password)
	}
}

Rust

1. Seleção simples com crate rand

use rand::Rng;

fn main() {
    let pool: Vec<char> = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()".chars().collect();
    let mut rng = rand::thread_rng();

    for _ in 0..5 {
        let mut password = String::new();
        for _ in 0..12 {
            let index = rng.gen_range(0..pool.len());
            password.push(pool[index]);
        }
        println!("{}", password);
    }
}

2. Garantia de composição com shuffle de posições

use rand::Rng;
use rand::seq::SliceRandom;

fn main() {
    let upper: Vec<char> = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars().collect();
    let lower: Vec<char> = "abcdefghijklmnopqrstuvwxyz".chars().collect();
    let digit: Vec<char> = "0123456789".chars().collect();
    let special: Vec<char> = "!@#$%^&*()".chars().collect();
    let pool: Vec<char> = upper.iter().chain(lower.iter()).chain(digit.iter()).chain(special.iter()).cloned().collect();
    let mut rng = rand::thread_rng();

    for _ in 0..5 {
        let mut indices: Vec<usize> = (0..12).collect();
        indices.shuffle(&mut rng);

        let mut password: Vec<char> = vec![' '; 12];
        password[indices[0]] = *rng.choose(&upper).unwrap();
        password[indices[1]] = *rng.choose(&lower).unwrap();
        password[indices[2]] = *rng.choose(&digit).unwrap();
        password[indices[3]] = *rng.choose(&special).unwrap();

        for i in 0..12 {
            if password[i] == ' ' {
                password[i] = *rng.choose(&pool).unwrap();
            }
        }
        println!("{}", password.into_iter().collect::<String>());
    }
}

3. Versão segura com OsRng

use rand::rngs::OsRng;
use rand::RngCore;

fn main() {
    let pool: Vec<u8> = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()".as_bytes().to_vec();
    let pool_len = pool.len() as u32;

    for _ in 0..5 {
        let mut password = String::new();
        let mut bytes = [0u8; 12];
        OsRng.fill_bytes(&mut bytes);
        for &byte in bytes.iter() {
            let index = (byte as u32 % pool_len) as usize;
            password.push(pool[index] as char);
        }
        println!("{}", password);
    }
}

JavaScript (Node.js)

1. Implementação simples

const pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()';

for (let i = 0; i < 5; i++) {
  let password = '';
  for (let j = 0; j < 12; j++) {
    const index = Math.floor(Math.random() * pool.length);
    password += pool[index];
  }
  console.log(password);
}

2. Com garantia de composição

const upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const lower = 'abcdefghijklmnopqrstuvwxyz';
const digit = '0123456789';
const special = '!@#$%^&*()';
const pool = upper + lower + digit + special;

for (let i = 0; i < 5; i++) {
  const positions = Array.from({length: 12}, (_, index) => index).sort(() => Math.random() - 0.5);
  let password = new Array(12);
  password[positions[0]] = upper[Math.floor(Math.random() * upper.length)];
  password[positions[1]] = lower[Math.floor(Math.random() * lower.length)];
  password[positions[2]] = digit[Math.floor(Math.random() * digit.length)];
  password[positions[3]] = special[Math.floor(Math.random() * special.length)];

  for (let j = 0; j < 12; j++) {
    if (password[j] === undefined) {
      password[j] = pool[Math.floor(Math.random() * pool.length)];
    }
  }
  console.log(password.join(''));
}

3. Versão com módulo crypto

const crypto = require('crypto');

for (let i = 0; i < 5; i++) {
  const randomBytes = crypto.randomBytes(9);
  let password = randomBytes.toString('base64').slice(0, 12);
  console.log(password);
}

PHP

1. Versão simples

<?php
$pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()';

for ($i = 0; $i < 5; $i++) {
    $password = '';
    for ($j = 0; $j < 12; $j++) {
        $index = rand(0, strlen($pool) - 1);
        $password .= $pool[$index];
    }
    echo $password . PHP_EOL;
}
?>

2. Com garantia de composição

<?php
$upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$lower = 'abcdefghijklmnopqrstuvwxyz';
$digit = '0123456789';
$special = '!@#$%^&*()';
$pool = $upper . $lower . $digit . $special;

for ($i = 0; $i < 5; $i++) {
    $positions = range(0, 11);
    shuffle($positions);
    $password = array_fill(0, 12, null);
    $password[$positions[0]] = $upper[rand(0, strlen($upper) - 1)];
    $password[$positions[1]] = $lower[rand(0, strlen($lower) - 1)];
    $password[$positions[2]] = $digit[rand(0, strlen($digit) - 1)];
    $password[$positions[3]] = $special[rand(0, strlen($special) - 1)];

    for ($j = 0; $j < 12; $j++) {
        if ($password[$j] === null) {
            $password[$j] = $pool[rand(0, strlen($pool) - 1)];
        }
    }
    echo implode('', $password) . PHP_EOL;
}
?>

3. Versão segura com random_bytes

<?php
$pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()';

for ($i = 0; $i < 5; $i++) {
    $password = '';
    $bytes = random_bytes(12);
    for ($j = 0; $j < 12; $j++) {
        $index = ord($bytes[$j]) % strlen($pool);
        $password .= $pool[$index];
    }
    echo $password . PHP_EOL;
}
?>

Python

1. Versão simples com random

import random

pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()'

for _ in range(5):
    password = ''.join(random.choice(pool) for _ in range(12))
    print(password)

2. Com garantia de composição

import random

upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
lower = 'abcdefghijklmnopqrstuvwxyz'
digit = '0123456789'
special = '!@#$%^&*()'
pool = upper + lower + digit + special

for _ in range(5):
    positions = random.sample(range(12), 4)
    password = [''] * 12
    password[positions[0]] = random.choice(upper)
    password[positions[1]] = random.choice(lower)
    password[positions[2]] = random.choice(digit)
    password[positions[3]] = random.choice(special)

    for i in range(12):
        if not password[i]:
            password[i] = random.choice(pool)
    print(''.join(password))

3. Versão segura com módulo secrets (recomendada)

import secrets

pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()'

for _ in range(5):
    password = ''.join(secrets.choice(pool) for _ in range(12))
    print(password)

Conclusão e Melhores Práticas

  • Em produção, sempre prefira geradores criptograficamente seguros (crypto/rand no Go, OsRng no Rust, crypto no Node.js, random_bytes no PHP e secrets no Python).
  • Evite Math.random() e rand padrão em aplicações sensíveis.
  • Considere o uso de gerenciadores de senhas ou APIs de password hashing (Argon2, bcrypt).
  • Para maior segurança, aumente o comprimento para 16+ caracteres e inclua mais variedade de caracteres especiais.

Este conjunto de exemplos serve como base sólida para desenvolvedores que precisam implementar geradores de senhas em diferentes ecossistemas.

Comentários

Mais em DevOps

Shell Script do Zero
Shell Script do Zero

At&eacute; aqui foram aprendidos comandos que se executam um de cada vez. She...

Estudar e realmente Aprender DevOps & Cloud
Estudar e realmente Aprender DevOps & Cloud

Existe um momento na carreira de todo desenvolvedor em que o c&oacute;digo fu...

Boas Práticas de Imagens: Leveza, Segurança e Camadas
Boas Práticas de Imagens: Leveza, Segurança e Camadas

Nos artigos anteriores foram constru&iacute;das imagens funcionais. Uma image...