Crypt-NaCl-Sodium

 view release on metacpan or  search on metacpan

t/sodium_aead_aes256gcm.t  view on Meta::CPAN


    for my $test ( @tests ) {
        my ($key_hex,
            $nonce_hex,
            $msg_hex,
            $ad_hex,
            $expected_ciphertext_hex,
            $expected_mac_hex
         ) = @$test;

        my $key = hex2bin($key_hex);
        my $nonce = hex2bin($nonce_hex);
        my $msg = hex2bin($msg_hex);
        my $ad = hex2bin($ad_hex);

        is(length($key_hex), 2 * $crypto_aead->AES256GCM_KEYBYTES, "key for $test_no is correct length");
        is(length($nonce_hex), 2 * $crypto_aead->AES256GCM_NPUBBYTES, "nonce for $test_no is correct length");
        is(length($expected_mac_hex), 2 * $crypto_aead->AES256GCM_ABYTES, "additional data for $test_no is correct length");

        $expected_ciphertext_hex .= $expected_mac_hex; 

        my $precal_key = $crypto_aead->aes256gcm_beforenm($key);
        isa_ok($precal_key, "Crypt::NaCl::Sodium::aead::aes256gcmstate");

        my $ciphertext = $crypto_aead->aes256gcm_encrypt($msg, $ad, $nonce, $key);
        is($ciphertext->to_hex, $expected_ciphertext_hex, "ciphertext is as expected: $expected_ciphertext_hex");

        my $ciphertext2 = $crypto_aead->aes256gcm_encrypt_afternm($msg, $ad, $nonce, $precal_key);
        is($ciphertext2->to_hex, $expected_ciphertext_hex, "ciphertext (using precalculated key) is as expected");

        if ( $ciphertext->length > $crypto_aead->AES256GCM_ABYTES ) {
            # at least AES256GCM_ABYTES
            my $t_len = $crypto_aead->AES256GCM_ABYTES + random_number($ciphertext->length - $crypto_aead->AES256GCM_ABYTES);
            eval {
                my $d = $crypto_aead->aes256gcm_decrypt(
                    substr($ciphertext->bytes, 0, $t_len), $ad, $nonce, $key
                );
            };
            like($@, qr/Message forged/, "Cannot decrypt truncated ciphertext");
        }

        eval {
            my $d = $crypto_aead->aes256gcm_decrypt(
                substr($ciphertext->bytes, 0, random_number($crypto_aead->AES256GCM_ABYTES)), $ad, $nonce, $key
            );
        };
        like($@, qr/Invalid ciphertext/, "Cannot decrypt too short ciphertext");

        my $decrypted = $crypto_aead->aes256gcm_decrypt($ciphertext->bytes, $ad, $nonce, $key);
        is($decrypted->to_hex, $msg_hex, "message decrypted");

        my $decrypted2 =
        $crypto_aead->aes256gcm_decrypt_afternm($ciphertext->bytes, $ad, $nonce, $precal_key);
        is($decrypted2->to_hex, $msg_hex, "message decrypted (using precalculated key)");

        $test_no++;
    }

    my $key = "\0" x $crypto_aead->AES256GCM_KEYBYTES;
    my $precal_key = $crypto_aead->aes256gcm_beforenm($key);
    can_ok($precal_key, $_) for qw( lock unlock is_locked );

    my $ad = "Shoppping list";
    my $msg = "Milk";
    my $nonce = "\0" x $crypto_aead->AES256GCM_NPUBBYTES;

    ok(! $precal_key->is_locked, "precalculated key is not locked by default");
    my $ciphertext = $crypto_aead->aes256gcm_encrypt_afternm($msg, $ad, $nonce,
        $precal_key);
    is($ciphertext->to_hex, "83ce2c56bf10b9385d1f80e635a26b3c1d1c72b7", "can encrypt with unlocked precalculated key");
    my $decrypted = 
        $crypto_aead->aes256gcm_decrypt_afternm($ciphertext->bytes, $ad, $nonce, $precal_key);
    is($decrypted->bytes, $msg, "message decrypted (using unlocked precalculated key)");

    ok($precal_key->lock, "and lock the precalculated key");
    ok($precal_key->is_locked, "...and confirm it using is_locked()");

    eval {
        my $tmp = $crypto_aead->aes256gcm_encrypt_afternm($msg, $ad, $nonce,
            $precal_key);
    };
    like($@, qr/Unlock AES256GCM precalculated key object before accessing the state/,
        "...and cannot encrypt using locked precalculated key anymore");

    eval {
        my $tmp = 
            $crypto_aead->aes256gcm_decrypt_afternm($ciphertext->bytes, $ad, $nonce, $precal_key);
    };
    like($@, qr/Unlock AES256GCM precalculated key object before accessing the state/,
        "...and cannot decrypt using locked precalculated key anymore");

    ok($precal_key->unlock, "but can unlock the precalculated key");
    ok(! $precal_key->is_locked, "...and confirm it using is_locked()");

    my $decrypted2 = 
        $crypto_aead->aes256gcm_decrypt_afternm($ciphertext->bytes, $ad, $nonce, $precal_key);
    is($decrypted2->bytes, $msg, "to decrypted the message (using unlocked precalculated key)");
 
}

SKIP: {
    skip "AES256GCM is available", 1 if $is_available;

	my @noargs_methods = qw(
		AES256GCM_KEYBYTES
		AES256GCM_NPUBBYTES
		AES256GCM_ABYTES
		aes256gcm_keygen
		aes256gcm_nonce
	);
	for my $m ( @noargs_methods ) {
		eval {
			$crypto_aead->$m();
		};
		like($@, qr/AES256-GCM is not supported by this CPU/, "$m is not available");
	}

	eval {
		my $ciphertext = $crypto_aead->aes256gcm_encrypt("msg", "", "\0", "\0");
	};
	like($@, qr/AES256-GCM is not supported by this CPU/, "aes256gcm_encrypt is not available");


	eval {
		my $plain = $crypto_aead->aes256gcm_decrypt("ciphertext", "", "\0", "\0");
	};
	like($@, qr/AES256-GCM is not supported by this CPU/, "aes256gcm_decrypt is not available");


	eval {
		my $precal_key = $crypto_aead->aes256gcm_beforenm("\0");
	};
	like($@, qr/AES256-GCM is not supported by this CPU/, "aes256gcm_beforenm is not available");


	eval {
		my $ciphertext = $crypto_aead->aes256gcm_encrypt_afternm("msg", "", "\0", "\0");
	};
	like($@, qr/AES256-GCM is not supported by this CPU/, "aes256gcm_encrypt_afternm is not available");


	eval {
		my $plain = $crypto_aead->aes256gcm_decrypt_afternm("ciphertext", "", "\0", "\0");
	};
	like($@, qr/AES256-GCM is not supported by this CPU/, "aes256gcm_decrypt_afternm is not available");

}


done_testing();



( run in 2.588 seconds using v1.01-cache-2.11-cpan-364913b4093 )