sha3_digest Subroutine

public subroutine sha3_digest(state, digest)

!GFORTRAN 8.3 BUG!*!state%buffer( state%r/8 ) = transfer(int(b‘10000110’,kind=int8),state%buffer(1))

!GFORTRAN 8.3 BUG!!state%buffer( state%r/8 ) = transfer(int(b‘10000000’,kind=int8),state%buffer(1)) $ do $ i = min( r/8, d/8 - j ) $ sha3_sponge(j+1:j+i) = S(1:i) ! get r bits from state $ j = j + i ! update the number of bytes outputted $ ! exit when we have enough $ if ( j >= d/8 ) exit $ ! otherwise, continue squeezing $ S = sha3_keccak_p( S, 25W, 2*ELL+12 ) $ enddo

Arguments

Type IntentOptional Attributes Name
type(sha3_state), intent(inout) :: state
integer(kind=int8), intent(out), dimension(:) :: digest

Source Code

subroutine sha3_digest( state, digest )

  type(sha3_state),         intent(inout) :: state
  integer(kind=int8), dimension(:), intent(out)   :: digest

  integer(kind=int8) :: bug
  integer :: i, j
  integer(kind=int8), dimension(25*LANE) :: string

  ! it remains to apply padding the the current buffer, add this to sponge
  ! apply keccak, and squeeze

  ! the problem may be that, depending on the size of the buffer, we may have
  ! one or two r-bits blocks after padding
  digest = 0_int8

  ! proceed to padding. in here, we know that bufsize is strictly less than r/8 bytes
  ! (contrary to the sha3 function)
  i = mod( state%bufsize + 1, state%r/8 ) ! how many bytes to add
  if ( i == 0 ) then
     ! just add one byte for padding, and we have a full block ready to hash

     !>>>>>>>>>>>>
     !*!GFORTRAN 8.3 BUG!*!state%buffer( state%r/8 ) = transfer(int(b'10000110',kind=int8),state%buffer(1))
     bug=setbits8('10000110')
     state%buffer( state%r/8 ) = transfer(bug,state%buffer(1))
     !<<<<<<<<<<<<

  else
     state%buffer( state%bufsize + 1 ) = transfer(int(b'00000110',kind=int8),state%buffer(1))
     state%buffer( state%bufsize + 2 : state%r/8 - 1 ) = 0_int8

     !>>>>>>>>>>>>
     !*!GFORTRAN 8.3 BUG!*!state%buffer( state%r/8 ) = transfer(int(b'10000000',kind=int8),state%buffer(1))
     bug=setbits8('10000000')
     state%buffer( state%r/8 ) = transfer(bug,state%buffer(1))
     !<<<<<<<<<<<<

  endif

  ! absorb this last block...
  call sha3_block( state%S, state%buffer(1:state%r/8), state%r/8 )

  ! ...and squeeze
  if ( state%d < state%r ) then
     ! go back from state matrix to string
     string = sha3_state2string2( state%S, 25*W/8 )
     digest = string(1:state%d/8)
     do i = 1, state%d/8
        digest(i) = sha3_reverse(digest(i))
     enddo
  else
     j = 0 ! number of bytes currently outputted
!!$     do
!!$        i = min( r/8, d/8 - j )
!!$        sha3_sponge(j+1:j+i) = S(1:i) ! get r bits from state
!!$        j = j + i ! update the number of bytes outputted
!!$        ! exit when we have enough
!!$        if ( j >= d/8 ) exit
!!$        ! otherwise, continue squeezing
!!$        S = sha3_keccak_p( S, 25*W, 2*ELL+12 )
!!$     enddo
  endif

  ! once the digest has been provide, there are some tasks to perform
  ! (reinit the state and deallocation)
  deallocate( state%buffer )
  nullify( state%buffer )
  state%bufsize = -1

end subroutine sha3_digest