Skip to content

Commit 78b714f

Browse files
committed
Add Perl 5 example
1 parent a1cd644 commit 78b714f

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

Perl/SCEE.pl

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
2+
use Crypt::PRNG qw(random_bytes);
3+
use Crypt::KeyDerivation qw(pbkdf2);
4+
use MIME::Base64 qw(encode_base64 decode_base64);
5+
6+
7+
use constant ALGORITHM_NONCE_SIZE => 12;
8+
use constant ALGORITHM_TAG_SIZE => 16;
9+
use constant ALGORITHM_KEY_SIZE => 16;
10+
use constant PBKDF2_SALT_SIZE => 16;
11+
use constant PBKDF2_ITERATIONS => 32767;
12+
use constant PBKDF2_NAME => "SHA256";
13+
14+
15+
sub encrypt_string {
16+
my ($plaintext, $password) = @_;
17+
18+
# Generate a 128-bit salt using a CSPRNG.
19+
my $salt = random_bytes(PBKDF2_SALT_SIZE);
20+
21+
# Derive a key.
22+
my $key = pbkdf2($password, $salt, PBKDF2_ITERATIONS, PBKDF2_NAME, ALGORITHM_KEY_SIZE);
23+
24+
# Encrypt and prepend salt and return as base64 string.
25+
return encode_base64($salt . encrypt($plaintext, $key), '');
26+
}
27+
28+
sub decrypt_string {
29+
my ($base64CiphertextAndNonceAndSalt, $password) = @_;
30+
31+
# Decode the base64.
32+
my $ciphertextAndNonceAndSalt = decode_base64($base64CiphertextAndNonceAndSalt);
33+
34+
# Retrieve the salt and ciphertextAndNonce.
35+
my ($salt, $ciphertextAndNonce) = unpack("a" . PBKDF2_SALT_SIZE . "a*", $ciphertextAndNonceAndSalt);
36+
37+
# Derive the key.
38+
my $key = pbkdf2($password, $salt, PBKDF2_ITERATIONS, PBKDF2_NAME, ALGORITHM_KEY_SIZE);
39+
40+
# Decrypt and return result.
41+
return decrypt($ciphertextAndNonce, $key);
42+
}
43+
44+
sub encrypt {
45+
my ($plaintext, $key) = @_;
46+
47+
# Generate a 96-bit nonce using a CSPRNG.
48+
my $nonce = random_bytes(ALGORITHM_NONCE_SIZE);
49+
50+
# Encrypt and prepend nonce.
51+
my ($ciphertext, $tag) = gcm_encrypt_authenticate('AES', $key, $nonce, '', $plaintext);
52+
die "Invalid tag size" unless length $tag == ALGORITHM_TAG_SIZE;
53+
my $ciphertextAndNonce = $nonce . $ciphertext . $tag;
54+
55+
return $ciphertextAndNonce;
56+
}
57+
58+
sub decrypt {
59+
my ($ciphertextAndNonce, $key) = @_;
60+
61+
# Retrieve the nonce and ciphertext.
62+
my ($nonce, $ciphertext, $tag) = unpack("a" . ALGORITHM_NONCE_SIZE .
63+
"a" . (length($ciphertextAndNonce) - ALGORITHM_NONCE_SIZE - ALGORITHM_TAG_SIZE) .
64+
"a" . ALGORITHM_TAG_SIZE, $ciphertextAndNonce);
65+
66+
# Decrypt and return result.
67+
my $plaintext = gcm_decrypt_verify('AES', $key, $nonce, '', $ciphertext, $tag);
68+
69+
return $plaintext;
70+
}
71+
72+
73+
1;

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ compatible.
5454
|Rust|v1.30.0|Requires the ring v0.13.2 and base64 v0.9.3 crates||
5555
|Swift|Swift 4.0|Requires [SwiftGCM](https://github.com/luke-park/SwiftGCM).|Must use a bridge for CommonCrypto.|
5656
|PHP|Requires PHP 7||Uses `random_bytes` which requires PHP 7.|
57+
|Perl|Perl 5|Requires [CryptX](https://metacpan.org/pod/CryptX)||
5758

5859
## Test Vectors
5960
The following ciphertexts are the results of `encryptString` using the given password. If your implementation can `encryptString` and `decryptString` using the code you've written, and can also `decryptString` the ciphertexts below to the same given result, then it is suitable for inclusion in this repository. Recall that, due to a randomly generated salt and nonce, the following are not expected outputs for `encryptString`, they are for testing `decryptString` only.

0 commit comments

Comments
 (0)