You are here

public static function ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_pull in Automatic Updates 7

Same name and namespace in other branches
  1. 8 vendor/paragonie/sodium_compat/src/Crypto32.php \ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_pull()

Parameters

string $state:

string $cipher:

string $aad:

Return value

bool|array{0: string, 1: int}

Throws

SodiumException

1 call to ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_pull()
ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_pull in vendor/paragonie/sodium_compat/src/Compat.php

File

vendor/paragonie/sodium_compat/src/Crypto32.php, line 1426

Class

ParagonIE_Sodium_Crypto32
Class ParagonIE_Sodium_Crypto

Code

public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '') {
  $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);
  $cipherlen = ParagonIE_Sodium_Core32_Util::strlen($cipher);

  #     mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
  $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES;
  $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad);

  #     if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {

  #         sodium_misuse();

  #     }
  if ($msglen + 63 >> 6 > 0xfffffffe) {
    throw new SodiumException('message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes');
  }

  #     crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);

  #     crypto_onetimeauth_poly1305_init(&poly1305_state, block);

  #     sodium_memzero(block, sizeof block);
  $auth = new ParagonIE_Sodium_Core32_Poly1305_State(ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st
    ->getCombinedNonce(), $st
    ->getKey()));

  #     crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
  $auth
    ->update($aad);

  #     crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,

  #         (0x10 - adlen) & 0xf);
  $auth
    ->update(str_repeat("\0", 0x10 - $aadlen & 0xf));

  #     memset(block, 0, sizeof block);

  #     block[0] = in[0];

  #     crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,

  #                                        state->nonce, 1U, state->k);
  $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc($cipher[0] . str_repeat("\0", 63), $st
    ->getCombinedNonce(), $st
    ->getKey(), ParagonIE_Sodium_Core32_Util::store64_le(1));

  #     tag = block[0];

  #     block[0] = in[0];

  #     crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
  $tag = ParagonIE_Sodium_Core32_Util::chrToInt($block[0]);
  $block[0] = $cipher[0];
  $auth
    ->update($block);

  #     c = in + (sizeof tag);

  #     crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
  $auth
    ->update(ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen));

  #     crypto_onetimeauth_poly1305_update

  #     (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
  $auth
    ->update(str_repeat("\0", 0x10 - 64 + $msglen & 0xf));

  #     STORE64_LE(slen, (uint64_t) adlen);

  #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
  $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen);
  $auth
    ->update($slen);

  #     STORE64_LE(slen, (sizeof block) + mlen);

  #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
  $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen);
  $auth
    ->update($slen);

  #     crypto_onetimeauth_poly1305_final(&poly1305_state, mac);

  #     sodium_memzero(&poly1305_state, sizeof poly1305_state);
  $mac = $auth
    ->finish();

  #     stored_mac = c + mlen;

  #     if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {

  #     sodium_memzero(mac, sizeof mac);

  #         return -1;

  #     }
  $stored = ParagonIE_Sodium_Core32_Util::substr($cipher, $msglen + 1, 16);
  if (!ParagonIE_Sodium_Core32_Util::hashEquals($mac, $stored)) {
    return false;
  }

  #     crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
  $out = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen), $st
    ->getCombinedNonce(), $st
    ->getKey(), ParagonIE_Sodium_Core32_Util::store64_le(2));

  #     XOR_BUF(STATE_INONCE(state), mac,

  #         crypto_secretstream_xchacha20poly1305_INONCEBYTES);
  $st
    ->xorNonce($mac);

  #     sodium_increment(STATE_COUNTER(state),

  #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
  $st
    ->incrementCounter();

  #     if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||

  #         sodium_is_zero(STATE_COUNTER(state),

  #             crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {

  #         crypto_secretstream_xchacha20poly1305_rekey(state);

  #     }

  // Overwrite by reference:
  $state = $st
    ->toString();

  /** @var bool $rekey */
  $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0;
  if ($rekey || $st
    ->needsRekey()) {

    // DO REKEY
    self::secretstream_xchacha20poly1305_rekey($state);
  }
  return array(
    $out,
    $tag,
  );
}