Search code examples
perl

Writing a custom base64 encoding function in perl


I'm trying to learn perl by writing a custom base64 encoding function, unfortunately I've had no success by now. What I've come to is the following, which doesn't work and I unfortunately don't have any clue about how to proceed.

sub base64($) {
  # Split string into single bits
  my $bitstring = unpack("B*", $_[0]);
  # Pack bits in pieces of six bits at a time
  my @splitsixs = unpack("(A6)*", $bitstring);
  my @enc = ("A".."Z", "a".."z", "0".."9", "+", "/");
  # For each piece of six bits, convert them to integer, and take the corresponding place in @enc.
  my @s = map { $enc[pack("B6", $_)] } @splitsixs;
  join "", @s;
}

Can someone explain to me what am I doing wrong in this conversion? (Please leave aside for now the fact that I'm not considering padding)


Solution

  • I finally made it! I was erroneously trying to indexing elements in $enc directly via packed bytes, while I should convert them first into integers. You can see this in the lines below. I copy the entire function, padding included, in the hope that it might be useful to others.

    sub base64($) {
      # Split string into single bits
      my $bitstring = unpack("B*", $_[0]);
      # Pack bits in pieces of six bits at a time
      my @sixs = unpack("(A6)*", $bitstring);
      # Compute the amount of zero padding necessary to obtain a 6-aligned bitstring
      my $padding = ((6 - (length $sixs[-1]) % 6) % 6);
      $sixs[-1] = join "", ($sixs[-1], "0" x $padding);
      # Array of mapping from pieces to encodings
      my @enc = ("A".."Z", "a".."z", "0".."9", "+", "/");
      # Unpack bit strings into integers
      @sixs = map { unpack("c", pack("b6", join "", reverse(split "", $_))) } @sixs;
      # For each integer take the corresponding place in @enc.
      my @s = map { $enc[$_] } @sixs;
      # Concatenate string adding necessary padding
      join "", (@s, "=" x ($padding / 2));
    }