canvas-website/src/components/auth/CryptoDebug.tsx

265 lines
8.6 KiB
TypeScript

import React, { useState } from 'react';
import { CryptoAuthService } from '../../lib/auth/cryptoAuthService';
import * as crypto from '../../lib/auth/crypto';
const CryptoDebug: React.FC = () => {
const [testResults, setTestResults] = useState<string[]>([]);
const [testUsername, setTestUsername] = useState('testuser123');
const [isRunning, setIsRunning] = useState(false);
const addResult = (message: string) => {
setTestResults(prev => [...prev, `${new Date().toLocaleTimeString()}: ${message}`]);
};
const runCryptoTest = async () => {
setIsRunning(true);
setTestResults([]);
try {
addResult('Starting cryptographic authentication test...');
// Test 1: Key Generation
addResult('Testing key pair generation...');
const keyPair = await crypto.generateKeyPair();
if (keyPair) {
addResult('✓ Key pair generated successfully');
} else {
addResult('❌ Key pair generation failed');
return;
}
// Test 2: Public Key Export
addResult('Testing public key export...');
const publicKeyBase64 = await crypto.exportPublicKey(keyPair.publicKey);
if (publicKeyBase64) {
addResult('✓ Public key exported successfully');
} else {
addResult('❌ Public key export failed');
return;
}
// Test 3: Public Key Import
addResult('Testing public key import...');
const importedPublicKey = await crypto.importPublicKey(publicKeyBase64);
if (importedPublicKey) {
addResult('✓ Public key imported successfully');
} else {
addResult('❌ Public key import failed');
return;
}
// Test 4: Data Signing
addResult('Testing data signing...');
const testData = 'Hello, WebCryptoAPI!';
const signature = await crypto.signData(keyPair.privateKey, testData);
if (signature) {
addResult('✓ Data signed successfully');
} else {
addResult('❌ Data signing failed');
return;
}
// Test 5: Signature Verification
addResult('Testing signature verification...');
const isValid = await crypto.verifySignature(importedPublicKey, signature, testData);
if (isValid) {
addResult('✓ Signature verified successfully');
} else {
addResult('❌ Signature verification failed');
return;
}
// Test 6: User Registration
addResult(`Testing user registration for: ${testUsername}`);
const registerResult = await CryptoAuthService.register(testUsername);
if (registerResult.success) {
addResult('✓ User registration successful');
} else {
addResult(`❌ User registration failed: ${registerResult.error}`);
return;
}
// Test 7: User Login
addResult(`Testing user login for: ${testUsername}`);
const loginResult = await CryptoAuthService.login(testUsername);
if (loginResult.success) {
addResult('✓ User login successful');
} else {
addResult(`❌ User login failed: ${loginResult.error}`);
return;
}
// Test 8: Verify stored data integrity
addResult('Testing stored data integrity...');
const storedData = localStorage.getItem(`${testUsername}_authData`);
if (storedData) {
try {
const parsed = JSON.parse(storedData);
addResult(` - Challenge length: ${parsed.challenge?.length || 0}`);
addResult(` - Signature length: ${parsed.signature?.length || 0}`);
addResult(` - Timestamp: ${parsed.timestamp || 'missing'}`);
} catch (e) {
addResult(` - Data parse error: ${e}`);
}
} else {
addResult(' - No stored auth data found');
}
addResult('🎉 All cryptographic tests passed!');
} catch (error) {
addResult(`❌ Test error: ${error}`);
} finally {
setIsRunning(false);
}
};
const clearResults = () => {
setTestResults([]);
};
const checkStoredUsers = () => {
const users = crypto.getRegisteredUsers();
addResult(`Stored users: ${JSON.stringify(users)}`);
users.forEach(user => {
const publicKey = crypto.getPublicKey(user);
const authData = localStorage.getItem(`${user}_authData`);
addResult(`User: ${user}, Public Key: ${publicKey ? '✓' : '✗'}, Auth Data: ${authData ? '✓' : '✗'}`);
if (authData) {
try {
const parsed = JSON.parse(authData);
addResult(` - Challenge: ${parsed.challenge ? '✓' : '✗'}`);
addResult(` - Signature: ${parsed.signature ? '✓' : '✗'}`);
addResult(` - Timestamp: ${parsed.timestamp || '✗'}`);
} catch (e) {
addResult(` - Auth data parse error: ${e}`);
}
}
});
// Test the login popup functionality
addResult('Testing login popup user detection...');
try {
const storedUsers = JSON.parse(localStorage.getItem('registeredUsers') || '[]');
addResult(`All registered users: ${JSON.stringify(storedUsers)}`);
// Filter for users with valid keys (same logic as CryptoLogin)
const validUsers = storedUsers.filter((user: string) => {
const publicKey = localStorage.getItem(`${user}_publicKey`);
if (!publicKey) return false;
const authData = localStorage.getItem(`${user}_authData`);
if (!authData) return false;
try {
const parsed = JSON.parse(authData);
return parsed.challenge && parsed.signature && parsed.timestamp;
} catch (e) {
return false;
}
});
addResult(`Users with valid keys: ${JSON.stringify(validUsers)}`);
addResult(`Valid users count: ${validUsers.length}/${storedUsers.length}`);
if (validUsers.length > 0) {
addResult(`Login popup would suggest: ${validUsers[0]}`);
} else {
addResult('No valid users found - would default to registration mode');
}
} catch (e) {
addResult(`Error reading stored users: ${e}`);
}
};
const cleanupInvalidUsers = () => {
try {
const storedUsers = JSON.parse(localStorage.getItem('registeredUsers') || '[]');
const validUsers = storedUsers.filter((user: string) => {
const publicKey = localStorage.getItem(`${user}_publicKey`);
const authData = localStorage.getItem(`${user}_authData`);
if (!publicKey || !authData) return false;
try {
const parsed = JSON.parse(authData);
return parsed.challenge && parsed.signature && parsed.timestamp;
} catch (e) {
return false;
}
});
// Update the registered users list to only include valid users
localStorage.setItem('registeredUsers', JSON.stringify(validUsers));
addResult(`Cleaned up invalid users. Removed ${storedUsers.length - validUsers.length} invalid entries.`);
addResult(`Remaining valid users: ${JSON.stringify(validUsers)}`);
} catch (e) {
addResult(`Error cleaning up users: ${e}`);
}
};
return (
<div className="crypto-debug-container">
<h2>Cryptographic Authentication Debug</h2>
<div className="debug-controls">
<input
type="text"
value={testUsername}
onChange={(e) => setTestUsername(e.target.value)}
placeholder="Test username"
className="debug-input"
/>
<button
onClick={runCryptoTest}
disabled={isRunning}
className="debug-button"
>
{isRunning ? 'Running Tests...' : 'Run Crypto Test'}
</button>
<button
onClick={checkStoredUsers}
className="debug-button"
>
Check Stored Users
</button>
<button
onClick={cleanupInvalidUsers}
className="debug-button"
>
Cleanup Invalid Users
</button>
<button
onClick={clearResults}
disabled={isRunning}
className="debug-button"
>
Clear Results
</button>
</div>
<div className="debug-results">
<h3>Debug Results:</h3>
{testResults.length === 0 ? (
<p>No test results yet. Click "Run Crypto Test" to start.</p>
) : (
<div className="results-list">
{testResults.map((result, index) => (
<div key={index} className="result-item">
{result}
</div>
))}
</div>
)}
</div>
</div>
);
};
export default CryptoDebug;