views:

56

answers:

3

Is it possible to take a digest created like

my $digest  = Digest::SHA->new('sha1')->add('hello')->digest;

and then convert $digest to base10 (instead of hex or base64?) or could you split a hexdigest into 5 pieces and then convert those into integers? would that work? Trying to come up with a way to store the digest as integers (yes I know someone is going to think I'm crazy or stupid, probably both).

update

In theory I should be able to take the final encoded integer output and reverse and reencode to hex and base64 as needed.

A: 

Something like this, maybe?

#!/usr/bin/perl

use strict; use warnings;
use Digest::SHA;
use YAML;

my $digest  = Digest::SHA->new('sha1')->add('hello')->hexdigest;
print "$digest\n";
print Dump [ map { [$_, hex] } $digest =~ /([[:xdigit:]]{8})/g ];

Output:

aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
---
-
  - aaf4c61d
  - 2868168221
-
  - dcc5e8a2
  - 3703957666
-
  - dabede0f
  - 3669941775
-
  - 3b482cd9
  - 994585817
-
  - aea9434d
  - 2930328397
Sinan Ünür
similar to a solution i'd hacked up (though probably better because of the map) can it be reversed? by reversed I mean could I take it from the integers and get it to a base64 encoding (that's the same as a base64 encode of the digest) if I wanted?
xenoterracide
+2  A: 

I think pack & unpack will probably be more efficient:

use Digest::SHA;

my $digest  = Digest::SHA->new('sha1')->add('hello')->digest;
my @ints = unpack('N*', $digest);
print "@ints\n";

my $redone = pack('N*', @ints);

print "match\n" if $digest eq $redone;

my $hexdigest = sprintf '%08x' x @ints, @ints;
print "$hexdigest\n";
printf "%s\n", Digest::SHA->new('sha1')->add('hello')->hexdigest;

use MIME::Base64 'encode_base64';
my $b64digest = encode_base64(pack('N*', @ints));
print $b64digest;
printf "%s\n", Digest::SHA->new('sha1')->add('hello')->b64digest;

Output:

2868168221 3703957666 3669941775 994585817 2930328397
match
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
qvTGHdzF6KLavt4PO0gs2a6pQ00=
qvTGHdzF6KLavt4PO0gs2a6pQ00

Note that MIME::Base64 pads the result, and the b64digest method doesn't. But it's easy enough to strip off the trailing = if you need to.

cjm
+4  A: 

If wherever you're going can handle arbitrary-precision integers without flinching (yeah, unikely, but you never know), then you can just encode it as a single integer ;)

$ re.pl
$ use Digest::SHA; use Math::BigInt;

$ my $hex = Digest::SHA->new("SHA-1")->add("hello")->hexdigest;
aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
$ Math::BigInt->from_hex("0x" . $hex)->bstr
975987071262755080377722350727279193143145743181
$ Math::BigInt->new("975987071262755080377722350727279193143145743181")->as_hex
0xaaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
hobbs