Secure Random String Generator in Every Programming Language
Every programming language has a way to generate cryptographically secure random strings, but the API differs wildly between languages. This is your copy-paste reference for generating secure API keys, tokens, and secrets in JavaScript, Python, Go, Rust, Java, C#, Ruby, PHP, Swift, and Kotlin.
Every example below uses a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) that draws from the operating system's entropy pool. None of them use insecure sources like Math.random(), rand(), or Random().
Quick Reference Table
| Language | CSPRNG Source | Module/Import |
|---|---|---|
| JavaScript | crypto.getRandomValues() | Built-in (Web Crypto API) |
| Node.js | crypto.randomBytes() | node:crypto |
| Python | secrets.token_hex() | secrets (stdlib) |
| Go | crypto/rand.Read() | crypto/rand |
| Rust | OsRng | rand crate |
| Java | SecureRandom | java.security |
| C# | RandomNumberGenerator | System.Security.Cryptography |
| Ruby | SecureRandom | securerandom (stdlib) |
| PHP | random_bytes() | Built-in (PHP 7+) |
| Swift | SecRandomCopyBytes | Security framework |
| Kotlin | SecureRandom | java.security |
JavaScript (Browser)
function secureRandomString(length = 32) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const bytes = new Uint8Array(length);
crypto.getRandomValues(bytes);
return Array.from(bytes, b => chars[b % chars.length]).join('');
}
// Hex variant
function secureRandomHex(bytes = 32) {
const buf = new Uint8Array(bytes);
crypto.getRandomValues(buf);
return Array.from(buf, b => b.toString(16).padStart(2, '0')).join('');
}
console.log(secureRandomString()); // "Kx9mR4vL2bN7qP5sT8wJ1cF6gH0iA3d"
console.log(secureRandomHex()); // "a3f8c1d9e4b7..."
Node.js
import { randomBytes } from 'node:crypto';
// Hex string
function secureRandomHex(bytes = 32) {
return randomBytes(bytes).toString('hex');
}
// Base64URL string
function secureRandomBase64URL(bytes = 32) {
return randomBytes(bytes).toString('base64url');
}
// Alphanumeric string
function secureRandomAlphanumeric(length = 32) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const bytes = randomBytes(length);
return Array.from(bytes, b => chars[b % chars.length]).join('');
}
console.log(secureRandomHex()); // 64-char hex string
console.log(secureRandomBase64URL()); // 43-char base64url string
console.log(secureRandomAlphanumeric()); // 32-char alphanumeric string
Python
import secrets
import string
# Hex string (simplest)
token = secrets.token_hex(32) # 64-char hex, 256 bits
# URL-safe Base64 string
token = secrets.token_urlsafe(32) # 43-char base64url, 256 bits
# Alphanumeric string
def secure_random_string(length=32):
alphabet = string.ascii_letters + string.digits
return ''.join(secrets.choice(alphabet) for _ in range(length))
print(secure_random_string()) # "Kx9mR4vL2bN7qP5sT8wJ1cF6gH0iA3d"
Always use the
secretsmodule in Python, neverrandom. Therandommodule uses a Mersenne Twister PRNG which is predictable and unsuitable for security.
Go
package main
import (
"crypto/rand"
"encoding/hex"
"fmt"
"math/big"
)
// Hex string
func secureRandomHex(byteLen int) string {
b := make([]byte, byteLen)
if _, err := rand.Read(b); err != nil {
panic(err)
}
return hex.EncodeToString(b)
}
// Alphanumeric string
func secureRandomString(length int) string {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
result := make([]byte, length)
for i := range result {
n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(chars))))
result[i] = chars[n.Int64()]
}
return string(result)
}
func main() {
fmt.Println(secureRandomHex(32)) // 64-char hex
fmt.Println(secureRandomString(32)) // 32-char alphanumeric
}
Go's crypto/rand reads from /dev/urandom on Unix and CryptGenRandom on Windows. Never use math/rand for security-sensitive operations — it is seeded with a predictable value.
Rust
use rand::Rng;
use rand::rngs::OsRng;
fn secure_random_hex(byte_len: usize) -> String {
let mut bytes = vec![0u8; byte_len];
OsRng.fill(&mut bytes[..]);
hex::encode(bytes)
}
fn secure_random_string(length: usize) -> String {
const CHARS: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let mut rng = OsRng;
(0..length)
.map(|_| {
let idx = rng.gen_range(0..CHARS.len());
CHARS[idx] as char
})
.collect()
}
fn main() {
println!("{}", secure_random_hex(32));
println!("{}", secure_random_string(32));
}
Add these to your Cargo.toml:
[dependencies]
rand = "0.8"
hex = "0.4"
Java
import java.security.SecureRandom;
import java.util.Base64;
public class SecureRandomGenerator {
private static final SecureRandom random = new SecureRandom();
private static final String CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// Hex string
public static String randomHex(int byteLength) {
byte[] bytes = new byte[byteLength];
random.nextBytes(bytes);
StringBuilder sb = new StringBuilder(byteLength * 2);
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
// Alphanumeric string
public static String randomString(int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(CHARS.charAt(random.nextInt(CHARS.length())));
}
return sb.toString();
}
// Base64URL string
public static String randomBase64URL(int byteLength) {
byte[] bytes = new byte[byteLength];
random.nextBytes(bytes);
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
}
}
Java's SecureRandom automatically selects the best available CSPRNG for the platform. On Linux, it uses /dev/urandom by default.
C# / .NET
using System.Security.Cryptography;
// .NET 6+ (recommended)
static string SecureRandomHex(int byteLength = 32)
{
byte[] bytes = RandomNumberGenerator.GetBytes(byteLength);
return Convert.ToHexString(bytes).ToLower();
}
static string SecureRandomString(int length = 32)
{
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
byte[] bytes = RandomNumberGenerator.GetBytes(length);
char[] result = new char[length];
for (int i = 0; i < length; i++)
{
result[i] = chars[bytes[i] % chars.Length];
}
return new string(result);
}
static string SecureRandomBase64URL(int byteLength = 32)
{
byte[] bytes = RandomNumberGenerator.GetBytes(byteLength);
return Convert.ToBase64String(bytes)
.Replace('+', '-')
.Replace('/', '_')
.TrimEnd('=');
}
Ruby
require 'securerandom'
# Hex string
token = SecureRandom.hex(32) # 64-char hex, 256 bits
# Base64URL string
token = SecureRandom.urlsafe_base64(32) # 43-char base64url
# Alphanumeric string
def secure_random_string(length = 32)
chars = [*'A'..'Z', *'a'..'z', *'0'..'9']
Array.new(length) { chars.sample(random: SecureRandom) }.join
end
puts secure_random_string # "Kx9mR4vL2bN7qP5sT8wJ1cF6gH0iA3d"
PHP
<?php
// Hex string (PHP 7+)
$token = bin2hex(random_bytes(32)); // 64-char hex, 256 bits
// Alphanumeric string
function secureRandomString(int $length = 32): string {
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$result = '';
$bytes = random_bytes($length);
for ($i = 0; $i < $length; $i++) {
$result .= $chars[ord($bytes[$i]) % strlen($chars)];
}
return $result;
}
// Base64URL string
function secureRandomBase64URL(int $byteLength = 32): string {
return rtrim(strtr(base64_encode(random_bytes($byteLength)), '+/', '-_'), '=');
}
echo secureRandomString(); // "Kx9mR4vL2bN7qP5sT8wJ1cF6gH0iA3d"
PHP's random_bytes() (PHP 7+) and random_int() use the OS CSPRNG. Never use mt_rand(), rand(), or uniqid() for security-sensitive strings.
Swift
import Foundation
import Security
func secureRandomHex(byteLength: Int = 32) -> String {
var bytes = [UInt8](repeating: 0, count: byteLength)
let status = SecRandomCopyBytes(kSecRandomDefault, byteLength, &bytes)
guard status == errSecSuccess else { fatalError("CSPRNG failed") }
return bytes.map { String(format: "%02x", $0) }.joined()
}
func secureRandomString(length: Int = 32) -> String {
let chars = Array("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
var bytes = [UInt8](repeating: 0, count: length)
SecRandomCopyBytes(kSecRandomDefault, length, &bytes)
return String(bytes.map { chars[Int($0) % chars.count] })
}
print(secureRandomHex()) // 64-char hex
print(secureRandomString()) // 32-char alphanumeric
Kotlin
import java.security.SecureRandom
fun secureRandomHex(byteLength: Int = 32): String {
val bytes = ByteArray(byteLength)
SecureRandom().nextBytes(bytes)
return bytes.joinToString("") { "%02x".format(it) }
}
fun secureRandomString(length: Int = 32): String {
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
val random = SecureRandom()
return (1..length)
.map { chars[random.nextInt(chars.length)] }
.joinToString("")
}
fun main() {
println(secureRandomHex()) // 64-char hex
println(secureRandomString()) // 32-char alphanumeric
}
Common Pitfalls Across All Languages
- Using the wrong random source. Every language has both a fast-but-insecure PRNG and a slower-but-secure CSPRNG. Use the CSPRNG for any security-sensitive operation.
- Modulo bias. Using
byte % charset_lengthintroduces slight bias when 256 is not evenly divisible by the charset length. For most API key use cases (charset of 62), the bias is negligible (< 0.4%). For maximum uniformity, use rejection sampling. - Insufficient length. Generate at least 16 bytes (128 bits of entropy) for any token used in production. 32 bytes (256 bits) is recommended.
- Logging the full key. Log only a prefix (first 4-8 characters) for debugging. Never log the complete key.
- Storing keys in plaintext. Hash keys with SHA-256 before storing in a database. Show the full key to the user exactly once at creation time.
Need a quick key without writing code? Use our free API key generator which supports hex, base64, base64url, alphanumeric, and prefixed formats.
Recommended Resources
For the cryptographic foundations behind every CSPRNG in this article, read Real-World Cryptography. It covers how entropy pools, PRNGs, and secure random generation work across operating systems.
For JavaScript-specific depth, JavaScript: The Definitive Guide is the standard reference. To understand how weak random generation gets exploited, The Web Application Hacker's Handbook covers real attack scenarios.