Authen-U2F

 view release on metacpan or  search on metacpan

lib/Authen/U2F.pm  view on Meta::CPAN

    $pkec->import_key_raw($key, "nistp256");
  }
  catch {
    croak "invalid key argument (parse failure: $_)";
  };

  my $client_data = decode_base64url($args->{client_data});
  croak "couldn't decode client data; not valid Base64-URL?"
    unless $client_data;

  {
    my $data = decode_json($client_data);
    croak "invalid client data (challenge doesn't match)"
      unless $data->{challenge} eq $args->{challenge};
    croak "invalid client data (origin doesn't match)"
      unless $data->{origin} eq $args->{origin};
  }

  my $sign_data = decode_base64url($args->{signature_data});
  croak "couldn't decode signature data; not valid Base64-URL?"
    unless $sign_data;

  # $sig_data is packed like so
  #
  # 1-byte  user presence
  # 4-byte  counter (big-endian)
  #         signature

  my ($presence, $counter, $sig) = unpack 'a N a*', $sign_data;

  # XXX presence check

  # XXX counter check

  # signature data. sha256 of:
  #
  # 32-byte sha256(app ID)                      (application parameter)
  # 1-byte  user presence
  # 4-byte  counter (big endian)
  # 32-byte sha256(client data (JSON-encoded))  (challenge parameter)

  my $app_id_sha = sha256($args->{app_id});
  my $challenge_sha = sha256($client_data);

  my $sigdata = pack "a32 a N a32", $app_id_sha, $presence, $counter, $challenge_sha;
  my $sigdata_sha = sha256($sigdata);

  $pkec->verify_hash($sig, $sigdata_sha)
    or croak "invalid signature data (signature verification failed)";

  return;
}

1;
__END__

=pod

=encoding UTF-8

=for markdown [![Build Status](https://secure.travis-ci.org/robn/Authen-U2F.png)](http://travis-ci.org/robn/Authen-U2F)

=head1 NAME

Authen-U2F - FIDO U2F library

=head1 SYNOPSIS

    use Authen::U2F qw(
      u2f_challenge
      u2f_registration_verify
      u2f_signature_verify);

    # Create a challenge to send to the U2F host
    my $challenge = u2f_challenge;

    # Process a registration response from the U2F host
    my ($key_handle, $key) = u2f_registration_verify(
      challenge         => $challenge,
      app_id            => $app_id,
      origin            => $origin,
      registration_data => $registration_data,
      client_data       => $client_data,
    );

    # Process a signing (authentication) response from the U2F host
    u2f_signature_verify(
      challenge      => $challenge,
      app_id         => $app_id,
      origin         => $origin,
      key_handle     => $key_handle,
      key            => $key,
      signature_data => $signature_data,
      client_data    => $client_data,
    );

    # Or, if you don't like to clutter up your namespace
    my $challenge = Authen::U2F->challenge;
    my ($key_handle, $key) = Authen::U2F->registration_verify(...);
    Authen::U2F->signature_verify(...);

=head1 DESCRIPTION

This module provides the tools you need to add support for U2F in your
application.

It's expected that you know the basics of U2F. More information about this can
be found at L<Yubico|https://www.yubico.com/about/background/fido/> and
L<FIDO|https://fidoalliance.org/specifications/overview/>.

This module does not handle the wire encoding of U2F challenges and response,
as these are different depending on the U2F host you're using and the style of
your application. In the C<examples> dir there are scripts that implement the
1.0 wire format, used by L<Yubico's libu2f-host|https://developers.yubico.com/libu2f-host/>,
and a Plack application that works with
L<Google's JavaScript module|https://github.com/google/u2f-ref-code/blob/master/u2f-gae-demo/war/js/u2f-api.js>.

Sadly, the documentation around U2F is rather more confusing than it should be,
and this short description is probably not making things better. Please improve
this or write something about U2F so we can improve application security
everywhere.



( run in 1.820 second using v1.01-cache-2.11-cpan-788537b7465 )