sha256 Function

public function sha256(str)

For the sha256 and dirty_sha256 procedures and supporting private routines:

Copyright (c) 2014 Mikael Leetmaa

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you must not
      claim that you wrote the original software. If you use this software
      in a product, an acknowledgment in the product documentation would be
      appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
      distribution.

NAME

sha256(3f) - [M_hashkeys] generate a SHA-256 hashing

SYNOPSIS

function sha256(str)

character(len=64)            :: sha256
character(len=*), intent(in) :: str

DESCRIPTION

A Fortran module for SHA-256 hashing.

Note that this code will not produce the same results on big-endian
machines and the module was only tested on a little-endian Ubuntu LTS
12.04 system using gfortran 4.6.3.

OPTIONS

str      The message to digest.

RETURNS

sha256   The SHA-256 digest as a string of length 64.

COMPILE NOTES

The '-fno-range-check' flag is required on gfortran(1) since the
Fortran standard otherwise doesn't currently allow us to work with
all bits in the integers (as if they were unsigned).

AUTHOR

This routine is heavily based on the SHA-256 routines by
Mikael Leetmaa <leetmaa@kth.se>, 2014-01-05. changes have
been made to incorporate it into the GPF (General Purpose Fortran)
framework.

If you found this useful, please let Mikael Leetmaa know.

EXAMPLE

Sample program:

program demo_sha256
use M_hashkeys, only : sha256, dirty_sha256
implicit none
character(len=:),allocatable :: str
character(len=64)            :: ref

! Test the sha256 function with a set of reference strings.

str=""
ref="E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"
call unit_check('sha256',sha256(str)==ref,'test sha256 1')

str="abc"
ref="BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"
call unit_check('sha256',sha256(str)==ref,'test sha256 2')

str="abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
ref="248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1"
call unit_check('sha256',sha256(str)==ref,'test sha256 3')

str="abcdefghbcdefghicdefghijdefghijkefghijklfghi&
     &jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
ref="CF5B16A778AF8380036CE59E7B0492370B249B11E8F07A51AFAC45037AFEE9D1"
call unit_check('sha256',sha256(str)==ref,'test sha256 4')

str=repeat("a",1000000)
ref="CDC76E5C9914FB9281A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0"
call unit_check('sha256',sha256(str)==ref,'test sha256 5')

str="message digest"
ref="F7846F55CF23E14EEBEAB5B4E1550CAD5B509E3348FBC4EFA3A1413D393CB650"
call unit_check('sha256',sha256(str)==ref,'test sha256 6')

str="secure hash algorithm"
ref="F30CEB2BB2829E79E4CA9753D35A8ECC00262D164CC077080295381CBD643F0D"
call unit_check('sha256',sha256(str)==ref,'test sha256 7')

str="SHA256 is considered to be safe"
ref="6819D915C73F4D1E77E4E1B52D1FA0F9CF9BEAEAD3939F15874BD988E2A23630"
call unit_check('sha256',sha256(str)==ref,'test sha256 8')

str="For this sample, this 63-byte string will be used as input data"
ref="F08A78CBBAEE082B052AE0708F32FA1E50C5C421AA772BA5DBB406A2EA6BE342"
call unit_check('sha256',sha256(str)==ref,'test sha256 9')

str="This is exactly 64 bytes long, not counting the terminating byte"
ref="AB64EFF7E88E2E46165E29F2BCE41826BD4C7B3552F6B382A9E7D3AF47C245F8"
call unit_check('sha256',sha256(str)==ref,'test sha256 10')

! Check the quick and dirty implementation as well.
ref="69E3FACD5F08321F78117BD53476E5321845433356F106E7013E68EC367F3017"
call unit_check('sha256',dirty_sha256(str)==ref,'test dirtysha256 1')

!!str=repeat("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno",16777216)
!!ref="50E72A0E26442FE2552DC3938AC58658228C0CBFB1D2CA872AE435266FCD055E"
!!call unit_check('sha256',sha256(str)==ref,'test sha256 11 -- long test')

contains
subroutine unit_check(name,test,message)
character(len=*),intent(in) :: name
logical,intent(in)          :: test
character(len=*),intent(in) :: message
   write(*,'(a)') repeat("=",64)
   write(*,'(a)') sha256(str)
   write(*,'(a)') ref
   if(test)then
      write(*,*)trim(name)," PASSED: ",trim(message)
   else
      write(*,*)trim(name)," FAILED: ",trim(message)
   endif
end subroutine unit_check
!
end program demo_sha256

UNIT TEST

When porting to a new programming environment use the built-in unit test …

program test_sha256
use M_hashkeys, only : test_suite_sha256
   call test_suite_sha256()
end program test_sha256

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: str

Return Value character(len=64)


Source Code

function sha256(str)
implicit none

! ident_1="@(#) M_hashkeys sha256(3f) SHA-256 interface function"

! Define the interface.
character(len=64) :: sha256           ! The SHA-256 digest as a string of length 64.
character(len=*), intent(in) :: str   ! (in) The message to digest.
! Call the work horse with proper bit swapping.
      sha256 = sha256b(str, 1)
end function sha256