Crypt-OPAQUE
view release on metacpan or search on metacpan
=head1 NAME
L<Crypt::OPAQUE>
=head2 PROTOCOL
L<https://datatracker.ietf.org/doc/draft-irtf-cfrg-opaque/>
=head1 FUNCTION
=head2 create_cleartext_credentials
my $cleartext_credentials = create_cleartext_credentials($s_pub, $c_pub, $s_id, $c_id);
=head2 store
my $store_r = store($randomized_pwd, $s_pub, $s_id, $c_id, $Nn, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func, $mac_func);
=head2 recover
my $recover_r = recover($randomized_pwd, $s_pub, $envelope, $s_id, $c_id, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func, $mac_func);
=head2 create_registration_request
my $randomize_pwd = derive_random_pwd($ec_params, $pwd, $blind, $evaluate_element, $hash_name, $harden_func);
=head2 create_credential_request
my $cred_req_r = create_credential_request($request, $s_pub, $oprf_seed, $credential_identifier, $DSI, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func, $point_compress_t);
=head2 create_credential_response
my $cred_res_r = create_credential_response($request, $s_pub, $oprf_seed, $credential_identifier, $DSI, $envelope, $masking_key, $Nn, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func, $point_compress_t, $pack_func);
=head2 recover_credentials
my $recover_r = recover_credentials($cred_request, $cred_response, $pwd, $c_id, $s_id, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func, $mac_func, $pwd_harden_func, $unpack_func);
=cut
lib/Crypt/OPAQUE.pm view on Meta::CPAN
use Crypt::OpenSSL::Bignum;
use Crypt::OpenSSL::ECDSA;
use Crypt::OPRF;
#use Smart::Comments;
our $VERSION = 0.012;
our @ISA = qw(Exporter);
our @EXPORT = qw/
create_cleartext_credentials
store
recover
create_registration_request
create_registration_response
finalize_registration_request
derive_random_pwd
create_credential_request
create_credential_response
recover_credentials
/;
our @EXPORT_OK = @EXPORT;
sub recover_credentials {
my (
$cred_request, $cred_response, $pwd, $c_id, $s_id, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func,
$mac_func, $pwd_harden_func, $unpack_func
) = @_;
my $evaluate_element = hex2point( $cred_request->{ec_params}{name}, unpack( "H*", $cred_response->{Z} ) );
my $randomized_pwd =
derive_random_pwd( $cred_request->{ec_params}, $pwd, $cred_request->{blind}, $evaluate_element, $hash_name, $pwd_harden_func );
### randomized_pwd: unpack("H*", $randomized_pwd)
lib/Crypt/OPAQUE.pm view on Meta::CPAN
my $recover_r = recover(
$randomized_pwd, $s_pub, $envelope, $s_id, $c_id, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func,
$mac_func
);
$recover_r->{s_pub} = $s_pub;
### recover s_pub: unpack("H*", $s_pub)
### recover c_priv: $recover_r->{c_priv}->to_hex
### recover export_key: unpack("H*", $recover_r->{export_key})
return $recover_r;
} ## end sub recover_credentials
sub create_credential_response {
my (
$request, $s_pub, $oprf_seed, $credential_identifier, $DSI, $envelope, $masking_key, $Nn, $Nseed, $group_name, $info, $DST,
$hash_name, $expand_message_func, $point_compress_t, $pack_func
) = @_;
### blindElement: unpack("H*", $request->{data})
### s_pub: unpack("H*", $s_pub)
### oprf_seed: unpack("H*", $oprf_seed)
### $credential_identifier
lib/Crypt/OPAQUE.pm view on Meta::CPAN
( $blind, $blindedElement ) =
blind( $pwd, $blind, $DSI, $group_name, $type, $hash_name, $expand_message_func, $clear_cofactor_flag );
my $ec_params = get_ec_params( $group_name );
#my $blindedElement_hex = sn_point2hex( $group_name, $blindedElement, 2 );
my $blindedElement_hex = Crypt::OpenSSL::EC::EC_POINT::point2hex($ec_params->{group}, $blindedElement, 2, $ec_params->{ctx});
my $request = { data => pack( "H*", $blindedElement_hex ) };
return { request => $request, blind => $blind, ec_params => $ec_params };
}
sub create_cleartext_credentials {
my ( $s_pub, $c_pub, $s_id, $c_id ) = @_;
$s_id //= $s_pub;
$c_id //= $c_pub;
my $cleartext_credentials = join(
"", $s_pub,
map { i2osp( length( $_ ), 2 ) . $_ } ( $s_id, $c_id ) );
return $cleartext_credentials;
}
sub store {
my ( $randomized_pwd, $s_pub, $s_id, $c_id, $Nn, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func, $mac_func ) =
@_;
my $envelope_nonce_bn = ( ref( $Nn ) eq 'Crypt::OpenSSL::Bignum' ) ? $Nn : random_bn( $Nn );
my $envelope_nonce = $envelope_nonce_bn->to_bin;
my $hash_func = EVP_get_digestbyname( $hash_name );
lib/Crypt/OPAQUE.pm view on Meta::CPAN
### auth_key: unpack("H*", $auth_key)
my $seed = Crypt::KeyDerivation::hkdf_expand( $randomized_pwd, $hash_name, $Nseed, $envelope_nonce . "PrivateKey" );
### seed: unpack("H*", $seed)
my $c_ec_key_r = derive_key_pair( $group_name, $seed, $info, $DST, $hash_name, $expand_message_func );
my $c_priv = $c_ec_key_r->{priv_bn};
my $c_pub = $c_ec_key_r->{pub_bin};
### c_priv: $c_priv->to_hex
my $cleartext_credentials = create_cleartext_credentials( $s_pub, $c_pub, $s_id, $c_id );
### cleartext_credentails: unpack("H*", $cleartext_credentials)
my $auth_tag = $mac_func->( $envelope_nonce . $cleartext_credentials, $auth_key );
my $envelope = { auth_tag => $auth_tag, nonce => $envelope_nonce };
return {
envelope => $envelope, c_pub => $c_pub, masking_key => $masking_key,
export_key => $export_key,
c_priv => $c_priv, auth_key => $auth_key,
cleartext_credentails => $cleartext_credentials,
};
} ## end sub store
sub recover {
my (
$randomized_pwd, $s_pub, $envelope, $s_id, $c_id, $Nseed, $group_name, $info, $DST, $hash_name, $expand_message_func,
$mac_func
) = @_;
my $hash_func = EVP_get_digestbyname( $hash_name );
lib/Crypt/OPAQUE.pm view on Meta::CPAN
### export_key: unpack("H*", $export_key)
my $seed = Crypt::KeyDerivation::hkdf_expand( $randomized_pwd, $hash_name, $Nseed, $envelope->{nonce} . "PrivateKey" );
### seed: unpack("H*", $seed)
my $c_ec_key_r = derive_key_pair( $group_name, $seed, $info, $DST, $hash_name, $expand_message_func );
my $c_priv = $c_ec_key_r->{priv_bn};
my $c_pub = $c_ec_key_r->{pub_bin};
### c_priv: $c_priv->to_hex
my $cleartext_credentials = create_cleartext_credentials( $s_pub, $c_pub, $s_id, $c_id );
my $expected_tag = $mac_func->( $envelope->{nonce} . $cleartext_credentials, $auth_key );
if ( $envelope->{auth_tag} ne $expected_tag ) {
croak "not match envelope.auth_tag";
}
return {
export_key => $export_key,
c_priv => $c_priv,
c_ec_key_r => $c_ec_key_r,
};
t/04.register.t view on Meta::CPAN
my ($r) = @_;
my $s_pub = substr $r, 0, 33;
my $nonce = substr $r, 33, 32;
my $auth_tag = substr $r, 65, 32;
### r: unpack("H*", $r)
### s_pub: unpack("H*", $s_pub)
### nonce: unpack("H*", $nonce)
### auth_tag: unpack("H*", $auth_tag)
return [ $s_pub, $nonce, $auth_tag ];
};
my $recover_r = recover_credentials($cred_req_r, $cred_res_r, $pwd, $c_id, $s_id, $Nseed, $group_name, $finalize_info, $finalize_DST, $hash_name, $expand_message_func, $mac_func, $pwd_harden_func, $unpack_func);
is($recover_r->{c_priv}->to_hex, 'D1D280F712E4EBF3C881C686E13C281BC3A3FAB30A00411A350F4F8B7A1EA550', 'recover_credentials');
is($recover_r->{export_key}, pack("H*", '77869b0d11debf6fc88c1d192dde9546baf528b2f70c2aea89960fc2178586da'), 'recover_credentials');
done_testing;
1;
t/05.sigma_i.t view on Meta::CPAN
my ($r) = @_;
my $s_pub = substr $r, 0, 33;
my $nonce = substr $r, 33, 32;
my $auth_tag = substr $r, 65, 32;
### r: unpack("H*", $r)
### s_pub: unpack("H*", $s_pub)
### nonce: unpack("H*", $nonce)
### auth_tag: unpack("H*", $auth_tag)
return [ $s_pub, $nonce, $auth_tag ];
};
my $recover_r = recover_credentials($cred_req_r, $a_recv_cred_res_r, $pwd, $id_a, $a_recv_msg2_r->{id_b}, $Nseed, $group_name, $finalize_info, $finalize_DST, $hash_name, $expand_message_func, $mac_func, $pwd_harden_func, $unpack_func);
is($recover_r->{export_key}, pack("H*", '77869b0d11debf6fc88c1d192dde9546baf528b2f70c2aea89960fc2178586da'), 'recover_credentials');
is($recover_r->{c_priv}->to_hex, 'D1D280F712E4EBF3C881C686E13C281BC3A3FAB30A00411A350F4F8B7A1EA550', 'recover_credentials');
my $a_recover_a_s_priv_pkey = gen_ec_key($group_name, $recover_r->{c_priv}->to_hex);
write_key_to_pem("$Bin/a_recover_c_s_priv.pem", $a_recover_a_s_priv_pkey );
my $a_recover_b_s_pub_pkey = gen_ec_pubkey($group_name, unpack("H*", $recover_r->{s_pub}));
write_pubkey_to_pem("$Bin/a_recover_b_s_pub.pem", $a_recover_b_s_pub_pkey );
my $a_verify_msg2 = a_verify_msg2(
$msg1_r, $a_recv_msg2_r, "$Bin/a_recover_b_s_pub.pem",
\&encode_cbor,
$mac_func,
( run in 0.281 second using v1.01-cache-2.11-cpan-4d50c553e7e )