[Cryptography] Removal of spaces in NIST Draft SP-800-63B

Jonathan Thornburg jthorn4242 at gmail.com
Sat Apr 8 16:07:06 EDT 2017


On Sat, Apr 08, 2017 at 02:09:39PM +1000, Jason Richards wrote:
> Jonathan Thornburg:
> > dd if=/dev/arandom bs=50 count=1|alphanumeric.encode
> 
> What is this "alphanumeric.encode" you speak of?
> 
> I do something similar, piping to 'openssl base64', which unfortunately
> produces output without a whole lot of entropy, although it usually
> satisfies at least three and often all four of the standard password
> character sets.
> 
> Is there something specific you use to convert to human-readable output?

alphanumeric.encode is a quick-n-dirty perl program I wrote to convert
random binary data into random characters from [a-zA-Z0-9] or [a-z0-9]:

[[I don't know if (short) code is appropriate for the cryptography mailing
list -- if our Esteemed Moderator wants to reject this that's fine, and
I'll mail the code privately to anyone who wants it.]]

#!/usr/bin/perl -w
use strict;
use Getopt::Long;
my $false = 0;
my $true  = 1;

########################################

my $help_msg = <<'EOF';
Usage:
   dd if=/dev/arandom bs=100 count=1 | alphanumeric.encode
or
   dd if=/dev/arandom bs=100 count=1 | alphanumeric.encode  --lower-case

By default, this program encodes standard input binary-data into mixed-case
alphanumeric characgers ([a-zA-Z0-9]).

If the --lower-case option is specified, then this program encodes into
lower-case alphanumeric characters ([a-z0-9]).
EOF

#
# At present we do the encoding "by hand".
# FIXME: It would probably be better to not reinvent the wheel here,
#        and instead use an existing Perl module such as Math::Int2Base
#        or Math::Base::Convert.
#
# Mixed-case:
#   Since 2*26+10 = 62, and 62**3 = 14776336 = less than 256**3 = 16777216,
#   we can encode 3 chars (24 bits) of binary input into 4 base62 output
#   characters.  If we get an "unencodable" input 3-tuple we just discard
#   it and try again with the next input 3-tuple.
#
# Lower-case
#   Since 26+10 = 36, and 36**3 = 46656 = less than 256**2 = 65536,
#   we can encode 2 chars (16 bits) of binary input into 3 base36 output
#   characters.  If we get an "unencodable" input 2-tuple we just discard
#   it and try again with the next input 2-tuple.
#

########################################

my $debug           = 0;
my $help_flag       = $false;
my $lower_case_flag = $false;
GetOptions(
  'debug=i'    => \$debug,
  'help'       => \$help_flag,
  'lower-case' => \$lower_case_flag,
	  ) || die $help_msg;				# *** ERROR EXIT ***
if ($help_flag)
	{ print $help_msg; exit; }			# *** --help EXIT ***

########################################

my $N_in     = $lower_case_flag ? 2 : 3;
my $in_base  = 256;
my $in_limit = $in_base ** $N_in;
my $N_out        = $lower_case_flag ? 3 : 4;
my @out_alphabet = $lower_case_flag ? (0..9, 'a'..'z')
				    : (0..9, 'a'..'z', 'A'..'Z');
my $out_base     = scalar(@out_alphabet);
my $out_limit    = $out_base ** $N_out;

if ($debug > 0)
	{
	print "in_base=${in_base} N_in=${N_in} ==> in_limit = ${in_limit}\n";
	print "out_base=${out_base} N_out=${N_out} ==> out_limit = ${out_limit}\n";
	}

binmode(STDIN);

my $count_on_line = 0;
my $buffer;
	while (my $N_read = read(STDIN, $buffer, $N_in))
	{
	if ($N_read != $N_in)
		{ last; }				# *** LOOP EXIT ***
	my @in_chars  = split(//, $buffer);
	my @in_digits = map {ord($_)} @in_chars;

	# integer in [0, $in_limit)
	my $N = $lower_case_flag
		? $in_digits[0] + $in_base*$in_digits[1]
		: $in_digits[0] + $in_base
				  *($in_digits[1] + $in_base*$in_digits[2]);
	if ($debug >= 6)
		{ print "in_digits=(",join(',', at in_digits),") ==> N=${N}\n"; }

	if ($N >= $out_limit)
		{
		if ($debug >= 6)
			{ print "   N > out_limit ==> try again\n"; }
		next;					# *** LOOP CONTROL ***
		}
	
	my @out_digits = ();
	
		for (my $i = 0 ; $i < $N_out ; ++$i)
		{
		my $d  = $N % $out_base;
		$N = int($N / $out_base);
		push @out_digits, $d;
		}
	if ($debug >= 6)
		{ print "   out_digits=(",join(',', at out_digits),")\n"; }

	my @out_chars = map {$out_alphabet[$_]} @out_digits;

	$count_on_line += $N_out;
	if ($debug >= 6)
		{ print '   :',join('', at out_chars),":\n"; }
	   else { print join('', at out_chars); }
	if ($count_on_line >= 60)
		{
		print "\n";
		$count_on_line = 0;
		}
	}


More information about the cryptography mailing list