Changeset 46858 for trunk/src/wp-includes/sodium_compat/src/Crypto32.php
- Timestamp:
- 12/09/2019 04:40:11 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/sodium_compat/src/Crypto32.php
r46586 r46858 778 778 779 779 /** 780 * Initialize a hashing context for BLAKE2b. 781 * 782 * @internal Do not use this directly. Use ParagonIE_Sodium_Compat. 783 * 784 * @param string $key 785 * @param int $outputLength 786 * @param string $salt 787 * @param string $personal 788 * @return string 789 * @throws RangeException 790 * @throws SodiumException 791 * @throws TypeError 792 */ 793 public static function generichash_init_salt_personal( 794 $key = '', 795 $outputLength = 32, 796 $salt = '', 797 $personal = '' 798 ) { 799 // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is initialized 800 ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor(); 801 802 $k = null; 803 if (!empty($key)) { 804 $k = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key); 805 if ($k->count() > ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) { 806 throw new RangeException('Invalid key size'); 807 } 808 } 809 if (!empty($salt)) { 810 $s = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($salt); 811 } else { 812 $s = null; 813 } 814 if (!empty($salt)) { 815 $p = ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($personal); 816 } else { 817 $p = null; 818 } 819 820 /** @var SplFixedArray $ctx */ 821 $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength, $s, $p); 822 823 return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx); 824 } 825 826 /** 780 827 * Update a hashing context for BLAKE2b with $message 781 828 * … … 1186 1233 1187 1234 /** 1235 * @param string $key 1236 * @return array<int, string> Returns a state and a header. 1237 * @throws Exception 1238 * @throws SodiumException 1239 */ 1240 public static function secretstream_xchacha20poly1305_init_push($key) 1241 { 1242 # randombytes_buf(out, crypto_secretstream_xchacha20poly1305_HEADERBYTES); 1243 $out = random_bytes(24); 1244 1245 # crypto_core_hchacha20(state->k, out, k, NULL); 1246 $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20($out, $key); 1247 $state = new ParagonIE_Sodium_Core32_SecretStream_State( 1248 $subkey, 1249 ParagonIE_Sodium_Core32_Util::substr($out, 16, 8) . str_repeat("\0", 4) 1250 ); 1251 1252 # _crypto_secretstream_xchacha20poly1305_counter_reset(state); 1253 $state->counterReset(); 1254 1255 # memcpy(STATE_INONCE(state), out + crypto_core_hchacha20_INPUTBYTES, 1256 # crypto_secretstream_xchacha20poly1305_INONCEBYTES); 1257 # memset(state->_pad, 0, sizeof state->_pad); 1258 return array( 1259 $state->toString(), 1260 $out 1261 ); 1262 } 1263 1264 /** 1265 * @param string $key 1266 * @param string $header 1267 * @return string Returns a state. 1268 * @throws Exception 1269 */ 1270 public static function secretstream_xchacha20poly1305_init_pull($key, $header) 1271 { 1272 # crypto_core_hchacha20(state->k, in, k, NULL); 1273 $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20( 1274 ParagonIE_Sodium_Core32_Util::substr($header, 0, 16), 1275 $key 1276 ); 1277 $state = new ParagonIE_Sodium_Core32_SecretStream_State( 1278 $subkey, 1279 ParagonIE_Sodium_Core32_Util::substr($header, 16) 1280 ); 1281 $state->counterReset(); 1282 # memcpy(STATE_INONCE(state), in + crypto_core_hchacha20_INPUTBYTES, 1283 # crypto_secretstream_xchacha20poly1305_INONCEBYTES); 1284 # memset(state->_pad, 0, sizeof state->_pad); 1285 # return 0; 1286 return $state->toString(); 1287 } 1288 1289 /** 1290 * @param string $state 1291 * @param string $msg 1292 * @param string $aad 1293 * @param int $tag 1294 * @return string 1295 * @throws SodiumException 1296 */ 1297 public static function secretstream_xchacha20poly1305_push(&$state, $msg, $aad = '', $tag = 0) 1298 { 1299 $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); 1300 # crypto_onetimeauth_poly1305_state poly1305_state; 1301 # unsigned char block[64U]; 1302 # unsigned char slen[8U]; 1303 # unsigned char *c; 1304 # unsigned char *mac; 1305 1306 $msglen = ParagonIE_Sodium_Core32_Util::strlen($msg); 1307 $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad); 1308 1309 if ((($msglen + 63) >> 6) > 0xfffffffe) { 1310 throw new SodiumException( 1311 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' 1312 ); 1313 } 1314 1315 # if (outlen_p != NULL) { 1316 # *outlen_p = 0U; 1317 # } 1318 # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { 1319 # sodium_misuse(); 1320 # } 1321 1322 # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); 1323 # crypto_onetimeauth_poly1305_init(&poly1305_state, block); 1324 # sodium_memzero(block, sizeof block); 1325 $auth = new ParagonIE_Sodium_Core32_Poly1305_State( 1326 ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) 1327 ); 1328 1329 # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); 1330 $auth->update($aad); 1331 1332 # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, 1333 # (0x10 - adlen) & 0xf); 1334 $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); 1335 1336 # memset(block, 0, sizeof block); 1337 # block[0] = tag; 1338 # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, 1339 # state->nonce, 1U, state->k); 1340 $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( 1341 ParagonIE_Sodium_Core32_Util::intToChr($tag) . str_repeat("\0", 63), 1342 $st->getCombinedNonce(), 1343 $st->getKey(), 1344 ParagonIE_Sodium_Core32_Util::store64_le(1) 1345 ); 1346 1347 # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); 1348 $auth->update($block); 1349 1350 # out[0] = block[0]; 1351 $out = $block[0]; 1352 # c = out + (sizeof tag); 1353 # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k); 1354 $cipher = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( 1355 $msg, 1356 $st->getCombinedNonce(), 1357 $st->getKey(), 1358 ParagonIE_Sodium_Core32_Util::store64_le(2) 1359 ); 1360 1361 # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); 1362 $auth->update($cipher); 1363 1364 $out .= $cipher; 1365 unset($cipher); 1366 1367 # crypto_onetimeauth_poly1305_update 1368 # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); 1369 $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); 1370 1371 # STORE64_LE(slen, (uint64_t) adlen); 1372 $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen); 1373 1374 # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); 1375 $auth->update($slen); 1376 1377 # STORE64_LE(slen, (sizeof block) + mlen); 1378 $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen); 1379 1380 # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); 1381 $auth->update($slen); 1382 1383 # mac = c + mlen; 1384 # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); 1385 $mac = $auth->finish(); 1386 $out .= $mac; 1387 1388 # sodium_memzero(&poly1305_state, sizeof poly1305_state); 1389 unset($auth); 1390 1391 1392 # XOR_BUF(STATE_INONCE(state), mac, 1393 # crypto_secretstream_xchacha20poly1305_INONCEBYTES); 1394 $st->xorNonce($mac); 1395 1396 # sodium_increment(STATE_COUNTER(state), 1397 # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); 1398 $st->incrementCounter(); 1399 // Overwrite by reference: 1400 $state = $st->toString(); 1401 1402 /** @var bool $rekey */ 1403 $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; 1404 # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || 1405 # sodium_is_zero(STATE_COUNTER(state), 1406 # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { 1407 # crypto_secretstream_xchacha20poly1305_rekey(state); 1408 # } 1409 if ($rekey || $st->needsRekey()) { 1410 // DO REKEY 1411 self::secretstream_xchacha20poly1305_rekey($state); 1412 } 1413 # if (outlen_p != NULL) { 1414 # *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen; 1415 # } 1416 return $out; 1417 } 1418 1419 /** 1420 * @param string $state 1421 * @param string $cipher 1422 * @param string $aad 1423 * @return bool|array{0: string, 1: int} 1424 * @throws SodiumException 1425 */ 1426 public static function secretstream_xchacha20poly1305_pull(&$state, $cipher, $aad = '') 1427 { 1428 $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); 1429 1430 $cipherlen = ParagonIE_Sodium_Core32_Util::strlen($cipher); 1431 # mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES; 1432 $msglen = $cipherlen - ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES; 1433 $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad); 1434 1435 # if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) { 1436 # sodium_misuse(); 1437 # } 1438 if ((($msglen + 63) >> 6) > 0xfffffffe) { 1439 throw new SodiumException( 1440 'message cannot be larger than SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes' 1441 ); 1442 } 1443 1444 # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k); 1445 # crypto_onetimeauth_poly1305_init(&poly1305_state, block); 1446 # sodium_memzero(block, sizeof block); 1447 $auth = new ParagonIE_Sodium_Core32_Poly1305_State( 1448 ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32, $st->getCombinedNonce(), $st->getKey()) 1449 ); 1450 1451 # crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen); 1452 $auth->update($aad); 1453 1454 # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0, 1455 # (0x10 - adlen) & 0xf); 1456 $auth->update(str_repeat("\0", ((0x10 - $aadlen) & 0xf))); 1457 1458 1459 # memset(block, 0, sizeof block); 1460 # block[0] = in[0]; 1461 # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block, 1462 # state->nonce, 1U, state->k); 1463 $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( 1464 $cipher[0] . str_repeat("\0", 63), 1465 $st->getCombinedNonce(), 1466 $st->getKey(), 1467 ParagonIE_Sodium_Core32_Util::store64_le(1) 1468 ); 1469 # tag = block[0]; 1470 # block[0] = in[0]; 1471 # crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block); 1472 $tag = ParagonIE_Sodium_Core32_Util::chrToInt($block[0]); 1473 $block[0] = $cipher[0]; 1474 $auth->update($block); 1475 1476 1477 # c = in + (sizeof tag); 1478 # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen); 1479 $auth->update(ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen)); 1480 1481 # crypto_onetimeauth_poly1305_update 1482 # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf); 1483 $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen) & 0xf))); 1484 1485 # STORE64_LE(slen, (uint64_t) adlen); 1486 # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); 1487 $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen); 1488 $auth->update($slen); 1489 1490 # STORE64_LE(slen, (sizeof block) + mlen); 1491 # crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen); 1492 $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen); 1493 $auth->update($slen); 1494 1495 # crypto_onetimeauth_poly1305_final(&poly1305_state, mac); 1496 # sodium_memzero(&poly1305_state, sizeof poly1305_state); 1497 $mac = $auth->finish(); 1498 1499 # stored_mac = c + mlen; 1500 # if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) { 1501 # sodium_memzero(mac, sizeof mac); 1502 # return -1; 1503 # } 1504 1505 $stored = ParagonIE_Sodium_Core32_Util::substr($cipher, $msglen + 1, 16); 1506 if (!ParagonIE_Sodium_Core32_Util::hashEquals($mac, $stored)) { 1507 return false; 1508 } 1509 1510 # crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k); 1511 $out = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( 1512 ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen), 1513 $st->getCombinedNonce(), 1514 $st->getKey(), 1515 ParagonIE_Sodium_Core32_Util::store64_le(2) 1516 ); 1517 1518 # XOR_BUF(STATE_INONCE(state), mac, 1519 # crypto_secretstream_xchacha20poly1305_INONCEBYTES); 1520 $st->xorNonce($mac); 1521 1522 # sodium_increment(STATE_COUNTER(state), 1523 # crypto_secretstream_xchacha20poly1305_COUNTERBYTES); 1524 $st->incrementCounter(); 1525 1526 # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 || 1527 # sodium_is_zero(STATE_COUNTER(state), 1528 # crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) { 1529 # crypto_secretstream_xchacha20poly1305_rekey(state); 1530 # } 1531 1532 // Overwrite by reference: 1533 $state = $st->toString(); 1534 1535 /** @var bool $rekey */ 1536 $rekey = ($tag & ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY) !== 0; 1537 if ($rekey || $st->needsRekey()) { 1538 // DO REKEY 1539 self::secretstream_xchacha20poly1305_rekey($state); 1540 } 1541 return array($out, $tag); 1542 } 1543 1544 /** 1545 * @param string $state 1546 * @return void 1547 * @throws SodiumException 1548 */ 1549 public static function secretstream_xchacha20poly1305_rekey(&$state) 1550 { 1551 $st = ParagonIE_Sodium_Core32_SecretStream_State::fromString($state); 1552 # unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + 1553 # crypto_secretstream_xchacha20poly1305_INONCEBYTES]; 1554 # size_t i; 1555 # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { 1556 # new_key_and_inonce[i] = state->k[i]; 1557 # } 1558 $new_key_and_inonce = $st->getKey(); 1559 1560 # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { 1561 # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i] = 1562 # STATE_INONCE(state)[i]; 1563 # } 1564 $new_key_and_inonce .= ParagonIE_Sodium_Core32_Util::substR($st->getNonce(), 0, 8); 1565 1566 # crypto_stream_chacha20_ietf_xor(new_key_and_inonce, new_key_and_inonce, 1567 # sizeof new_key_and_inonce, 1568 # state->nonce, state->k); 1569 1570 $st->rekey(ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc( 1571 $new_key_and_inonce, 1572 $st->getCombinedNonce(), 1573 $st->getKey(), 1574 ParagonIE_Sodium_Core32_Util::store64_le(0) 1575 )); 1576 1577 # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) { 1578 # state->k[i] = new_key_and_inonce[i]; 1579 # } 1580 # for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) { 1581 # STATE_INONCE(state)[i] = 1582 # new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]; 1583 # } 1584 # _crypto_secretstream_xchacha20poly1305_counter_reset(state); 1585 $st->counterReset(); 1586 1587 $state = $st->toString(); 1588 } 1589 1590 /** 1188 1591 * Detached Ed25519 signature. 1189 1592 *
Note: See TracChangeset
for help on using the changeset viewer.