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:
- Abordagem simples – Seleção aleatória direta de um pool de caracteres.
- Abordagem com garantia de composição – Garante pelo menos um caractere de cada tipo.
- 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/randno Go,OsRngno Rust,cryptono Node.js,random_bytesno PHP esecretsno Python). - Evite
Math.random()erandpadrã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.