fixed issues with base64 length limit.
This commit is contained in:
parent
f8f07abc2c
commit
32fd5afc65
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"require": {
|
||||
"paragonie/sodium_compat": "^2.1"
|
||||
"paragonie/sodium_compat": "^2.1",
|
||||
"ext-curl": "*"
|
||||
}
|
||||
}
|
||||
69
index.php
69
index.php
|
|
@ -52,6 +52,39 @@ function respond($status, $message, $data = []) {
|
|||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Try to decode a Base64 or URL-safe Base64 string (or data: URI).
|
||||
* Returns decoded bytes on success, or false on failure.
|
||||
*/
|
||||
function maybeDecodeBase64($input) {
|
||||
if ($input === null) return false;
|
||||
$trim = preg_replace('/\s+/', '', $input);
|
||||
if (stripos($trim, 'data:') === 0 && ($pos = stripos($trim, ';base64,')) !== false) {
|
||||
$payload = substr($trim, $pos + 8);
|
||||
} else {
|
||||
$payload = $trim;
|
||||
}
|
||||
$payload = strtr($payload, '-_', '+/');
|
||||
$pad = strlen($payload) % 4;
|
||||
if ($pad) { $payload .= str_repeat('=', 4 - $pad); }
|
||||
$decoded = base64_decode($payload, true);
|
||||
if ($decoded === false) { return false; }
|
||||
|
||||
// Heuristic to reduce false positives: compare normalized encoding or check for binary-ish data
|
||||
$re = rtrim(strtr(base64_encode($decoded), '+/', '-_'), '=');
|
||||
$pa = rtrim(str_replace('=', '', $payload), '=');
|
||||
if ($re !== $pa) {
|
||||
$nonPrintable = preg_match_all('/[^\x09\x0A\x0D\x20-\x7E]/', $decoded);
|
||||
if ($nonPrintable < max(1, (int)(strlen($decoded) * 0.1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
// Enhance Base64 decoding to handle both raw and URL-safe inputs
|
||||
function safeBase64Decode($input) {
|
||||
// First, attempt a direct Base64 decode
|
||||
|
|
@ -173,24 +206,40 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_GET['action'] === 'retrieve') {
|
|||
|
||||
$pubkey_hash = bin2hex(sodium_crypto_generichash($decodedPubkey));
|
||||
|
||||
if (!sodium_crypto_sign_verify_detached($decodedSignature, $data, $decodedPubkey)) {
|
||||
respond(400, "Invalid signature");
|
||||
|
||||
// If data looks like base64 (or data:...;base64,...) decode it for size check and storage.
|
||||
$decodedData = maybeDecodeBase64($data);
|
||||
$isBase64Payload = ($decodedData !== false);
|
||||
|
||||
// Verify signature. First try verifying exactly what we received (backwards compatibility).
|
||||
$sigOk = sodium_crypto_sign_verify_detached($decodedSignature, $data, $decodedPubkey);
|
||||
|
||||
// If that fails and it looked like base64, also try verifying the decoded bytes (clients that sign raw bytes).
|
||||
if (!$sigOk && $isBase64Payload) {
|
||||
$sigOk = sodium_crypto_sign_verify_detached($decodedSignature, $decodedData, $decodedPubkey);
|
||||
}
|
||||
if (!$sigOk) {
|
||||
respond(403, "Invalid signature");
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("SELECT * FROM storage WHERE pubkey_hash = :pubkey_hash");
|
||||
$stmt->execute([':pubkey_hash' => $pubkey_hash]);
|
||||
if (!$stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
respond(404, "Space not found");
|
||||
}
|
||||
|
||||
if (strlen($data) > 1024) {
|
||||
// Enforce 1k limit against decoded bytes when base64 was used; otherwise against the raw payload.
|
||||
$dataForLimit = $isBase64Payload ? $decodedData : $data;
|
||||
if (strlen($dataForLimit) > 1024) {
|
||||
respond(400, "Data exceeds 1k size limit");
|
||||
}
|
||||
|
||||
// Choose what we store: decoded bytes when base64 was used (so retrieval returns raw), otherwise raw text.
|
||||
$dataToStore = $isBase64Payload ? $decodedData : $data;
|
||||
// Normalize MIME type for common images if a data URI was provided.
|
||||
if ($isBase64Payload && isset($_PUT['mime_type']) && stripos($_PUT['mime_type'], 'image/') === 0) {
|
||||
$mime_type = $_PUT['mime_type'];
|
||||
}
|
||||
// Persist
|
||||
$stmt = $db->prepare("UPDATE storage SET data = :data, mime_type = :mime_type WHERE pubkey_hash = :pubkey_hash");
|
||||
$stmt->execute([':data' => $data, ':mime_type' => $mime_type, ':pubkey_hash' => $pubkey_hash]);
|
||||
$stmt->execute([':data' => $dataToStore, ':mime_type' => $mime_type, ':pubkey_hash' => $pubkey_hash]);
|
||||
|
||||
respond(200, "Storage updated");
|
||||
|
||||
}
|
||||
|
||||
// Handle deletion (not in spec, but helpful)
|
||||
|
|
|
|||
5
main.php
5
main.php
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="https://github.com/the1024club/the1024.club" target="_blank">Source Code</a></li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
|
|
@ -168,7 +169,7 @@ php 1kb_client.php retrieve public_key.pem
|
|||
|
||||
<footer>
|
||||
<p class="license-title">The MIT License (MIT)</p>
|
||||
<p class="license-copyright">©2020 The 1024 Club Developers (see AUTHORS.txt)</p>
|
||||
<p class="license-copyright">©2024 The 1024 Club Developers <a href="https://github.com/the1024club/the1024.club" target="_blank">Source Code</a></p>
|
||||
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>
|
||||
<p>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</p>
|
||||
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
// Load Sodium extension
|
||||
require __DIR__ . '/../vendor/autoload.php'; // Adjust the path to the autoload file
|
||||
|
||||
// Base64 decode the public and private keys
|
||||
$publicKey = base64_decode('0HCO9Tm3JvvbK+J93PStb4/23HSxEZS9WUrWSjmLIz4=');
|
||||
$privateKey = base64_decode('s1cAUQfbxa6Q8lJxn90N6aKER17Ng9tD/gHpX+8x6drQcI71Obcm+9sr4n3c9K1vj/bcdLERlL1ZStZKOYsjPg==');
|
||||
|
||||
// Derive the public key from the private key to check if they match
|
||||
$derivedPublicKey = sodium_crypto_sign_publickey_from_secretkey($privateKey);
|
||||
|
||||
// Compare the derived public key with the provided public key
|
||||
if (hash_equals($publicKey, $derivedPublicKey)) {
|
||||
echo "The public and private key pair match!" . PHP_EOL;
|
||||
} else {
|
||||
echo "The public and private key pair do NOT match!" . PHP_EOL;
|
||||
}
|
||||
?>
|
||||
Loading…
Reference in New Issue