wp/wp-includes/sodium_compat/src/Core/AEGIS128L.php
changeset 22 8c2e4d02f4ef
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
       
     1 <?php
       
     2 
       
     3 if (!defined('SODIUM_COMPAT_AEGIS_C0')) {
       
     4     define('SODIUM_COMPAT_AEGIS_C0', "\x00\x01\x01\x02\x03\x05\x08\x0d\x15\x22\x37\x59\x90\xe9\x79\x62");
       
     5 }
       
     6 if (!defined('SODIUM_COMPAT_AEGIS_C1')) {
       
     7     define('SODIUM_COMPAT_AEGIS_C1', "\xdb\x3d\x18\x55\x6d\xc2\x2f\xf1\x20\x11\x31\x42\x73\xb5\x28\xdd");
       
     8 }
       
     9 
       
    10 class ParagonIE_Sodium_Core_AEGIS128L extends ParagonIE_Sodium_Core_AES
       
    11 {
       
    12     /**
       
    13      * @param string $ct
       
    14      * @param string $tag
       
    15      * @param string $ad
       
    16      * @param string $key
       
    17      * @param string $nonce
       
    18      * @return string
       
    19      * @throws SodiumException
       
    20      */
       
    21     public static function decrypt($ct, $tag, $ad, $key, $nonce)
       
    22     {
       
    23         $state = self::init($key, $nonce);
       
    24         $ad_blocks = (self::strlen($ad) + 31) >> 5;
       
    25         for ($i = 0; $i < $ad_blocks; ++$i) {
       
    26             $ai = self::substr($ad, $i << 5, 32);
       
    27             if (self::strlen($ai) < 32) {
       
    28                 $ai = str_pad($ai, 32, "\0", STR_PAD_RIGHT);
       
    29             }
       
    30             $state->absorb($ai);
       
    31         }
       
    32 
       
    33         $msg = '';
       
    34         $cn = self::strlen($ct) & 31;
       
    35         $ct_blocks = self::strlen($ct) >> 5;
       
    36         for ($i = 0; $i < $ct_blocks; ++$i) {
       
    37             $msg .= $state->dec(self::substr($ct, $i << 5, 32));
       
    38         }
       
    39         if ($cn) {
       
    40             $start = $ct_blocks << 5;
       
    41             $msg .= $state->decPartial(self::substr($ct, $start, $cn));
       
    42         }
       
    43         $expected_tag = $state->finalize(
       
    44             self::strlen($ad) << 3,
       
    45             self::strlen($msg) << 3
       
    46         );
       
    47         if (!self::hashEquals($expected_tag, $tag)) {
       
    48             try {
       
    49                 // The RFC says to erase msg, so we shall try:
       
    50                 ParagonIE_Sodium_Compat::memzero($msg);
       
    51             } catch (SodiumException $ex) {
       
    52                 // Do nothing if we cannot memzero
       
    53             }
       
    54             throw new SodiumException('verification failed');
       
    55         }
       
    56         return $msg;
       
    57     }
       
    58 
       
    59     /**
       
    60      * @param string $msg
       
    61      * @param string $ad
       
    62      * @param string $key
       
    63      * @param string $nonce
       
    64      * @return array
       
    65      *
       
    66      * @throws SodiumException
       
    67      */
       
    68     public static function encrypt($msg, $ad, $key, $nonce)
       
    69     {
       
    70         $state = self::init($key, $nonce);
       
    71         // ad_blocks = Split(ZeroPad(ad, 256), 256)
       
    72         // for ai in ad_blocks:
       
    73         //     Absorb(ai)
       
    74         $ad_len = self::strlen($ad);
       
    75         $msg_len = self::strlen($msg);
       
    76         $ad_blocks = ($ad_len + 31) >> 5;
       
    77         for ($i = 0; $i < $ad_blocks; ++$i) {
       
    78             $ai = self::substr($ad, $i << 5, 32);
       
    79             if (self::strlen($ai) < 32) {
       
    80                 $ai = str_pad($ai, 32, "\0", STR_PAD_RIGHT);
       
    81             }
       
    82             $state->absorb($ai);
       
    83         }
       
    84 
       
    85         // msg_blocks = Split(ZeroPad(msg, 256), 256)
       
    86         // for xi in msg_blocks:
       
    87         //     ct = ct || Enc(xi)
       
    88         $ct = '';
       
    89         $msg_blocks = ($msg_len + 31) >> 5;
       
    90         for ($i = 0; $i < $msg_blocks; ++$i) {
       
    91             $xi = self::substr($msg, $i << 5, 32);
       
    92             if (self::strlen($xi) < 32) {
       
    93                 $xi = str_pad($xi, 32, "\0", STR_PAD_RIGHT);
       
    94             }
       
    95             $ct .= $state->enc($xi);
       
    96         }
       
    97         // tag = Finalize(|ad|, |msg|)
       
    98         // ct = Truncate(ct, |msg|)
       
    99         $tag = $state->finalize(
       
   100             $ad_len << 3,
       
   101             $msg_len << 3
       
   102         );
       
   103         // return ct and tag
       
   104         return array(
       
   105             self::substr($ct, 0, $msg_len),
       
   106             $tag
       
   107         );
       
   108     }
       
   109 
       
   110     /**
       
   111      * @param string $key
       
   112      * @param string $nonce
       
   113      * @return ParagonIE_Sodium_Core_AEGIS_State128L
       
   114      */
       
   115     public static function init($key, $nonce)
       
   116     {
       
   117         return ParagonIE_Sodium_Core_AEGIS_State128L::init($key, $nonce);
       
   118     }
       
   119 }