If at all possible, pull something off the shelf. You do not want to roll back your own implementation of SHA-256, because in order to receive an official blessing, you will need to certify it.
However, the specification
5.1.1 SHA-1, SHA-224 and SHA-256
Suppose the message length, M, is 1 bit. Add bit 1
to the end of the message, followed by k zero bits, where k is the smallest non-negative solution to the equation
l + 1 + k & equiv; 448 mod 512
Then add a 64-bit block, which is equal to the number l, expressed using a binary representation. For example, the message (8-bit ASCII) " abc " has a length of 8 × 3 = 24, so the message is filled with one bit, then 448 - (24 + 1) = 423 zero bits, and then the message length to become 512-bit padded message
423 64 .-^-. .---^---. 01100001 01100010 01100011 1 00…00 00…011000 "a" "b" "c" '-v-' l=24
Then the length of the filled message should be a multiple of 512 bits.
You may be tempted to use vec
as it allows you to access single bits, but you will have to work with funk addresses.
If the bit is 4 or less, the string is split into bytes, then the bit of each byte is split into 8 / BITS groups. Byte bits are numbered in a small sequence, as in 0x01
, 0x02
, 0x04
, 0x08
, 0x10
, 0x20
, 0x40
, 0x80
. For example, splitting a single input byte chr(0x36)
into two groups gives a list (0x6, 0x3)
; dividing it into 4 groups, we obtain (0x2, 0x1, 0x3, 0x0)
.
Instead, pack
template B*
indicates
Bit string (descending bit order within each byte).
and N
Unfamiliar long (32-bit) in the "network" (big-endian) order.
The latter is useful for building message lengths. Although pack
has the Q
parameter for quad, the result is in native order.
Start with a bit of preparatory work.
our($UPPER32BITS,$LOWER32BITS); BEGIN { use Config; die "$0: $^X not configured for 64-bit ints" unless $Config{use64bitint};
Then you can define pad_message
as
sub pad_message { use bytes; my($msg) = @_; my $l = bytes::length($msg) * 8; my $extra = $l % 512;
Say the code prints the completed message with
my $padded = pad_message "abc"; # break into multiple lines for readability for (unpack("H*", $padded) =~ /(.{64})/g) { print $_, "\n"; }
Then conclusion
61626380000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000018
which meets the specification.