Commit 363ff07d authored by Lucas Kanashiro's avatar Lucas Kanashiro

Imported Upstream version 0.29

parent 53dd5a7a
Revision history for Bytes::Random::Secure Revision history for Bytes::Random::Secure
0.29 2015-07-12
- Added a shuffle method available via the OO user interface.
- Added a SEE ALSO POD section that mentions Bytes::Random::Secure::Tiny
0.28 2013-11-21 0.28 2013-11-21
- Removed silly micro-optimization that was responsible for generating a - Removed silly micro-optimization that was responsible for generating a
warning in Perl versions prior to 5.18. warning in Perl versions prior to 5.18.
......
...@@ -23,6 +23,7 @@ t/23-string_from_unicode.t ...@@ -23,6 +23,7 @@ t/23-string_from_unicode.t
t/24-oo_construct.t t/24-oo_construct.t
t/26-oo_public.t t/26-oo_public.t
t/27-fips140-1.t t/27-fips140-1.t
t/36-shuffle.t
examples/random-sha512.pl examples/random-sha512.pl
examples/random-sha512-oo.pl examples/random-sha512-oo.pl
examples/random-from.pl examples/random-from.pl
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"David Oswald <davido@cpan.org>" "David Oswald <davido@cpan.org>"
], ],
"dynamic_config" : 1, "dynamic_config" : 1,
"generated_by" : "ExtUtils::MakeMaker version 6.78, CPAN::Meta::Converter version 2.132140", "generated_by" : "ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001",
"license" : [ "license" : [
"perl_5" "perl_5"
], ],
...@@ -48,5 +48,5 @@ ...@@ -48,5 +48,5 @@
"version" : 2 "version" : 2
} }
}, },
"version" : "0.28" "version" : "0.29"
} }
...@@ -3,29 +3,29 @@ abstract: 'Perl extension to generate cryptographically-secure random bytes.' ...@@ -3,29 +3,29 @@ abstract: 'Perl extension to generate cryptographically-secure random bytes.'
author: author:
- 'David Oswald <davido@cpan.org>' - 'David Oswald <davido@cpan.org>'
build_requires: build_requires:
Test::More: 0.98 Test::More: '0.98'
configure_requires: configure_requires:
ExtUtils::MakeMaker: 6.56 ExtUtils::MakeMaker: '6.56'
dynamic_config: 1 dynamic_config: 1
generated_by: 'ExtUtils::MakeMaker version 6.78, CPAN::Meta::Converter version 2.132140' generated_by: 'ExtUtils::MakeMaker version 7.0401, CPAN::Meta::Converter version 2.150001'
license: perl license: perl
meta-spec: meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: 1.4 version: '1.4'
name: Bytes-Random-Secure name: Bytes-Random-Secure
no_index: no_index:
directory: directory:
- t - t
- inc - inc
requires: requires:
Carp: 0 Carp: '0'
Crypt::Random::Seed: 0 Crypt::Random::Seed: '0'
MIME::Base64: 0 MIME::Base64: '0'
MIME::QuotedPrint: 3.03 MIME::QuotedPrint: '3.03'
Math::Random::ISAAC: 0 Math::Random::ISAAC: '0'
Scalar::Util: 1.21 Scalar::Util: '1.21'
perl: 5.006000 perl: '5.006000'
resources: resources:
Metaspec: Metaspec:
version: 2 version: 2
version: 0.28 version: '0.29'
...@@ -25,7 +25,7 @@ our @EXPORT_OK = qw( ...@@ -25,7 +25,7 @@ our @EXPORT_OK = qw(
our @EXPORT = qw( random_bytes ); ## no critic(export) our @EXPORT = qw( random_bytes ); ## no critic(export)
our $VERSION = '0.28'; our $VERSION = '0.29';
# Seed size: 256 bits is eight 32-bit integers. # Seed size: 256 bits is eight 32-bit integers.
use constant SEED_SIZE => 256; # In bits use constant SEED_SIZE => 256; # In bits
...@@ -283,7 +283,19 @@ sub string_from { ...@@ -283,7 +283,19 @@ sub string_from {
return $rand_bytes; return $rand_bytes;
} }
# Helpers for string_from()
sub shuffle {
my($self, $aref) = @_;
croak 'Argument must be an array reference.' unless 'ARRAY' eq ref $aref;
return $aref unless @$aref;
for (my $i = @$aref; --$i;) {
my $r = ($self->_ranged_randoms($i+1, 1))[0];
($aref->[$i],$aref->[$r]) = ($aref->[$r], $aref->[$i]);
}
return $aref;
}
# Helpers for string_from() and shuffle.
sub _ranged_randoms { sub _ranged_randoms {
my ( $self, $range, $count ) = @_; my ( $self, $range, $count ) = @_;
...@@ -700,6 +712,25 @@ Returns a random 32-bit unsigned integer. The value will satisfy ...@@ -700,6 +712,25 @@ Returns a random 32-bit unsigned integer. The value will satisfy
C<< 0 <= x <= 2**32-1 >>. This functionality is only available through the OO C<< 0 <= x <= 2**32-1 >>. This functionality is only available through the OO
interface. interface.
=head2 shuffle
my $aref_shuffled = $random->shuffle($aref);
Shuffles the contents of a reference to an array in sitiu, and returns
the same reference.
L<List::Util>, which ships with Perl, includes C<shuffle> function. But that
function is flawed in two ways. First, from a cryptographic standpoint,
it uses Perl's C<rand>, which is not a CSPRNG, and therefore is inadequate.
Second, because Perl's rand has an internal state of just 32 bits, it cannot
possibly generate all permutations of arrays containing 13 or more elements.
This module's C<shuffle> uses a CSPRNG, and also benefits from large seeds
and a huge internal state. ISAAC can be seeded with up to 8192 bits, yielding
2^8192 possible initial states, and 2^8288 possible internal states. A seed of
8192 bits will assure that for arrays of up to 966 elements every permutation
is accessible.
=head1 CONFIGURATION =head1 CONFIGURATION
...@@ -895,6 +926,17 @@ Test coverage for Bytes::Random::Secure is 100% (per Devel::Cover) on any ...@@ -895,6 +926,17 @@ Test coverage for Bytes::Random::Secure is 100% (per Devel::Cover) on any
system that has L<Test::Warn> installed. But to keep the module light-weight, system that has L<Test::Warn> installed. But to keep the module light-weight,
Test::Warn is not dragged in by default at installation time. Test::Warn is not dragged in by default at installation time.
=head1 SEE ALSO
L<Math::Random::Secure> and L<Crypt::Random> provide strong CSPRINGs and even
more configuration options, but come with hefty toolchains.
L<Bytes::Random::Secure::Tiny> is a stand-alone adaptation of
L<Bytes::Random::Secure> with no dependencies. It will, however, detect if
L<Math::Random::ISAAC>, L<Math::Random::ISAAC::XS>, and L<Crypt::Random::Seed>
are installed on the target system, and if they are, it quietly upgrades to
using them.
=head1 AUTHOR =head1 AUTHOR
David Oswald C<< <davido [at] cpan (dot) org> >> David Oswald C<< <davido [at] cpan (dot) org> >>
......
...@@ -15,6 +15,7 @@ use English qw( -no_match_vars ); ...@@ -15,6 +15,7 @@ use English qw( -no_match_vars );
if ( not $ENV{RELEASE_TESTING} ) { if ( not $ENV{RELEASE_TESTING} ) {
my $msg = 'Author Test: Set $ENV{RELEASE_TESTING} to a true value to run.'; my $msg = 'Author Test: Set $ENV{RELEASE_TESTING} to a true value to run.';
plan( skip_all => $msg ); plan( skip_all => $msg );
done_testing();
} }
# We also don't want to force a dependency on Test::Perl::Critic, so if the # We also don't want to force a dependency on Test::Perl::Critic, so if the
...@@ -25,6 +26,7 @@ eval { require Test::Perl::Critic; 1; }; ...@@ -25,6 +26,7 @@ eval { require Test::Perl::Critic; 1; };
if ($EVAL_ERROR) { if ($EVAL_ERROR) {
my $msg = 'Author Test: Test::Perl::Critic required to criticise code.'; my $msg = 'Author Test: Test::Perl::Critic required to criticise code.';
plan( skip_all => $msg ); plan( skip_all => $msg );
done_testing();
} }
# Set a higher severity level. Note: List/BinarySearch.pm meets level 2. # Set a higher severity level. Note: List/BinarySearch.pm meets level 2.
...@@ -35,5 +37,3 @@ Test::Perl::Critic->import( -severity => 4 ); ...@@ -35,5 +37,3 @@ Test::Perl::Critic->import( -severity => 4 );
my @directories = qw{ blib/ t/ }; my @directories = qw{ blib/ t/ };
Test::Perl::Critic::all_critic_ok(@directories); Test::Perl::Critic::all_critic_ok(@directories);
done_testing();
#!/usr/bin/env perl
use strict;
use warnings;
use Bytes::Random::Secure;
use List::Util qw(max min);
use Test::More;
my $r = Bytes::Random::Secure->new;
isa_ok $r, 'Bytes::Random::Secure';
my @array = 1..16;
my @ranged = map {($r->_ranged_randoms(scalar @array, 1))[0]} 1 .. 10000;
is min(@ranged), 0, 'Minimum ranged is zero.';
is max(@ranged), 15, 'Maximum ranged is fifteen.';
my $aref = $r->shuffle([@array]);
cmp_ok ref $aref, 'eq', 'ARRAY', 'shuffle returns an aref.';
cmp_ok scalar @$aref, '==', 16,
'in sitiu shuffle returned correct element count.';
is min(@$aref), 1, 'shuffle returned correct min value.';
is max(@$aref), 16, 'shuffle returned correct max value.';
my %found;
@found{@$aref} = ();
is scalar keys %found, 16, 'All elements received after shuffle.';
ok((0 != grep { $array[$_] != $aref->[$_] } 0 .. 15),
'Elements are in different order from original.');
my $res = eval {$r->shuffle(@array)} || $@;
like $res, qr/Argument must be an array reference\./,
'shuffle dies unless passed an array reference.';
done_testing();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment