76 const CRYPTO_BOX_PUBLICKEYBYTES = 32; |
78 const CRYPTO_BOX_PUBLICKEYBYTES = 32; |
77 const CRYPTO_BOX_KEYPAIRBYTES = 64; |
79 const CRYPTO_BOX_KEYPAIRBYTES = 64; |
78 const CRYPTO_BOX_MACBYTES = 16; |
80 const CRYPTO_BOX_MACBYTES = 16; |
79 const CRYPTO_BOX_NONCEBYTES = 24; |
81 const CRYPTO_BOX_NONCEBYTES = 24; |
80 const CRYPTO_BOX_SEEDBYTES = 32; |
82 const CRYPTO_BOX_SEEDBYTES = 32; |
|
83 const CRYPTO_CORE_RISTRETTO255_BYTES = 32; |
|
84 const CRYPTO_CORE_RISTRETTO255_SCALARBYTES = 32; |
|
85 const CRYPTO_CORE_RISTRETTO255_HASHBYTES = 64; |
|
86 const CRYPTO_CORE_RISTRETTO255_NONREDUCEDSCALARBYTES = 64; |
81 const CRYPTO_KDF_BYTES_MIN = 16; |
87 const CRYPTO_KDF_BYTES_MIN = 16; |
82 const CRYPTO_KDF_BYTES_MAX = 64; |
88 const CRYPTO_KDF_BYTES_MAX = 64; |
83 const CRYPTO_KDF_CONTEXTBYTES = 8; |
89 const CRYPTO_KDF_CONTEXTBYTES = 8; |
84 const CRYPTO_KDF_KEYBYTES = 32; |
90 const CRYPTO_KDF_KEYBYTES = 32; |
85 const CRYPTO_KX_BYTES = 32; |
91 const CRYPTO_KX_BYTES = 32; |
1684 * |
1704 * |
1685 * @param string $my_secret |
1705 * @param string $my_secret |
1686 * @param string $their_public |
1706 * @param string $their_public |
1687 * @param string $client_public |
1707 * @param string $client_public |
1688 * @param string $server_public |
1708 * @param string $server_public |
1689 * @return string |
1709 * @param bool $dontFallback |
1690 * @throws SodiumException |
1710 * @return string |
1691 * @throws TypeError |
1711 * @throws SodiumException |
1692 * @psalm-suppress MixedArgument |
1712 * @throws TypeError |
1693 */ |
1713 * @psalm-suppress MixedArgument |
1694 public static function crypto_kx($my_secret, $their_public, $client_public, $server_public) |
1714 */ |
|
1715 public static function crypto_kx($my_secret, $their_public, $client_public, $server_public, $dontFallback = false) |
1695 { |
1716 { |
1696 /* Type checks: */ |
1717 /* Type checks: */ |
1697 ParagonIE_Sodium_Core_Util::declareScalarType($my_secret, 'string', 1); |
1718 ParagonIE_Sodium_Core_Util::declareScalarType($my_secret, 'string', 1); |
1698 ParagonIE_Sodium_Core_Util::declareScalarType($their_public, 'string', 2); |
1719 ParagonIE_Sodium_Core_Util::declareScalarType($their_public, 'string', 2); |
1699 ParagonIE_Sodium_Core_Util::declareScalarType($client_public, 'string', 3); |
1720 ParagonIE_Sodium_Core_Util::declareScalarType($client_public, 'string', 3); |
3046 public static function crypto_stream_keygen() |
3067 public static function crypto_stream_keygen() |
3047 { |
3068 { |
3048 return random_bytes(self::CRYPTO_STREAM_KEYBYTES); |
3069 return random_bytes(self::CRYPTO_STREAM_KEYBYTES); |
3049 } |
3070 } |
3050 |
3071 |
|
3072 |
|
3073 /** |
|
3074 * Expand a key and nonce into a keystream of pseudorandom bytes. |
|
3075 * |
|
3076 * @param int $len Number of bytes desired |
|
3077 * @param string $nonce Number to be used Once; must be 24 bytes |
|
3078 * @param string $key XChaCha20 key |
|
3079 * @param bool $dontFallback |
|
3080 * @return string Pseudorandom stream that can be XORed with messages |
|
3081 * to provide encryption (but not authentication; see |
|
3082 * Poly1305 or crypto_auth() for that, which is not |
|
3083 * optional for security) |
|
3084 * @throws SodiumException |
|
3085 * @throws TypeError |
|
3086 * @psalm-suppress MixedArgument |
|
3087 */ |
|
3088 public static function crypto_stream_xchacha20($len, $nonce, $key, $dontFallback = false) |
|
3089 { |
|
3090 /* Type checks: */ |
|
3091 ParagonIE_Sodium_Core_Util::declareScalarType($len, 'int', 1); |
|
3092 ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); |
|
3093 ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); |
|
3094 |
|
3095 /* Input validation: */ |
|
3096 if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { |
|
3097 throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); |
|
3098 } |
|
3099 if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { |
|
3100 throw new SodiumException('Argument 3 must be CRYPTO_STREAM_XCHACHA20_KEYBYTES long.'); |
|
3101 } |
|
3102 |
|
3103 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3104 return sodium_crypto_stream_xchacha20($len, $nonce, $key); |
|
3105 } |
|
3106 if (PHP_INT_SIZE === 4) { |
|
3107 return ParagonIE_Sodium_Core32_XChaCha20::stream($len, $nonce, $key); |
|
3108 } |
|
3109 return ParagonIE_Sodium_Core_XChaCha20::stream($len, $nonce, $key); |
|
3110 } |
|
3111 |
|
3112 /** |
|
3113 * DANGER! UNAUTHENTICATED ENCRYPTION! |
|
3114 * |
|
3115 * Unless you are following expert advice, do not used this feature. |
|
3116 * |
|
3117 * Algorithm: XChaCha20 |
|
3118 * |
|
3119 * This DOES NOT provide ciphertext integrity. |
|
3120 * |
|
3121 * @param string $message Plaintext message |
|
3122 * @param string $nonce Number to be used Once; must be 24 bytes |
|
3123 * @param string $key Encryption key |
|
3124 * @return string Encrypted text which is vulnerable to chosen- |
|
3125 * ciphertext attacks unless you implement some |
|
3126 * other mitigation to the ciphertext (i.e. |
|
3127 * Encrypt then MAC) |
|
3128 * @param bool $dontFallback |
|
3129 * @throws SodiumException |
|
3130 * @throws TypeError |
|
3131 * @psalm-suppress MixedArgument |
|
3132 */ |
|
3133 public static function crypto_stream_xchacha20_xor($message, $nonce, $key, $dontFallback = false) |
|
3134 { |
|
3135 /* Type checks: */ |
|
3136 ParagonIE_Sodium_Core_Util::declareScalarType($message, 'string', 1); |
|
3137 ParagonIE_Sodium_Core_Util::declareScalarType($nonce, 'string', 2); |
|
3138 ParagonIE_Sodium_Core_Util::declareScalarType($key, 'string', 3); |
|
3139 |
|
3140 /* Input validation: */ |
|
3141 if (ParagonIE_Sodium_Core_Util::strlen($nonce) !== self::CRYPTO_STREAM_XCHACHA20_NONCEBYTES) { |
|
3142 throw new SodiumException('Argument 2 must be CRYPTO_SECRETBOX_XCHACHA20_NONCEBYTES long.'); |
|
3143 } |
|
3144 if (ParagonIE_Sodium_Core_Util::strlen($key) !== self::CRYPTO_STREAM_XCHACHA20_KEYBYTES) { |
|
3145 throw new SodiumException('Argument 3 must be CRYPTO_SECRETBOX_XCHACHA20_KEYBYTES long.'); |
|
3146 } |
|
3147 |
|
3148 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3149 return sodium_crypto_stream_xchacha20_xor($message, $nonce, $key); |
|
3150 } |
|
3151 if (PHP_INT_SIZE === 4) { |
|
3152 return ParagonIE_Sodium_Core32_XChaCha20::streamXorIc($message, $nonce, $key); |
|
3153 } |
|
3154 return ParagonIE_Sodium_Core_XChaCha20::streamXorIc($message, $nonce, $key); |
|
3155 } |
|
3156 |
|
3157 /** |
|
3158 * Return a secure random key for use with crypto_stream_xchacha20 |
|
3159 * |
|
3160 * @return string |
|
3161 * @throws Exception |
|
3162 * @throws Error |
|
3163 */ |
|
3164 public static function crypto_stream_xchacha20_keygen() |
|
3165 { |
|
3166 return random_bytes(self::CRYPTO_STREAM_XCHACHA20_KEYBYTES); |
|
3167 } |
|
3168 |
3051 /** |
3169 /** |
3052 * Cache-timing-safe implementation of hex2bin(). |
3170 * Cache-timing-safe implementation of hex2bin(). |
3053 * |
3171 * |
3054 * @param string $string Hexadecimal string |
3172 * @param string $string Hexadecimal string |
3055 * @return string Raw binary string |
3173 * @return string Raw binary string |
3111 } |
3229 } |
3112 $var = $copy; |
3230 $var = $copy; |
3113 } |
3231 } |
3114 |
3232 |
3115 /** |
3233 /** |
|
3234 * @param string $str |
|
3235 * @return bool |
|
3236 * |
|
3237 * @throws SodiumException |
|
3238 */ |
|
3239 public static function is_zero($str) |
|
3240 { |
|
3241 $d = 0; |
|
3242 for ($i = 0; $i < 32; ++$i) { |
|
3243 $d |= ParagonIE_Sodium_Core_Util::chrToInt($str[$i]); |
|
3244 } |
|
3245 return ((($d - 1) >> 31) & 1) === 1; |
|
3246 } |
|
3247 |
|
3248 /** |
3116 * The equivalent to the libsodium minor version we aim to be compatible |
3249 * The equivalent to the libsodium minor version we aim to be compatible |
3117 * with (sans pwhash and memzero). |
3250 * with (sans pwhash and memzero). |
3118 * |
3251 * |
3119 * @return int |
3252 * @return int |
3120 * @psalm-suppress MixedInferredReturnType |
|
3121 * @psalm-suppress UndefinedFunction |
|
3122 */ |
3253 */ |
3123 public static function library_version_major() |
3254 public static function library_version_major() |
3124 { |
3255 { |
3125 if (self::useNewSodiumAPI()) { |
3256 if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MAJOR_VERSION')) { |
3126 return sodium_library_version_major(); |
3257 return SODIUM_LIBRARY_MAJOR_VERSION; |
3127 } |
3258 } |
3128 if (self::use_fallback('library_version_major')) { |
3259 if (self::use_fallback('library_version_major')) { |
|
3260 /** @psalm-suppress UndefinedFunction */ |
3129 return (int) call_user_func('\\Sodium\\library_version_major'); |
3261 return (int) call_user_func('\\Sodium\\library_version_major'); |
3130 } |
3262 } |
3131 return self::LIBRARY_VERSION_MAJOR; |
3263 return self::LIBRARY_VERSION_MAJOR; |
3132 } |
3264 } |
3133 |
3265 |
3134 /** |
3266 /** |
3135 * The equivalent to the libsodium minor version we aim to be compatible |
3267 * The equivalent to the libsodium minor version we aim to be compatible |
3136 * with (sans pwhash and memzero). |
3268 * with (sans pwhash and memzero). |
3137 * |
3269 * |
3138 * @return int |
3270 * @return int |
3139 * @psalm-suppress MixedInferredReturnType |
|
3140 * @psalm-suppress UndefinedFunction |
|
3141 */ |
3271 */ |
3142 public static function library_version_minor() |
3272 public static function library_version_minor() |
3143 { |
3273 { |
3144 if (self::useNewSodiumAPI()) { |
3274 if (self::useNewSodiumAPI() && defined('SODIUM_LIBRARY_MINOR_VERSION')) { |
3145 return sodium_library_version_minor(); |
3275 return SODIUM_LIBRARY_MINOR_VERSION; |
3146 } |
3276 } |
3147 if (self::use_fallback('library_version_minor')) { |
3277 if (self::use_fallback('library_version_minor')) { |
|
3278 /** @psalm-suppress UndefinedFunction */ |
3148 return (int) call_user_func('\\Sodium\\library_version_minor'); |
3279 return (int) call_user_func('\\Sodium\\library_version_minor'); |
3149 } |
3280 } |
3150 return self::LIBRARY_VERSION_MINOR; |
3281 return self::LIBRARY_VERSION_MINOR; |
3151 } |
3282 } |
3152 |
3283 |
3450 } |
3581 } |
3451 return random_int(0, 65535); |
3582 return random_int(0, 65535); |
3452 } |
3583 } |
3453 |
3584 |
3454 /** |
3585 /** |
|
3586 * @param string $p |
|
3587 * @param bool $dontFallback |
|
3588 * @return bool |
|
3589 * @throws SodiumException |
|
3590 */ |
|
3591 public static function ristretto255_is_valid_point($p, $dontFallback = false) |
|
3592 { |
|
3593 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3594 return sodium_crypto_core_ristretto255_is_valid_point($p); |
|
3595 } |
|
3596 try { |
|
3597 $r = ParagonIE_Sodium_Core_Ristretto255::ristretto255_frombytes($p); |
|
3598 return $r['res'] === 0 && |
|
3599 ParagonIE_Sodium_Core_Ristretto255::ristretto255_point_is_canonical($p) === 1; |
|
3600 } catch (SodiumException $ex) { |
|
3601 if ($ex->getMessage() === 'S is not canonical') { |
|
3602 return false; |
|
3603 } |
|
3604 throw $ex; |
|
3605 } |
|
3606 } |
|
3607 |
|
3608 /** |
|
3609 * @param string $p |
|
3610 * @param string $q |
|
3611 * @param bool $dontFallback |
|
3612 * @return string |
|
3613 * @throws SodiumException |
|
3614 */ |
|
3615 public static function ristretto255_add($p, $q, $dontFallback = false) |
|
3616 { |
|
3617 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3618 return sodium_crypto_core_ristretto255_add($p, $q); |
|
3619 } |
|
3620 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_add($p, $q); |
|
3621 } |
|
3622 |
|
3623 /** |
|
3624 * @param string $p |
|
3625 * @param string $q |
|
3626 * @param bool $dontFallback |
|
3627 * @return string |
|
3628 * @throws SodiumException |
|
3629 */ |
|
3630 public static function ristretto255_sub($p, $q, $dontFallback = false) |
|
3631 { |
|
3632 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3633 return sodium_crypto_core_ristretto255_sub($p, $q); |
|
3634 } |
|
3635 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_sub($p, $q); |
|
3636 } |
|
3637 |
|
3638 /** |
|
3639 * @param string $r |
|
3640 * @param bool $dontFallback |
|
3641 * @return string |
|
3642 * |
|
3643 * @throws SodiumException |
|
3644 */ |
|
3645 public static function ristretto255_from_hash($r, $dontFallback = false) |
|
3646 { |
|
3647 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3648 return sodium_crypto_core_ristretto255_from_hash($r); |
|
3649 } |
|
3650 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_from_hash($r); |
|
3651 } |
|
3652 |
|
3653 /** |
|
3654 * @param bool $dontFallback |
|
3655 * @return string |
|
3656 * |
|
3657 * @throws SodiumException |
|
3658 */ |
|
3659 public static function ristretto255_random($dontFallback = false) |
|
3660 { |
|
3661 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3662 return sodium_crypto_core_ristretto255_random(); |
|
3663 } |
|
3664 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_random(); |
|
3665 } |
|
3666 |
|
3667 /** |
|
3668 * @param bool $dontFallback |
|
3669 * @return string |
|
3670 * |
|
3671 * @throws SodiumException |
|
3672 */ |
|
3673 public static function ristretto255_scalar_random($dontFallback = false) |
|
3674 { |
|
3675 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3676 return sodium_crypto_core_ristretto255_scalar_random(); |
|
3677 } |
|
3678 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_random(); |
|
3679 } |
|
3680 |
|
3681 /** |
|
3682 * @param string $s |
|
3683 * @param bool $dontFallback |
|
3684 * @return string |
|
3685 * @throws SodiumException |
|
3686 */ |
|
3687 public static function ristretto255_scalar_invert($s, $dontFallback = false) |
|
3688 { |
|
3689 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3690 return sodium_crypto_core_ristretto255_scalar_invert($s); |
|
3691 } |
|
3692 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_invert($s); |
|
3693 } |
|
3694 /** |
|
3695 * @param string $s |
|
3696 * @param bool $dontFallback |
|
3697 * @return string |
|
3698 * @throws SodiumException |
|
3699 */ |
|
3700 public static function ristretto255_scalar_negate($s, $dontFallback = false) |
|
3701 { |
|
3702 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3703 return sodium_crypto_core_ristretto255_scalar_negate($s); |
|
3704 } |
|
3705 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_negate($s); |
|
3706 } |
|
3707 |
|
3708 /** |
|
3709 * @param string $s |
|
3710 * @param bool $dontFallback |
|
3711 * @return string |
|
3712 * @throws SodiumException |
|
3713 */ |
|
3714 public static function ristretto255_scalar_complement($s, $dontFallback = false) |
|
3715 { |
|
3716 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3717 return sodium_crypto_core_ristretto255_scalar_complement($s); |
|
3718 } |
|
3719 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_complement($s); |
|
3720 } |
|
3721 |
|
3722 /** |
|
3723 * @param string $x |
|
3724 * @param string $y |
|
3725 * @param bool $dontFallback |
|
3726 * @return string |
|
3727 * @throws SodiumException |
|
3728 */ |
|
3729 public static function ristretto255_scalar_add($x, $y, $dontFallback = false) |
|
3730 { |
|
3731 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3732 return sodium_crypto_core_ristretto255_scalar_add($x, $y); |
|
3733 } |
|
3734 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_add($x, $y); |
|
3735 } |
|
3736 |
|
3737 /** |
|
3738 * @param string $x |
|
3739 * @param string $y |
|
3740 * @param bool $dontFallback |
|
3741 * @return string |
|
3742 * @throws SodiumException |
|
3743 */ |
|
3744 public static function ristretto255_scalar_sub($x, $y, $dontFallback = false) |
|
3745 { |
|
3746 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3747 return sodium_crypto_core_ristretto255_scalar_sub($x, $y); |
|
3748 } |
|
3749 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_sub($x, $y); |
|
3750 } |
|
3751 |
|
3752 /** |
|
3753 * @param string $x |
|
3754 * @param string $y |
|
3755 * @param bool $dontFallback |
|
3756 * @return string |
|
3757 * @throws SodiumException |
|
3758 */ |
|
3759 public static function ristretto255_scalar_mul($x, $y, $dontFallback = false) |
|
3760 { |
|
3761 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3762 return sodium_crypto_core_ristretto255_scalar_mul($x, $y); |
|
3763 } |
|
3764 return ParagonIE_Sodium_Core_Ristretto255::ristretto255_scalar_mul($x, $y); |
|
3765 } |
|
3766 |
|
3767 /** |
|
3768 * @param string $n |
|
3769 * @param string $p |
|
3770 * @param bool $dontFallback |
|
3771 * @return string |
|
3772 * @throws SodiumException |
|
3773 */ |
|
3774 public static function scalarmult_ristretto255($n, $p, $dontFallback = false) |
|
3775 { |
|
3776 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3777 return sodium_crypto_scalarmult_ristretto255($n, $p); |
|
3778 } |
|
3779 return ParagonIE_Sodium_Core_Ristretto255::scalarmult_ristretto255($n, $p); |
|
3780 } |
|
3781 |
|
3782 /** |
|
3783 * @param string $n |
|
3784 * @param string $p |
|
3785 * @param bool $dontFallback |
|
3786 * @return string |
|
3787 * @throws SodiumException |
|
3788 */ |
|
3789 public static function scalarmult_ristretto255_base($n, $dontFallback = false) |
|
3790 { |
|
3791 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3792 return sodium_crypto_scalarmult_ristretto255_base($n); |
|
3793 } |
|
3794 return ParagonIE_Sodium_Core_Ristretto255::scalarmult_ristretto255_base($n); |
|
3795 } |
|
3796 |
|
3797 /** |
|
3798 * @param string $s |
|
3799 * @param bool $dontFallback |
|
3800 * @return string |
|
3801 * @throws SodiumException |
|
3802 */ |
|
3803 public static function ristretto255_scalar_reduce($s, $dontFallback = false) |
|
3804 { |
|
3805 if (self::useNewSodiumAPI() && !$dontFallback) { |
|
3806 return sodium_crypto_core_ristretto255_scalar_reduce($s); |
|
3807 } |
|
3808 return ParagonIE_Sodium_Core_Ristretto255::sc_reduce($s); |
|
3809 } |
|
3810 |
|
3811 /** |
3455 * Runtime testing method for 32-bit platforms. |
3812 * Runtime testing method for 32-bit platforms. |
3456 * |
3813 * |
3457 * Usage: If runtime_speed_test() returns FALSE, then our 32-bit |
3814 * Usage: If runtime_speed_test() returns FALSE, then our 32-bit |
3458 * implementation is to slow to use safely without risking timeouts. |
3815 * implementation is to slow to use safely without risking timeouts. |
3459 * If this happens, install sodium from PECL to get acceptable |
3816 * If this happens, install sodium from PECL to get acceptable |
3486 $diff = (int) ceil(($end - $start) * 1000); |
3843 $diff = (int) ceil(($end - $start) * 1000); |
3487 return $diff < $maxTimeout; |
3844 return $diff < $maxTimeout; |
3488 } |
3845 } |
3489 |
3846 |
3490 /** |
3847 /** |
|
3848 * Add two numbers (little-endian unsigned), storing the value in the first |
|
3849 * parameter. |
|
3850 * |
|
3851 * This mutates $val. |
|
3852 * |
|
3853 * @param string $val |
|
3854 * @param string $addv |
|
3855 * @return void |
|
3856 * @throws SodiumException |
|
3857 */ |
|
3858 public static function sub(&$val, $addv) |
|
3859 { |
|
3860 $val_len = ParagonIE_Sodium_Core_Util::strlen($val); |
|
3861 $addv_len = ParagonIE_Sodium_Core_Util::strlen($addv); |
|
3862 if ($val_len !== $addv_len) { |
|
3863 throw new SodiumException('values must have the same length'); |
|
3864 } |
|
3865 $A = ParagonIE_Sodium_Core_Util::stringToIntArray($val); |
|
3866 $B = ParagonIE_Sodium_Core_Util::stringToIntArray($addv); |
|
3867 |
|
3868 $c = 0; |
|
3869 for ($i = 0; $i < $val_len; $i++) { |
|
3870 $c = ($A[$i] - $B[$i] - $c); |
|
3871 $A[$i] = ($c & 0xff); |
|
3872 $c = ($c >> 8) & 1; |
|
3873 } |
|
3874 $val = ParagonIE_Sodium_Core_Util::intArrayToString($A); |
|
3875 } |
|
3876 |
|
3877 /** |
3491 * This emulates libsodium's version_string() function, except ours is |
3878 * This emulates libsodium's version_string() function, except ours is |
3492 * prefixed with 'polyfill-'. |
3879 * prefixed with 'polyfill-'. |
3493 * |
3880 * |
3494 * @return string |
3881 * @return string |
3495 * @psalm-suppress MixedInferredReturnType |
3882 * @psalm-suppress MixedInferredReturnType |