Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Converting integer to bytes

by Anonymous Monk
on Jan 07, 2021 at 11:10 UTC ( #11126521=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to implement the authentication described here.

In step 7, the integer/string (it's not clear) that represents the user ID is 1. That's converted into the bytes represented by 0x00000000 00000001 (8 bytes). I'm trying to write the Perl that would do that conversion, so that those bytes can then be passed to Digest::SHA as part of the message. The doc describes this ID as "8-byte (big-endian) user identifier". I concluded the Encode module isn't right as this should be perl internal string -> binary, without a character encoding in-between. I thought that unpack is the right way to go, but I'm not having much luck. I thought maybe I can have it represented as hex (something that Digest::SHA accepts as a data format for the message):
my $user_id_h = unpack("H*", $user_id); print(dump($user_id_h));
results in 31. OK, that's ASCII code for the character "1". But why is unpack treating it as a string? Probably because Perl doesn't differentiate internally between strings and numbers. So can I tell Perl it's a number? Treating it as an integer, such as
unpack("l>", 1);
results in undefined. I feel like there are probably some concepts I am missing here. Am I on the right lines with unpacl? How do I get from a perl number hard-coded or loaded from a config file to the big-endian binary octets that represent that number to pass to Digest::SHA? I am on (little-endian) Intel. In this Java implementation at line 385 the User ID is treated as a java Long, and then the ByteBuffer method putLong() is used to just do the right thing, whatever that is.

Replies are listed 'Best First'.
Re: Converting integer to bytes
by choroba (Archbishop) on Jan 07, 2021 at 11:36 UTC
    As you recognised, you first need to convert the string "1" to the actual 8-byte big-endian integer.
    my $eight_bytes = pack 'Q>', $user_id;
    You can use unpack to get the hex representation back to verify it's correct:
    my $hex = unpack 'H16', $eight_bytes;

    Update: renamed $int to $eight_bytes as the value is not an integer in Perl's sense.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Converting integer to bytes
by shmem (Chancellor) on Jan 07, 2021 at 11:35 UTC

    If you are sure the user ID is an integer:

    my $user_id_h = unpack("H*", pack("Q>",$user_id)); print(dump($user_id_h));
    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
Re: Converting integer to bytes
by realflash (Initiate) on Jan 07, 2021 at 11:11 UTC
    Not intended to be anonymous, that was me.
      Probably because Perl doesn't differentiate internally between strings and numbers. So can I tell Perl it's a number?
      Perl does know whether a variable is a string or a number. Normally this is of no consequence because Perl "does the right thing" (usually).
      You can tell Perl to explicitly convert a string to a number by simply doing some math on the variable! One use for this is to remove leading zeroes. $var="000123"; $var +=0; Now $var is 123 because it is flagged internally as numeric. Of course if $var is already being used as a numeric value, adding zero to it is harmless.

      Update: More fun with strings...Occasionally seen when using the DB. Sometimes it is necessary to return essentially 2 values: a)the operation "worked" and b) the result is numeric zero.

      use strict; use warnings; my $var = " 0123"; $var += 0; print "$var\n"; $var = "0 but true"; $var += 0; print "$var\n"; $var = "0E0"; $var += 0; print "$var\n"; __END__ Prints: 123 0 0
      The string "0 but true" is hardcoded into Perl as an exception. This is logically "true" but numerically 0.
      If we had "zero but true", that throws a warning: "Argument "zero but true" isn't numeric in addition (+) at...", but you get numeric 0 anyway.
Re: Converting integer to bytes
by realflash (Initiate) on Jan 11, 2021 at 09:35 UTC
    Thank you to everyone. My false thinking here was that unpack is a thing you use to convert strings into bytes because that's what I see it used for a lot, instead of thinking of it and pack more generically as "things you use to convert to and from lists and formats", thus I didn't think to look at pack.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11126521]
Approved by marto
Front-paged by haukex
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2021-01-22 01:08 GMT
Find Nodes?
    Voting Booth?