Generating passwords with SecureRandom
SecureRandom is a module in Ruby's standard gems that provides methods for generating random numbers and strings suitable for security-sensitive applications.
My most frequented methods in this module are hex and alphanumeric, which generate random strings of a specified length. Great for generating random tokens and passwords.
require "securerandom"
# Generate a random hexadecimal string of length 32
SecureRandom.hex(16)
# => "4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a"
# Generate a random alphanumeric string of length 32
SecureRandom.alphanumeric(32)
# => "Jiw8KLgMSd0A6SXlnvxFNGfazovbrAD9"
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
[...bytes]
.map((byte) => byte.toString(16).padStart(2, "0"))
.join("");
// => "4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a"
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
function randomAlphanumeric(length) {
const result = [];
while (result.length < length) {
const bytes = new Uint8Array(length);
crypto.getRandomValues(bytes);
for (const byte of bytes) {
// Avoid modulo bias: 62 * 4 = 248, so accept only 0-247
if (byte < 248) {
result.push(chars[byte % chars.length]);
if (result.length === length) break;
}
}
}
return result.join("");
}
randomAlphanumeric(32);
// => "Jiw8KLgMSd0A6SXlnvxFNGfazovbrAD9"
Now you may be asking, shouldn't we make sure to have special characters in our passwords?
I'm here to tell you no! No special characters!
You want your credentials to be easily copy-pastable. That includes double-clicking on a piece of text in your terminal or wherever and having the whole password selected, and we all know how well that goes with special characters in there, don't we.
You also don't want to have to worry about escaping special characters when using the password in a shell command or as userinfo in a URL, and yes you DO want to use basic-auth for your API authentication, not some custom X-Api-Token header nonsense. Authenticated HTTP URLs can be copy-pastable as well, you know.
Thank you for attending my TED talk 🙏
History
SecureRandom landed in Ruby version 1.8.7 in 2008 and has seen quite a few additions since then, including:
- uuid and urlsafe_base64 in Ruby 1.9.2, released in 2010.
- bytes in Ruby 2.4, released in 2015.
- alphanumeric in Ruby 2.5, released in 2016.