I just had a problem logging in to stackoverflow.com using my own OP,
implemented using Net::OpenID::Server.
The symptom was described many times in their bugtracker:
http://stackoverflow.uservoice.com/pages/general/suggestions/21858-openid-delegation-does-not-work-
http://stackoverflow.uservoice.com/pages/general/suggestions/98262-openid-with-chi-mp-doesn-t-work
http://stackoverflow.uservoice.com/pages/general/suggestions/103156-fix-login-with-launchpad-net-openids
http://stackoverflow.uservoice.com/pages/general/suggestions/21560-fix-the-aol-open-id-login-
http://stackoverflow.uservoice.com/pages/general/suggestions/106762-openid-does-not-work-with-launchpad-net-providor
I've hacked my local checkout of the code.sixapart.com/svn/openid
repository to make it work for me. It ain't pretty, but it works, so
maybe it can be a tiny start:
perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm | 27 ++++++++++++++--------
1 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm b/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm
index 1e06913..0a42f51 100644
--- a/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm
+++ b/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm
@@ -47,7 +47,7 @@ use fields (
use URI;
use MIME::Base64 ();
-use Digest::SHA1 qw(sha1 sha1_hex);
+use Digest::SHA qw(sha1 sha1_hex sha256 sha256_hex hmac_sha256_hex);
use Crypt::DH 0.05;
use Math::BigInt;
use Time::Local qw(timegm);
@@ -423,7 +423,7 @@ sub _generate_association {
my $type = delete $opts{type};
my $dumb = delete $opts{dumb} || 0;
Carp::croak("Unknown options: " . join(", ", keys %opts)) if %opts;
- die unless $type eq "HMAC-SHA1";
+ die unless $type =~ /^HMAC-SHA(1|256)$/;
my $now = time();
my $sec_time = $now - ($now % $self->secret_gen_interval);
@@ -435,7 +435,12 @@ sub _generate_association {
$nonce = "STLS.$nonce" if $dumb; # flag nonce as stateless
my $handle = "$now:$nonce";
- $handle .= ":" . substr(hmac_sha1_hex($handle, $s_sec), 0, 10);
+ if ($type eq 'HMAC-SHA1') {
+ $handle .= ":" . substr(hmac_sha1_hex($handle, $s_sec), 0, 10);
+ }
+ elsif ($type eq 'HMAC-SHA256') {
+ $handle .= ":" . substr(hmac_sha256_hex($handle, $s_sec), 0, 10);
+ }
my $c_sec = $self->_secret_of_handle($handle, dumb => $dumb)
or return ();
@@ -477,10 +482,7 @@ sub _mode_associate {
my $now = time();
my %prop;
- my $assoc_type = "HMAC-SHA1";
- # FUTURE: protocol will let people choose their preferred authn scheme,
- # in which case we see if we support any of them, and override the
- # default value of HMAC-SHA1
+ my $assoc_type = $self->pargs('openid.assoc_type') || "HMAC-SHA1";
my ($assoc_handle, $secret, $expires) =
$self->_generate_association(type => $assoc_type);
@@ -501,7 +503,7 @@ sub _mode_associate {
$prop{'issued'} = _time_to_w3c($now);
}
- if ($self->pargs("openid.session_type") eq "DH-SHA1") {
+ if ($self->pargs("openid.session_type") =~ /^DH-SHA(1|256)$/) {
my $dh = Crypt::DH->new;
my $p = _arg2bi($self->pargs("openid.dh_modulus")) || _default_p();
@@ -518,8 +520,13 @@ sub _mode_associate {
my $dh_sec = $dh->compute_secret($cpub);
$prop{'dh_server_public'} = _bi2arg($dh->pub_key);
- $prop{'session_type'} = "DH-SHA1";
- $prop{'enc_mac_key'} = _b64($secret ^ sha1(_bi2bytes($dh_sec)));
+ $prop{'session_type'} = $self->pargs("openid.session_type");
+ if ($self->pargs("openid.session_type") eq 'DH-SHA1') {
+ $prop{'enc_mac_key'} = _b64($secret ^ sha1(_bi2bytes($dh_sec)));
+ }
+ elsif ($self->pargs("openid.session_type") eq 'DH-SHA256') {
+ $prop{'enc_mac_key'} = _b64($secret ^ sha256(_bi2bytes($dh_sec)));
+ }
} else {
$prop{'mac_key'} = _b64($secret);
--
1.5.6.5
Best regards,
Adam
--
"It has been a long, slow collision" Adam Sjøgren
as...@koldfront.dk
> I've hacked my local checkout of the code.sixapart.com/svn/openid
> repository to make it work for me. It ain't pretty, but it works, so
> maybe it can be a tiny start:
Today I had login problems again; found a place I had overlooked
previously and patched that as well. Here is the combined patch, I hope
it can be of use.
Best regards,
Adam
perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm | 38 +++++++++++++++-------
1 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm b/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm
index 1e06913..90745e3 100644
--- a/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm
+++ b/perl/Net-OpenID-Server/lib/Net/OpenID/Server.pm
@@ -47,7 +47,7 @@ use fields (
use URI;
use MIME::Base64 ();
-use Digest::SHA1 qw(sha1 sha1_hex);
+use Digest::SHA qw(sha1 sha1_hex sha256 sha256_hex hmac_sha256_hex);
use Crypt::DH 0.05;
use Math::BigInt;
use Time::Local qw(timegm);
@@ -423,7 +423,7 @@ sub _generate_association {
my $type = delete $opts{type};
my $dumb = delete $opts{dumb} || 0;
Carp::croak("Unknown options: " . join(", ", keys %opts)) if %opts;
- die unless $type eq "HMAC-SHA1";
+ die unless $type =~ /^HMAC-SHA(1|256)$/;
my $now = time();
my $sec_time = $now - ($now % $self->secret_gen_interval);
@@ -435,12 +435,18 @@ sub _generate_association {
$nonce = "STLS.$nonce" if $dumb; # flag nonce as stateless
my $handle = "$now:$nonce";
- $handle .= ":" . substr(hmac_sha1_hex($handle, $s_sec), 0, 10);
+ if ($type eq 'HMAC-SHA1') {
+ $handle .= ":" . substr(hmac_sha1_hex($handle, $s_sec), 0, 10);
+ }
+ elsif ($type eq 'HMAC-SHA256') {
+ $handle .= ":" . substr(hmac_sha256_hex($handle, $s_sec), 0, 10);
+ }
- my $c_sec = $self->_secret_of_handle($handle, dumb => $dumb)
+ my $c_sec = $self->_secret_of_handle($handle, dumb => $dumb, type=>$type)
or return ();
my $expires = $sec_time + $self->secret_expire_age;
+
return ($handle, $c_sec, $expires);
}
@@ -450,6 +456,12 @@ sub _secret_of_handle {
my $dumb_mode = delete $opts{'dumb'} || 0;
my $no_verify = delete $opts{'no_verify'} || 0;
+ my $type = delete $opts{'type'} || 'HMAC-SHA1';
+ my %hmac_functions=(
+ 'HMAC-SHA1' =>\&hmac_sha1_hex,
+ 'MMAC-SHA256'=>\&hmac_sha256_hex,
+ );
+ my $hmac_function=$hmac_functions{$type} || Carp::croak "No function for $type";
Carp::croak("Unknown options: " . join(", ", keys %opts)) if %opts;
my ($time, $nonce, $nonce_sig80) = split(/:/, $handle);
@@ -466,7 +478,7 @@ sub _secret_of_handle {
length($nonce) == ($dumb_mode ? 25 : 20) or return;
length($nonce_sig80) == 10 or return;
- return unless $no_verify || $nonce_sig80 eq substr(hmac_sha1_hex("$time:$nonce", $s_sec), 0, 10);
+ return unless $no_verify || $nonce_sig80 eq substr(&$hmac_function("$time:$nonce", $s_sec), 0, 10);
return hmac_sha1($handle, $s_sec);
}
@@ -477,10 +489,7 @@ sub _mode_associate {
my $now = time();
my %prop;
- my $assoc_type = "HMAC-SHA1";
- # FUTURE: protocol will let people choose their preferred authn scheme,
- # in which case we see if we support any of them, and override the
- # default value of HMAC-SHA1
+ my $assoc_type = $self->pargs('openid.assoc_type') || "HMAC-SHA1";
my ($assoc_handle, $secret, $expires) =
$self->_generate_association(type => $assoc_type);
@@ -501,7 +510,7 @@ sub _mode_associate {
$prop{'issued'} = _time_to_w3c($now);
}
- if ($self->pargs("openid.session_type") eq "DH-SHA1") {
+ if ($self->pargs("openid.session_type") =~ /^DH-SHA(1|256)$/) {
my $dh = Crypt::DH->new;
my $p = _arg2bi($self->pargs("openid.dh_modulus")) || _default_p();
@@ -518,8 +527,13 @@ sub _mode_associate {
my $dh_sec = $dh->compute_secret($cpub);
$prop{'dh_server_public'} = _bi2arg($dh->pub_key);
- $prop{'session_type'} = "DH-SHA1";
- $prop{'enc_mac_key'} = _b64($secret ^ sha1(_bi2bytes($dh_sec)));
+ $prop{'session_type'} = $self->pargs("openid.session_type");
+ if ($self->pargs("openid.session_type") eq 'DH-SHA1') {
+ $prop{'enc_mac_key'} = _b64($secret ^ sha1(_bi2bytes($dh_sec)));
+ }
+ elsif ($self->pargs("openid.session_type") eq 'DH-SHA256') {
+ $prop{'enc_mac_key'} = _b64($secret ^ sha256(_bi2bytes($dh_sec)));
+ }
} else {
$prop{'mac_key'} = _b64($secret);
--
1.5.6.5
--
"Angels can fly because they take themselves lightly." Adam Sjøgren
as...@koldfront.dk
Thanks for this patch. I assume this patch is for the 1.0 branch rather
than the trunk?
Will this respond sensibly if a consumer requests an unsupported
signature method or session type?
Also, please update the dependencies in Makefile.PL to reflect the fact
that this now depends on Digest::SHA rather than Digest::SHA1.
It'd be good to also have a patch that applies to trunk, where I think
some of this stuff now lives in Net::OpenID::Common and is shared
between consumer and server.
> Thanks for this patch. I assume this patch is for the 1.0 branch
> rather than the trunk?
The patch I sent by email is against trunk of the old svn-repository.
(Which I am using because I couldn't make the version on CPAN work).
The one on my github fork¹ is against your github repository's master
branch. I must admit I haven't tested the latter, as it breaks
functionality for me.
> Will this respond sensibly if a consumer requests an unsupported
> signature method or session type?
As sensibly as it did previously, I'd guess? I have tried to update the
two existing checks, like this:
- die unless $type eq "HMAC-SHA1";
+ die unless $type =~ /^HMAC-SHA(1|256)$/;
[...]
- if ($self->pargs("openid.session_type") eq "DH-SHA1") {
+ if ($self->pargs("openid.session_type") =~ /^DH-SHA(1|256)$/) {
> Also, please update the dependencies in Makefile.PL to reflect the
> fact that this now depends on Digest::SHA rather than Digest::SHA1.
Good point; done: <http://github.com/asjo/libnet-openid-perl/commit/6dd211c746e1ce4c3ab8ff9564cc246584ad3292>
> It'd be good to also have a patch that applies to trunk, where I think
> some of this stuff now lives in Net::OpenID::Common and is shared
> between consumer and server.
I didn't notice any of the stuff I modify not being in
Net::OpenID::Server when I ported the patch to my fork of the new github
repository: <http://github.com/asjo/libnet-openid-perl/commit/c9a0a4e273c5586d698ce66dcce5f003d27cbb2e>
When I look at Net::OpenID::Server², it doesn't use Net::OpenID::Common,
so I wonder how it could be using code from ::Common?
Maybe I am looking in the wrong place; I haven't used github before
("only" git) - as I said, the latest code doesn't work for me, and I
haven't really had time to dig further yet.
Thanks for the reply,
Adam
¹ <http://github.com/asjo/libnet-openid-perl/tree/master>
--
"And [I went for] the fireengines Adam Sjøgren
But they were all upside down" as...@koldfront.dk
Sorry. I guess you made this patch before I started to work on
Net::OpenID::Server refactoring, so it looked like a 1.0 patch rather
than a trunk patch. (and, apparently, master on github isn't working
right now. It's mid-refactor, so this is not completely unexpected.)
I think for the moment I'll hold off on committing your patch until I'm
finished refactoring and then I'll work on pulling your changes on
github. I hope to do some more refactoring work later this week if time
allows.
> Sorry. I guess you made this patch before I started to work on
> Net::OpenID::Server refactoring, so it looked like a 1.0 patch rather
> than a trunk patch. (and, apparently, master on github isn't working
> right now. It's mid-refactor, so this is not completely unexpected.)
Ok, no problem.
> I think for the moment I'll hold off on committing your patch until I'm
> finished refactoring and then I'll work on pulling your changes on
> github. I hope to do some more refactoring work later this week if time
> allows.
Sounds good!
I will be happy to adjust my patch/fork to your changes and resubmit it
when it suits you.
How can I follow your progress, if it isn't by watching your master
branch on github?
Thanks!
Adam
My master branch on github is now the primary repository in which I'll
be doing development.
> My master branch on github is now the primary repository in which I'll
> be doing development.
Cool! I have tried to update my fork¹ on github accordingly.
Best regards,
Adam
¹ Slightly weird github terminology, IMHO.