Creating Random Passwords in Zig
Creating strong, random passwords is a vital step for digital security, and the Zig programming language provides a concise and safe way to tackle this task. The provided program is a fantastic example of using the Zig standard library to generate a random string, which can serve as an excellent foundation for a password generator. The core logic revolves around setting up a character set, establishing a random number generator and iteratively selecting characters to build the final string.
const std = @import("std");
pub fn main() !void {
const gpa = std.heap.page_allocator;
var args = try std.process.argsWithAllocator(gpa);
defer args.deinit();
_ = args.next();
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const charsetLen = charset.len;
var stringLength: u32 = 16;
if (args.next()) |arg| {
stringLength = try std.fmt.parseInt(u32, arg, 10);
}
const seed = @as(u64, @intCast(std.time.nanoTimestamp()));
var prng = std.Random.DefaultPrng.init(seed);
const rand = prng.random();
const result = try gpa.alloc(u8, stringLength);
defer gpa.free(result);
for (result) |*ch| {
const index = rand.intRangeAtMost(u8, 0, charsetLen);
ch.* = charset[index];
}
std.debug.print("Random string: {s}\n", .{result});
}
The program starts by initializing the page allocator (gpa) from std.heap and processing command-line arguments using std.process.argsWithAllocator. This allows the user to specify the desired password length, which defaults to 16 characters if no argument is provided. The program handles this input robustly, using std.fmt.parseInt to convert the string argument into an unsigned 32-bit integer (u32).
Next, we define our character set (charset), which currently includes all lowercase and uppercase English letters. This is the pool of characters from which the random password will be constructed. For true password strength, this set should ideally be expanded to include numbers and symbols. The heart of the randomness comes from the Pseudo-Random Number Generator (PRNG). The program seeds the default PRNG (std.Random.DefaultPrng) using the current nanosecond timestamp from std.time.nanoTimestamp(). While convenient for this example, for truly cryptographically secure passwords, a dedicated secure random number generator should be used, but this implementation provides a good general-purpose solution.
Finally, the program allocates memory for the result using the gpa and then enters a loop. For each position in the output string (result), it uses the random number generator’s intRangeAtMost function to generate a random index within the bounds of the charset. The character at that random index is then assigned to the current position in the result string. A defer statement is used to ensure the allocated memory for result is properly freed, upholding Zig’s focus on resource management. The final random string is then printed to the console, demonstrating a simple yet effective random password generation utility.
Save the code as randomString.zig and use it:
$ zig run randomString.zig -- 8
Random string: qHkuNYPR
$ zig run randomString.zig -- 4
Random string: qcKQ
$ zig run randomString.zig -- 14
Random string: aMmlMAYvEUHnJ
Happy coding in Zig!