ZetCode

Perl crypt Function

last modified October 8, 2026

The Perl crypt function performs one-way hashing of a string. It is used, for example, to store and verify passwords.

crypt takes a plaintext string and a salt. The salt selects the hashing method and adds randomness to the result. The algorithms available depend on the platform's C library. Traditional DES salts are two characters long; salts starting with $1$, $5$ or $6$ select MD5, SHA-256 or SHA-512.

The crypt function is available on most systems, but it offers limited control over the hashing cost. For new projects, consider dedicated password modules such as Authen::Passphrase.

Basic crypt Usage

The simplest way to use crypt is with a plaintext and a two-character salt.

basic.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $password = "secret123";
my $salt = "ab";

my $encrypted = crypt($password, $salt);
say "Encrypted: $encrypted";

We encrypt a password with a two-character DES salt. The result starts with the salt itself. The same input and salt always produce the same output.

$ ./basic.pl
Encrypted: abhv/ZnAzL36k

Password Verification

crypt is commonly used to verify passwords against stored hashes. When the stored hash is passed as the salt, crypt reuses the salt portion of the hash, so the result can be compared with the stored value.

verify.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $stored_hash = 'abhv/ZnAzL36k';

for my $input_pass ('secret123', 'wrongpass') {
    if (crypt($input_pass, $stored_hash) eq $stored_hash) {
        say "$input_pass: Password correct";
    } else {
        say "$input_pass: Password incorrect";
    }
}

The script checks two passwords against the stored hash. Only the correct password produces an identical hash.

$ ./verify.pl
secret123: Password correct
wrongpass: Password incorrect

Salts and Randomness

For secure hashing, the salt should be random. The following script generates a random two-character DES salt from the characters allowed by crypt.

salt.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my @chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');

sub generate_salt {
    return join '', map { $chars[rand @chars] } 1..2;
}

my $password = "mypassword";
my $salt = generate_salt();
my $hash = crypt($password, $salt);

say "Salt: $salt";
say "Hash: $hash";

The salt is different on every run, so the hash changes as well. The output below is one example run; your values will differ.

$ ./salt.pl
Salt: eh
Hash: ehlLzM/oN1akA

MD5 Hashing

A salt that starts with $1$ selects MD5. The salt may be up to eight characters long after the prefix. This example uses a fixed salt so the output is reproducible.

md5.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $password = "pass1234";
my $salt = '$1$xyzabc$';

my $hash = crypt($password, $salt);
say "MD5 Hash: $hash";

The MD5 salt is written as $1$, the salt string, and a closing $. The result repeats the salt before the hash.

$ ./md5.pl
MD5 Hash: $1$xyzabc$80H3B27nopKrWsDT6SDKc.

SHA-256 and SHA-512 Hashing

A salt that starts with $5$ selects SHA-256, and $6$ selects SHA-512. These are generally stronger than MD5 and DES. Support depends on the C library of the system.

sha.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my $password = "supersecret";
my $salt = '$6$saltsalt$';

my $hash = crypt($password, $salt);
say "SHA-512 Hash: $hash";

The salt $6$saltsalt$ selects SHA-512 with the salt saltsalt. The output is a long string of 86 characters after the salt.

$ ./sha.pl
SHA-512 Hash: $6$saltsalt$Pfw1F93xLasHRKAEQEsTS8fexYKl9a4WC8wR5VtiqDmjnmgajzu0aPSvniRrM9Qjc/VbeIVqTilDiaJPo1Lob1

Simple Login Check

The following script reads a username and password from standard input and checks them against stored hashes. Hashes are computed with a fixed salt, so the example works without a database.

login.pl
#!/usr/bin/perl

use strict;
use warnings;
use v5.34.0;

my %users = (
    'admin' => '$6$saltsalt$Pfw1F93xLasHRKAEQEsTS8fexYKl9a4WC8wR5VtiqDmjnmgajzu0aPSvniRrM9Qjc/VbeIVqTilDiaJPo1Lob1',
    'user1' => '$1$xyzabc$80H3B27nopKrWsDT6SDKc.',
);

print "Username: ";
my $username = <STDIN>;
chomp $username;

print "Password: ";
my $password = <STDIN>;
chomp $password;

if (exists $users{$username} &&
    crypt($password, $users{$username}) eq $users{$username}) {
    say "Authentication successful";
} else {
    say "Authentication failed";
}

The stored hash of each user is used as the salt for the check. The script expects the username and password on separate lines of standard input.

$ printf 'user1\npass1234\n' | ./login.pl
Username: Password: Authentication successful

$ printf 'user1\nwrong\n' | ./login.pl
Username: Password: Authentication failed

Best Practices

Source

Perl crypt Documentation

This tutorial covered Perl's crypt function with examples of DES, MD5 and SHA-512 hashing and simple password verification.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Perl tutorials.