Files
DiscordClone/Frontend/Electron/src/pages/Register.jsx
2025-12-30 13:53:13 -06:00

130 lines
5.0 KiB
JavaScript

import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
const Register = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const navigate = useNavigate();
const handleRegister = async (e) => {
e.preventDefault();
setError('');
setLoading(true);
try {
console.log('Starting registration for:', username);
// 1. Generate Salt and Master Key (MK)
const salt = await window.cryptoAPI.randomBytes(16);
const mk = await window.cryptoAPI.randomBytes(16); // 128-bit MK
console.log('Generated Salt and MK');
// 2. Derive Keys (DEK, DAK)
const { dek, dak } = await window.cryptoAPI.deriveAuthKeys(password, salt);
console.log('Derived keys');
// 3. Encrypt MK with DEK
const encryptedMKObj = await window.cryptoAPI.encryptData(mk, dek);
const encryptedMK = JSON.stringify(encryptedMKObj); // Store as JSON string {content, tag, iv}
// 4. Hash DAK for Auth Proof
const hak = await window.cryptoAPI.sha256(dak);
// 5. Generate Key Pairs
const keys = await window.cryptoAPI.generateKeys();
// 6. Encrypt Private Keys with MK
// We need to encrypt the private keys so the server can store them safely
// MK is used to encrypt these.
const encryptedRsaPriv = await window.cryptoAPI.encryptData(keys.rsaPriv, mk);
const encryptedEdPriv = await window.cryptoAPI.encryptData(keys.edPriv, mk);
const encryptedPrivateKeys = JSON.stringify({
rsa: encryptedRsaPriv,
ed: encryptedEdPriv
});
// 7. Send to Backend
const payload = {
username,
salt,
encryptedMK,
hak,
publicKey: keys.rsaPub,
signingKey: keys.edPub,
encryptedPrivateKeys // Note: Schema might need this column or we pack it into another
};
// NOTE: The schema in overview.md had 'Encrypted Private Keys' in the text but not explicitly in the SQL CREATE TABLE snippet provided in the prompt's overview.md (it was in the text description).
// The SQL snippet had: encrypted_master_key, hashed_auth_key, public_identity_key, public_signing_key.
// It did NOT have a column for encrypted_private_keys in the SQL block in overview.md.
// I should check schema.sql I created.
const response = await fetch('http://localhost:3000/api/auth/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || 'Registration failed');
}
console.log('Registration successful:', data);
navigate('/');
} catch (err) {
console.error('Registration error:', err);
setError(err.message);
} finally {
setLoading(false);
}
};
return (
<div className="auth-container">
<div className="auth-box">
<div className="auth-header">
<h2>Create an Account</h2>
<p>Join the secure chat!</p>
</div>
{error && <div style={{ color: 'red', marginBottom: 10, textAlign: 'center' }}>{error}</div>}
<form onSubmit={handleRegister}>
<div className="form-group">
<label>Username</label>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
disabled={loading}
/>
</div>
<div className="form-group">
<label>Password</label>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
disabled={loading}
/>
</div>
<button type="submit" className="auth-button" disabled={loading}>
{loading ? 'Generating Keys...' : 'Continue'}
</button>
</form>
<div className="auth-footer">
Already have an account? <Link to="/">Log In</Link>
</div>
</div>
</div>
);
};
export default Register;