You are here

public static function ParagonIE_Sodium_File::verify in Automatic Updates 8

Same name and namespace in other branches
  1. 7 vendor/paragonie/sodium_compat/src/File.php \ParagonIE_Sodium_File::verify()

Verify a file (rather than a string). Uses less memory than ParagonIE_Sodium_Compat::crypto_sign_verify_detached(), but produces the same result.

Parameters

string $sig Ed25519 signature:

string $filePath Absolute path to a file on the filesystem:

string $publicKey Signing public key:

Return value

bool

Throws

SodiumException

TypeError

Exception

File

vendor/paragonie/sodium_compat/src/File.php, line 657

Class

ParagonIE_Sodium_File
Class ParagonIE_Sodium_File

Code

public static function verify($sig, $filePath, $publicKey) {

  /* Type checks: */
  if (!is_string($sig)) {
    throw new TypeError('Argument 1 must be a string, ' . gettype($sig) . ' given.');
  }
  if (!is_string($filePath)) {
    throw new TypeError('Argument 2 must be a string, ' . gettype($filePath) . ' given.');
  }
  if (!is_string($publicKey)) {
    throw new TypeError('Argument 3 must be a string, ' . gettype($publicKey) . ' given.');
  }

  /* Input validation: */
  if (self::strlen($sig) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_BYTES) {
    throw new TypeError('Argument 1 must be CRYPTO_SIGN_BYTES bytes');
  }
  if (self::strlen($publicKey) !== ParagonIE_Sodium_Compat::CRYPTO_SIGN_PUBLICKEYBYTES) {
    throw new TypeError('Argument 3 must be CRYPTO_SIGN_PUBLICKEYBYTES bytes');
  }
  if (self::strlen($sig) < 64) {
    throw new SodiumException('Signature is too short');
  }
  if (PHP_INT_SIZE === 4) {
    return self::verify_core32($sig, $filePath, $publicKey);
  }

  /* Security checks */
  if (ParagonIE_Sodium_Core_Ed25519::chrToInt($sig[63]) & 240 && ParagonIE_Sodium_Core_Ed25519::check_S_lt_L(self::substr($sig, 32, 32))) {
    throw new SodiumException('S < L - Invalid signature');
  }
  if (ParagonIE_Sodium_Core_Ed25519::small_order($sig)) {
    throw new SodiumException('Signature is on too small of an order');
  }
  if ((self::chrToInt($sig[63]) & 224) !== 0) {
    throw new SodiumException('Invalid signature');
  }
  $d = 0;
  for ($i = 0; $i < 32; ++$i) {
    $d |= self::chrToInt($publicKey[$i]);
  }
  if ($d === 0) {
    throw new SodiumException('All zero public key');
  }

  /** @var int $size */
  $size = filesize($filePath);
  if (!is_int($size)) {
    throw new SodiumException('Could not obtain the file size');
  }

  /** @var resource $fp */
  $fp = fopen($filePath, 'rb');
  if (!is_resource($fp)) {
    throw new SodiumException('Could not open input file for reading');
  }

  /** @var bool The original value of ParagonIE_Sodium_Compat::$fastMult */
  $orig = ParagonIE_Sodium_Compat::$fastMult;

  // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up verification.
  ParagonIE_Sodium_Compat::$fastMult = true;

  /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */
  $A = ParagonIE_Sodium_Core_Ed25519::ge_frombytes_negate_vartime($publicKey);
  $hs = hash_init('sha512');
  hash_update($hs, self::substr($sig, 0, 32));
  hash_update($hs, self::substr($publicKey, 0, 32));

  /** @var resource $hs */
  $hs = self::updateHashWithFile($hs, $fp, $size);

  /** @var string $hDigest */
  $hDigest = hash_final($hs, true);

  /** @var string $h */
  $h = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hDigest) . self::substr($hDigest, 32);

  /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */
  $R = ParagonIE_Sodium_Core_Ed25519::ge_double_scalarmult_vartime($h, $A, self::substr($sig, 32));

  /** @var string $rcheck */
  $rcheck = ParagonIE_Sodium_Core_Ed25519::ge_tobytes($R);

  // Close the file handle
  fclose($fp);

  // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
  ParagonIE_Sodium_Compat::$fastMult = $orig;
  return self::verify_32($rcheck, self::substr($sig, 0, 32));
}