Hacking sha256 support into Net::OpenID::Server [patch]

20 views
Skip to first unread message

Adam Sjøgren

unread,
Feb 15, 2009, 4:08:23 PM2/15/09
to openi...@googlegroups.com
Hi.


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

Adam Sjøgren

unread,
Apr 26, 2009, 10:10:19 AM4/26/09
to openi...@googlegroups.com
On Sun, 15 Feb 2009 22:08:23 +0100, Adam wrote:

> 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

Martin Atkins

unread,
May 4, 2009, 3:00:39 PM5/4/09
to openi...@googlegroups.com

Hi Adam,

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.

Adam Sjøgren

unread,
May 4, 2009, 3:55:19 PM5/4/09
to openi...@googlegroups.com
On Mon, 04 May 2009 12:00:39 -0700, Martin wrote:

> 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>

² <http://github.com/apparentlymart/libnet-openid-perl/blob/2d6e872f73dce6412d1ec1f0f89cb21e3fdb90f0/Net-OpenID-Server/lib/Net/OpenID/Server.pm>

--
"And [I went for] the fireengines Adam Sjøgren
But they were all upside down" as...@koldfront.dk

Martin Atkins

unread,
May 5, 2009, 11:10:45 AM5/5/09
to openi...@googlegroups.com

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.

Adam Sjøgren

unread,
May 5, 2009, 1:12:03 PM5/5/09
to openi...@googlegroups.com
On Tue, 05 May 2009 08:10:45 -0700, Martin wrote:

> 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

Martin Atkins

unread,
May 6, 2009, 2:51:23 AM5/6/09
to openi...@googlegroups.com
Adam Sjøgren wrote:
>
> How can I follow your progress, if it isn't by watching your master
> branch on github?
>

My master branch on github is now the primary repository in which I'll
be doing development.


Adam Sjøgren

unread,
May 8, 2009, 3:29:08 PM5/8/09
to openi...@googlegroups.com
On Tue, 05 May 2009 23:51:23 -0700, Martin wrote:

> 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.

Reply all
Reply to author
Forward
0 new messages