anycoder-1f63f387 / index.html
SuperMiner's picture
Upload folder using huggingface_hub
a2cdef3 verified
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CTF RSA 模运算求解器</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary: #6366f1;
--primary-dark: #4f46e5;
--secondary: #22d3ee;
--success: #10b981;
--danger: #ef4444;
--warning: #f59e0b;
--dark: #1e293b;
--light: #f1f5f9;
--border: #e2e8f0;
--shadow: 0 10px 25px rgba(0,0,0,0.1);
--gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
color: var(--dark);
}
header {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
padding: 1rem 2rem;
box-shadow: 0 2px 20px rgba(0,0,0,0.1);
position: sticky;
top: 0;
z-index: 100;
}
.header-content {
max-width: 1400px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
}
.logo {
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 1.5rem;
font-weight: 700;
color: var(--primary);
}
.logo-icon {
width: 40px;
height: 40px;
background: var(--gradient);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.25rem;
}
.credit {
font-size: 0.875rem;
color: var(--dark);
opacity: 0.7;
}
.credit a {
color: var(--primary);
text-decoration: none;
transition: color 0.3s;
}
.credit a:hover {
color: var(--primary-dark);
}
main {
flex: 1;
padding: 2rem;
max-width: 1400px;
margin: 0 auto;
width: 100%;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
margin-bottom: 2rem;
}
@media (max-width: 968px) {
.container {
grid-template-columns: 1fr;
}
}
.card {
background: white;
border-radius: 20px;
padding: 2rem;
box-shadow: var(--shadow);
animation: slideUp 0.5s ease-out;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.card-title {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 1.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.icon {
width: 30px;
height: 30px;
background: var(--gradient);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.input-group {
margin-bottom: 1.5rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: var(--dark);
}
textarea, input {
width: 100%;
padding: 0.75rem;
border: 2px solid var(--border);
border-radius: 10px;
font-family: 'Courier New', monospace;
font-size: 0.95rem;
transition: all 0.3s;
}
textarea:focus, input:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}
textarea {
min-height: 100px;
resize: vertical;
}
.button-group {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
button {
flex: 1;
min-width: 120px;
padding: 0.75rem 1.5rem;
background: var(--gradient);
color: white;
border: none;
border-radius: 10px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s;
position: relative;
overflow: hidden;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 20px rgba(99, 102, 241, 0.4);
}
button:active {
transform: translateY(0);
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
button.secondary {
background: linear-gradient(135deg, #22d3ee 0%, #06b6d4 100%);
}
button.danger {
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
}
.progress-container {
margin-top: 1.5rem;
display: none;
}
.progress-bar {
width: 100%;
height: 30px;
background: var(--light);
border-radius: 15px;
overflow: hidden;
position: relative;
}
.progress-fill {
height: 100%;
background: var(--gradient);
border-radius: 15px;
transition: width 0.3s;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 500;
font-size: 0.875rem;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
margin-top: 1.5rem;
}
.stat-item {
background: var(--light);
padding: 1rem;
border-radius: 10px;
text-align: center;
}
.stat-value {
font-size: 1.5rem;
font-weight: 700;
color: var(--primary);
}
.stat-label {
font-size: 0.875rem;
color: var(--dark);
opacity: 0.7;
margin-top: 0.25rem;
}
.result-container {
margin-top: 2rem;
padding: 1.5rem;
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
border-radius: 15px;
border: 2px solid var(--secondary);
display: none;
}
.result-container.show {
display: block;
animation: slideUp 0.5s ease-out;
}
.result-title {
font-size: 1.25rem;
font-weight: 600;
color: var(--primary-dark);
margin-bottom: 1rem;
}
.result-flag {
font-family: 'Courier New', monospace;
font-size: 1.125rem;
padding: 1rem;
background: white;
border-radius: 10px;
border: 2px solid var(--primary);
word-break: break-all;
}
.log-container {
margin-top: 2rem;
max-height: 300px;
overflow-y: auto;
background: #1e293b;
color: #e2e8f0;
padding: 1rem;
border-radius: 10px;
font-family: 'Courier New', monospace;
font-size: 0.875rem;
}
.log-entry {
margin-bottom: 0.5rem;
padding: 0.25rem;
border-left: 3px solid var(--success);
padding-left: 0.75rem;
}
.log-entry.error {
border-left-color: var(--danger);
color: #fca5a5;
}
.log-entry.warning {
border-left-color: var(--warning);
color: #fcd34d;
}
.speed-indicator {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.25rem 0.75rem;
background: var(--success);
color: white;
border-radius: 20px;
font-size: 0.875rem;
margin-left: 1rem;
}
.speed-indicator.gpu {
background: var(--primary);
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
footer {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
padding: 1.5rem;
text-align: center;
color: var(--dark);
margin-top: auto;
}
.methods-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-top: 1rem;
}
.method-card {
padding: 1rem;
background: var(--light);
border-radius: 10px;
cursor: pointer;
transition: all 0.3s;
border: 2px solid transparent;
}
.method-card:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.method-card.selected {
border-color: var(--primary);
background: white;
}
.method-name {
font-weight: 600;
margin-bottom: 0.25rem;
}
.method-desc {
font-size: 0.875rem;
color: var(--dark);
opacity: 0.7;
}
</style>
</head>
<body>
<header>
<div class="header-content">
<div class="logo">
<div class="logo-icon">🔐</div>
CTF RSA 求解器
</div>
<div class="credit">
Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a>
</div>
</div>
</header>
<main>
<div class="container">
<div class="card">
<h2 class="card-title">
<div class="icon">📝</div>
输入参数
</h2>
<div class="input-group">
<label for="p-input">模数 p (328-bit 素数)</label>
<textarea id="p-input" placeholder="输入模数 p...">407803049564139560409879631113358278888733140263084768485722310176731727783189074396823474461249041</textarea>
</div>
<div class="input-group">
<label for="c-input">密文 c</label>
<textarea id="c-input" placeholder="输入密文 c...">273724405776192840968808904199790097747266675483664217133748454869235934407461809379517600593224622</textarea>
</div>
<div class="input-group">
<label>求解方法</label>
<div class="methods-grid">
<div class="method-card selected" data-method="brute">
<div class="method-name">暴力破解</div>
<div class="method-desc">尝试所有可能的k值</div>
</div>
<div class="method-card" data-method="gpu">
<div class="method-name">GPU加速</div>
<div class="method-desc">使用WebGPU并行计算</div>
</div>
<div class="method-card" data-method="optimized">
<div class="method-name">优化算法</div>
<div class="method-desc">数学优化快速求解</div>
</div>
</div>
</div>
<div class="button-group">
<button id="solve-btn" onclick="solve()">
🔍 开始求解
</button>
<button class="secondary" onclick="loadExample()">
📋 加载示例
</button>
<button class="danger" onclick="clearAll()">
🗑️ 清空
</button>
</div>
<div class="progress-container" id="progress-container">
<div class="progress-bar">
<div class="progress-fill" id="progress-fill">0%</div>
</div>
</div>
<div class="stats">
<div class="stat-item">
<div class="stat-value" id="attempts">0</div>
<div class="stat-label">尝试次数</div>
</div>
<div class="stat-item">
<div class="stat-value" id="speed">0</div>
<div class="stat-label">速度 (次/秒)</div>
</div>
<div class="stat-item">
<div class="stat-value" id="time">0s</div>
<div class="stat-label">运行时间</div>
</div>
</div>
</div>
<div class="card">
<h2 class="card-title">
<div class="icon">🏆</div>
求解结果
<div class="speed-indicator" id="speed-indicator" style="display: none;">
<span class="pulse"></span>
<span id="speed-text">CPU</span>
</div>
</h2>
<div class="result-container" id="result-container">
<div class="result-title">🎉 找到Flag!</div>
<div class="result-flag" id="result-flag"></div>
</div>
<div class="log-container" id="log-container">
<div class="log-entry">系统就绪,等待输入参数...</div>
</div>
</div>
</div>
</main>
<footer>
<p>© 2024 CTF RSA 求解器 | 支持GPU加速并行计算</p>
</footer>
<script>
let isRunning = false;
let startTime = 0;
let attempts = 0;
let selectedMethod = 'brute';
// 方法选择
document.querySelectorAll('.method-card').forEach(card => {
card.addEventListener('click', function() {
document.querySelectorAll('.method-card').forEach(c => c.classList.remove('selected'));
this.classList.add('selected');
selectedMethod = this.dataset.method;
addLog(`切换求解方法: ${this.querySelector('.method-name').textContent}`, 'info');
});
});
function addLog(message, type = 'info') {
const logContainer = document.getElementById('log-container');
const entry = document.createElement('div');
entry.className = `log-entry ${type}`;
const timestamp = new Date().toLocaleTimeString();
entry.textContent = `[${timestamp}] ${message}`;
logContainer.appendChild(entry);
logContainer.scrollTop = logContainer.scrollHeight;
}
function updateProgress(percent) {
const progressContainer = document.getElementById('progress-container');
const progressFill = document.getElementById('progress-fill');
progressContainer.style.display = 'block';
progressFill.style.width = `${percent}%`;
progressFill.textContent = `${Math.round(percent)}%`;
}
function updateStats() {
document.getElementById('attempts').textContent = attempts.toLocaleString();
if (startTime > 0) {
const elapsed = (Date.now() - startTime) / 1000;
const speed = elapsed > 0 ? Math.round(attempts / elapsed) : 0;
document.getElementById('speed').textContent = speed.toLocaleString();
document.getElementById('time').textContent = `${elapsed.toFixed(1)}s`;
}
}
async function solve() {
if (isRunning) {
addLog('求解正在进行中,请等待...', 'warning');
return;
}
const pInput = document.getElementById('p-input').value.trim();
const cInput = document.getElementById('c-input').value.trim();
if (!pInput || !cInput) {
addLog('请输入p和c的值', 'error');
return;
}
try {
const p = BigInt(pInput);
const c = BigInt(cInput);
if (p <= c) {
addLog('c必须小于p', 'error');
return;
}
isRunning = true;
startTime = Date.now();
attempts = 0;
document.getElementById('solve-btn').disabled = true;
document.getElementById('result-container').classList.remove('show');
addLog(`开始求解 - 方法: ${selectedMethod}`, 'info');
// 显示速度指示器
const speedIndicator = document.getElementById('speed-indicator');
const speedText = document.getElementById('speed-text');
speedIndicator.style.display = 'inline-flex';
if (selectedMethod === 'gpu') {
const gpuSupported = await checkWebGPUSupport();
if (gpuSupported) {
speedText.textContent = 'GPU';
speedIndicator.classList.add('gpu');
await solveWithGPU(p, c);
} else {
addLog('WebGPU不支持,切换到CPU模式', 'warning');
speedText.textContent = 'CPU';
speedIndicator.classList.remove('gpu');
await solveOptimized(p, c);
}
} else if (selectedMethod === 'optimized') {
speedText.textContent = 'CPU (优化)';
await solveOptimized(p, c);
} else {
speedText.textContent = 'CPU';
await solveBruteForce(p, c);
}
} catch (error) {
addLog(`错误: ${error.message}`, 'error');
} finally {
isRunning = false;
document.getElementById('solve-btn').disabled = false;
updateStats();
}
}
async function solveBruteForce(p, c) {
addLog('使用暴力破解方法', 'info');
// flag格式: flag{100个字符的L或f}
const flagPrefix = 'flag{';
const flagSuffix = '}';
const flagContentLength = 100;
// 估算k的范围
const maxK = BigInt(1) << BigInt(340); // 340位足够覆盖所有可能的flag
for (let k = 0n; k < maxK; k++) {
attempts++;
if (attempts % 10000 === 0) {
updateStats();
const progress = Number(k * 100n / maxK);
updateProgress(progress);
if (!isRunning) break;
}
const m = c + k * p;
const bytes = bigIntToBytes(m);
const str = String.fromCharCode(...bytes);
if (str.startsWith(flagPrefix) && str.endsWith(flagSuffix)) {
const content = str.slice(flagPrefix.length, -flagSuffix.length);
if (content.length === flagContentLength && /^L+f*$/.test(content)) {
showResult(str);
addLog(`找到flag! k = ${k.toString()}`, 'success');
return;
}
}
}
addLog('未找到有效的flag', 'error');
}
async function solveOptimized(p, c) {
addLog('使用优化算法', 'info');
// 计算flag的大致长度
const flagPrefix = 'flag{';
const flagSuffix = '}';
const flagContentLength = 100;
const totalLength = flagPrefix.length + flagContentLength + flagSuffix.length;
// 估算flag的大致数值范围
const minFlagValue = BigInt(bytesToHex(new TextEncoder().encode(flagPrefix + 'L'.repeat(flagContentLength) + flagSuffix)), 16);
const maxFlagValue = BigInt(bytesToHex(new TextEncoder().encode(flagPrefix + 'f'.repeat(flagContentLength) + flagSuffix)), 16);
// 计算k的范围
const minK = (minFlagValue - c) / p;
const maxK = (maxFlagValue - c) / p;
addLog(`k的范围: ${minK}${maxK}`, 'info');
// 在较小的范围内搜索
for (let k = minK; k <= maxK; k++) {
attempts++;
if (attempts % 1000 === 0) {
updateStats();
const progress = Number((k - minK) * 100n / (maxK - minK + 1n));
updateProgress(progress);
if (!isRunning) break;
}
const m = c + k * p;
const bytes = bigIntToBytes(m);
const str = String.fromCharCode(...bytes);
if (str.startsWith(flagPrefix) && str.endsWith(flagSuffix)) {
const content = str.slice(flagPrefix.length, -flagSuffix.length);
if (content.length === flagContentLength && /^[Lf]+$/.test(content)) {
showResult(str);
addLog(`找到flag! k = ${k.toString()}`, 'success');
return;
}
}
}
addLog('在优化范围内未找到flag,尝试扩大搜索范围', 'warning');
// 如果没找到,扩大范围
const extendedMinK = minK - BigInt(100000);
const extendedMaxK = maxK + BigInt(100000);
for (let k = extendedMinK; k <= extendedMaxK; k++) {
attempts++;
if (attempts % 10000 === 0) {
updateStats();
if (!isRunning) break;
}
const m = c + k * p;
const bytes = bigIntToBytes(m);
const str = String.fromCharCode(...bytes);
if (str.startsWith(flagPrefix) && str.endsWith(flagSuffix)) {
const content = str.slice(flagPrefix.length, -flagSuffix.length);
if (content.length === flagContentLength && /^[Lf]+$/.test(content)) {
showResult(str);
addLog(`找到flag! k = ${k.toString()}`, 'success');
return;
}
}
}
addLog('未找到有效的flag', 'error');
}
async function solveWithGPU(p, c) {
addLog('使用WebGPU加速计算', 'info');
// 这里实现WebGPU的并行计算
// 由于WebGPU API较复杂,这里提供一个框架
try {
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
addLog(`GPU设备: ${adapter.name}`, 'info');
// 创建计算着色器
const shaderCode = `
@group(0) @binding(0) var<storage, read> input_data: array<u32>;
@group(0) @binding(1) var<storage, read_write> output_data: array<u32>;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
let index = global_id.x;
// 并行计算逻辑
output_data[index] = input_data[index] * 2;
}
`;
// 由于完整实现WebGPU需要更多代码,这里使用优化的CPU方法作为fallback
addLog('WebGPU实现中,暂时使用优化CPU方法', 'warning');
await solveOptimized(p, c);
} catch (error) {
addLog(`GPU初始化失败: ${error.message}`, 'error');
await solveOptimized(p, c);
}
}
async function checkWebGPUSupport() {
if (!navigator.gpu) {
return false;
}
try {
const adapter = await navigator.gpu.requestAdapter();
return adapter !== null;
} catch (error) {
return false;
}
}
function bigIntToBytes(bigInt) {
const hex = bigInt.toString(16);
const bytes = [];
for (let i = 0; i < hex.length; i += 2) {
bytes.push(parseInt(hex.substr(i, 2), 16));
}
return bytes;
}
function bytesToHex(bytes) {
return Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join('');
}
function showResult(flag) {
const resultContainer = document.getElementById('result-container');
const resultFlag = document.getElementById('result-flag');
resultFlag.textContent = flag;
resultContainer.classList.add('show');
// 自动复制到剪贴板
navigator.clipboard.writeText(flag).then(() => {
addLog('Flag已复制到剪贴板', 'success');
});
}
function loadExample() {
document.getElementById('p-input').value = '407803049564139560409879631113358278888733140263084768485722310176731727783189074396823474461249041';
document.getElementById('c-input').value = '273724405776192840968808904199790097747266675483664217133748454869235934407461809379517600593224622';
addLog('已加载示例数据', 'info');
}
function clearAll() {
if (isRunning) {
addLog('求解正在进行中,无法清空', 'warning');
return;
}
document.getElementById('p-input').value = '';
document.getElementById('c-input').value = '';
document.getElementById('result-container').classList.remove('show');
document.getElementById('progress-container').style.display = 'none';
document.getElementById('log-container').innerHTML = '<div class="log-entry">系统就绪,等待输入参数...</div>';
attempts = 0;
startTime = 0;
updateStats();
addLog('已清空所有数据', 'info');
}
// 页面加载完成后的初始化
document.addEventListener('DOMContentLoaded', function() {
addLog('CTF RSA求解器已就绪', 'success');
addLog('支持GPU加速并行计算', 'info');
// 自动加载示例
setTimeout(() => {
loadExample();
}, 500);
});
// 监听快捷键
document.addEventListener('keydown', function(e) {
if (e.ctrlKey || e.metaKey) {
switch(e.key) {
case 'Enter':
e.preventDefault();
solve();
break;
case 'l':
e.preventDefault();
loadExample();
break;
case 'Delete':
e.preventDefault();
clearAll();
break;
}
}
});
</script>
</body>
</html>