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

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...

Shell Script do Zero
Shell Script do Zero

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

SSH: Conectando e Gerenciando Servidores Remotos
SSH: Conectando e Gerenciando Servidores Remotos

SSH &mdash;&nbsp;Secure Shell &mdash; &eacute; o protocolo pelo qual administ...