#!/usr/bin/env perl

##
## Author......: See docs/credits.txt
## License.....: MIT
##

use strict;
use warnings;

use Digest::SHA qw (sha256);

sub module_constraints { [[0, 127], [32, 32], [0, 31], [32, 32], [-1, -1]] }

sub module_generate_hash
{
  my $word = shift;
  my $id   = shift;
  my $rest = shift;

  if (defined $id == 0)
  {
    $id = "0" x 32;
  }

  if (defined $rest == 0)
  {
    $rest = "127*";
    $rest .= "0" x 64;
    $rest .= $id;
    $rest .= "0" x 158;
    $rest .= "*127*00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000*32*0000000000000000000000000000000000000000000000000000000000000000*32*0000000000000000000000000000000000000000000000000000000000000000";
  }

  my @data = split /\*/, $rest;

  my $u = pack ("H*", $data[1]);

  my $h = sha256 ($word . substr ($u, 32, 8));

  $data[1] = unpack ("H*", $h . substr ($u, 32));

  $rest = join ("*", @data);

  my $hash = sprintf ('$pdf$5*5*256*-1028*1*16*%s*%s', $id, $rest);

  return $hash;
}

sub module_verify_hash
{
  my $line = shift;

  # PDF 1.7 Level 3 (Acrobat 9)
  my ($hash_in, $word) = split ":", $line;

  return unless defined $hash_in;
  return unless defined $word;

  my @data = split /\*/, $hash_in;

  return unless scalar @data >= 11;

  return unless (shift @data eq '$pdf$5');
  return unless (shift @data eq '5');
  return unless (shift @data eq '256');
  return unless (shift @data eq '-1028');
  return unless (shift @data eq '1');
  return unless (shift @data eq '16');

  my $id   = shift @data;
  my $rest = join "*", @data;

  return unless defined $id;
  return unless defined $rest;
  return unless defined $word;

  $word = pack_if_HEX_notation ($word);

  my $new_hash = module_generate_hash ($word, $id, $rest);

  return ($new_hash, $word);
}

1;