Fix false short URL integrity warning
This commit is contained in:
35
app.js
35
app.js
@@ -400,7 +400,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that short URL has not been tampered with by checking HMAC signature
|
// Verify that the redirected hash still matches the stored short URL mapping.
|
||||||
function verifyShortUrlIntegrity(code, currentHash) {
|
function verifyShortUrlIntegrity(code, currentHash) {
|
||||||
fetch('/api/check-short.php?code=' + encodeURIComponent(code))
|
fetch('/api/check-short.php?code=' + encodeURIComponent(code))
|
||||||
.then(function (res) {
|
.then(function (res) {
|
||||||
@@ -408,47 +408,20 @@
|
|||||||
return res.json();
|
return res.json();
|
||||||
})
|
})
|
||||||
.then(function (data) {
|
.then(function (data) {
|
||||||
if (!data.signature) {
|
if (!data.hash) {
|
||||||
// Old format without signature - no integrity check
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify HMAC signature client-side
|
if (data.hash !== currentHash) {
|
||||||
verifyHmacSignature(data.hash, data.signature).then(function (valid) {
|
console.warn('xmrpay: Short URL hash mismatch detected for code', code);
|
||||||
if (!valid) {
|
|
||||||
console.warn('xmrpay: Hash signature mismatch - possible server tampering detected');
|
|
||||||
showToast(I18n.t('toast_integrity_warning'));
|
showToast(I18n.t('toast_integrity_warning'));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch(function (e) {
|
.catch(function (e) {
|
||||||
console.warn('xmrpay: Could not verify short URL integrity:', e);
|
console.warn('xmrpay: Could not verify short URL integrity:', e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client-side HMAC-SHA256 verification
|
|
||||||
async function verifyHmacSignature(hash, expectedSignature) {
|
|
||||||
try {
|
|
||||||
// Use hostname as part of the secret (same as server-side)
|
|
||||||
const secret = await crypto.subtle.digest('SHA-256',
|
|
||||||
new TextEncoder().encode(location.hostname + 'xmrpay.link'));
|
|
||||||
const key = await crypto.subtle.importKey('raw', secret,
|
|
||||||
{ name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
||||||
const signature = await crypto.subtle.sign('HMAC', key,
|
|
||||||
new TextEncoder().encode(hash));
|
|
||||||
|
|
||||||
// Convert to hex string
|
|
||||||
const sigHex = Array.from(new Uint8Array(signature))
|
|
||||||
.map(b => b.toString(16).padStart(2, '0'))
|
|
||||||
.join('');
|
|
||||||
|
|
||||||
return sigHex === expectedSignature;
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('xmrpay: HMAC verification failed:', e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSummary(xmrAmount, desc, days) {
|
function buildSummary(xmrAmount, desc, days) {
|
||||||
var html = '';
|
var html = '';
|
||||||
if (xmrAmount) {
|
if (xmrAmount) {
|
||||||
|
|||||||
2
app.min.js
vendored
2
app.min.js
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user