From de0eb0bce3013b170574373ddb363dd51aca7245 Mon Sep 17 00:00:00 2001 From: Alex Balhatchet Date: Sun, 31 May 2015 13:50:03 +0100 Subject: [PATCH] Monkey patch two dependencies to use /dev/unrandom over /dev/random This makes the tests 11-encrypt.t and 13-keygen.t run consistently quickly, whereas before they were intermittently much slower. Before: $ for i in $(seq 1 10) ; do prove -b t/11-encrypt.t 2>&1 | grep wallclock ; done Files=1, Tests=36, 0 wallclock secs ( 0.03 usr 0.00 sys + 0.67 cusr 0.01 csys = 0.71 CPU) Files=1, Tests=36, 1 wallclock secs ( 0.04 usr 0.00 sys + 0.64 cusr 0.02 csys = 0.70 CPU) Files=1, Tests=36, 80 wallclock secs ( 0.03 usr 0.00 sys + 0.66 cusr 0.01 csys = 0.70 CPU) Files=1, Tests=36, 87 wallclock secs ( 0.04 usr 0.00 sys + 0.55 cusr 0.00 csys = 0.59 CPU) Files=1, Tests=36, 67 wallclock secs ( 0.03 usr 0.00 sys + 0.58 cusr 0.00 csys = 0.61 CPU) Files=1, Tests=36, 89 wallclock secs ( 0.03 usr 0.01 sys + 0.49 cusr 0.02 csys = 0.55 CPU) Files=1, Tests=36, 83 wallclock secs ( 0.03 usr 0.01 sys + 0.65 cusr 0.02 csys = 0.71 CPU) Files=1, Tests=36, 80 wallclock secs ( 0.04 usr 0.01 sys + 0.60 cusr 0.01 csys = 0.66 CPU) Files=1, Tests=36, 34 wallclock secs ( 0.04 usr 0.00 sys + 0.62 cusr 0.03 csys = 0.69 CPU) Files=1, Tests=36, 32 wallclock secs ( 0.02 usr 0.00 sys + 0.54 cusr 0.01 csys = 0.57 CPU) After: $ for i in $(seq 1 10) ; do prove -b t/11-encrypt.t 2>&1 | grep wallclock ; done Files=1, Tests=36, 1 wallclock secs ( 0.02 usr 0.00 sys + 0.43 cusr 0.01 csys = 0.46 CPU) Files=1, Tests=36, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.41 cusr 0.00 csys = 0.43 CPU) Files=1, Tests=36, 1 wallclock secs ( 0.02 usr 0.00 sys + 0.40 cusr 0.01 csys = 0.43 CPU) Files=1, Tests=36, 0 wallclock secs ( 0.03 usr 0.00 sys + 0.40 cusr 0.00 csys = 0.43 CPU) Files=1, Tests=36, 1 wallclock secs ( 0.03 usr 0.00 sys + 0.42 cusr 0.02 csys = 0.47 CPU) Files=1, Tests=36, 0 wallclock secs ( 0.03 usr 0.00 sys + 0.40 cusr 0.01 csys = 0.44 CPU) Files=1, Tests=36, 1 wallclock secs ( 0.03 usr 0.00 sys + 0.40 cusr 0.00 csys = 0.43 CPU) Files=1, Tests=36, 0 wallclock secs ( 0.02 usr 0.01 sys + 0.39 cusr 0.01 csys = 0.43 CPU) Files=1, Tests=36, 1 wallclock secs ( 0.02 usr 0.01 sys + 0.41 cusr 0.01 csys = 0.45 CPU) Files=1, Tests=36, 0 wallclock secs ( 0.03 usr 0.00 sys + 0.41 cusr 0.00 csys = 0.44 CPU) --- lib/Crypt/OpenPGP.pm | 47 +++++++++++++++++++++++++++++++++++++++ lib/Crypt/OpenPGP/Util.pm | 23 +++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/lib/Crypt/OpenPGP.pm b/lib/Crypt/OpenPGP.pm index a90deb9..ddc00de 100644 --- a/lib/Crypt/OpenPGP.pm +++ b/lib/Crypt/OpenPGP.pm @@ -20,6 +20,53 @@ use File::Spec; use vars qw( %COMPAT ); +# HACK FOR PERFORMANCE +# Crypt::DSA::Util prefers /dev/random which can be slow sometimes. Let's try +# /dev/urandom if it's available to speed things up. +# Lame but it works... +{ + use Carp; + use Fcntl; + use Crypt::DSA::Util; + no warnings 'redefine'; + + sub Crypt::DSA::Util::makerandom { + warn "Using hacked version of Crypt::DSA::Util::makerandom\n"; + my %param = @_; + my $size = $param{Size}; + my $bytes = int($size / 8) + 1; + my $r = ''; + + my $dev_rand = '/dev/random'; + if (-r '/dev/urandom') { + $dev_rand = '/dev/urandom'; + } + + if ( sysopen my $fh, $dev_rand, O_RDONLY ) { + my $read = 0; + while ($read < $bytes) { + my $got = sysread $fh, my($chunk), $bytes - $read; + next unless $got; + die "Error: $!" if $got == -1; + $r .= $chunk; + $read = length $r; + } + close $fh; + } + elsif ( require Data::Random ) { + $r .= Data::Random::rand_chars( set=>'numeric' ) for 1..$bytes; + } + else { + croak "makerandom requires $dev_rand or Data::Random"; + } + my $down = $size - 1; + $r = unpack 'H*', pack 'B*', '0' x ( $size % 8 ? 8 - $size % 8 : 0 ) . + '1' . unpack "b$down", $r; + Math::BigInt->new('0x' . $r); + } +} +# /HACK + ## pgp2 and pgp5 do not trim trailing whitespace from "canonical text" ## signatures, only from cleartext signatures. ## See: diff --git a/lib/Crypt/OpenPGP/Util.pm b/lib/Crypt/OpenPGP/Util.pm index 6d82b53..4b5639d 100644 --- a/lib/Crypt/OpenPGP/Util.pm +++ b/lib/Crypt/OpenPGP/Util.pm @@ -102,6 +102,29 @@ sub _ensure_bigint { sub get_random_bytes { my $length = shift; if (eval 'require Crypt::Random; 1;') { + # HACK FOR PERFORMANCE + # In Crypt::Random::Seed::new dev_random is tried before dev_urandom, + # so let's override that method to check urandom first and then fall + # back on dev_random. + # Lame but it works... + { + no warnings 'redefine'; + + use Crypt::Random::Seed; + + sub Crypt::Random::Seed::_try_dev_random { + warn "Using hacked version of Crypt::Random::Seed::_try_dev_random\n"; + if (-r "/dev/urandom") { + return ('/dev/urandom', sub { Crypt::Random::Seed::__read_file('/dev/urandom', @_); }, 0, 0); + } + elsif (-r "/dev/random") { + my $blocking = ($^O eq 'freebsd') ? 0 : 1; + return ('/dev/random', sub { Crypt::Random::Seed::__read_file('/dev/random', @_); }, $blocking, 1); + } + return; + } + } + # /HACK return Crypt::Random::makerandom_octet( Length => $length); } elsif (eval 'require Bytes::Random::Secure; 1;') {