import 'dart:convert'; import 'dart:typed_data'; import 'package:bcrypt/bcrypt.dart'; import 'package:collection/collection.dart'; import 'package:crypto/crypto.dart'; import 'package:crypton/crypton.dart'; import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; import '../config/config.dart'; class KeyPair { final String publicKey; final String privateKey; KeyPair({required this.publicKey, required this.privateKey}); Map toJson() => { 'publicKey': publicKey, 'privateKey': privateKey, }; factory KeyPair.fromJson(Map json) { return KeyPair( publicKey: json['publicKey'] as String, privateKey: json['privateKey'] as String, ); } } class CryptoService { /// Generate a new Ed25519 key pair static KeyPair generateKeyPair() { final keyPair = ECKeypair.fromRandom(); return KeyPair( publicKey: keyPair.publicKey.toString(), privateKey: keyPair.privateKey.toString(), ); } /// Sign data with private key static String sign(String data, String privateKey) { final privKey = ECPrivateKey.fromString(privateKey); final signature = privKey.createSignature(data); return signature.toString(); } /// Verify signature with public key static bool verify(String data, String signature, String publicKey) { try { final pubKey = ECPublicKey.fromString(publicKey); final sig = ECSignature.fromString(signature); return pubKey.verifySignature(data, sig); } catch (_) { return false; } } /// Encrypt private key with password (for storage/backup) static EncryptedKey encryptPrivateKey(String privateKey, String password) { final salt = BCrypt.gensalt(); final key = _deriveKey(password, salt); final encrypted = _xorEncrypt(privateKey, key); return EncryptedKey( encryptedData: encrypted, salt: salt, ); } /// Decrypt private key with password static String? decryptPrivateKey( String encryptedData, String salt, String password) { try { final key = _deriveKey(password, salt); return _xorDecrypt(encryptedData, key); } catch (_) { return null; } } static String _deriveKey(String password, String salt) { final bytes = utf8.encode(password + salt); final hash = sha256.convert(bytes); return hash.toString(); } static String _xorEncrypt(String data, String key) { final dataBytes = utf8.encode(data); final keyBytes = utf8.encode(key); final encrypted = []; for (var i = 0; i < dataBytes.length; i++) { encrypted.add(dataBytes[i] ^ keyBytes[i % keyBytes.length]); } return base64Encode(encrypted); } static String _xorDecrypt(String encrypted, String key) { final encryptedBytes = base64Decode(encrypted); final keyBytes = utf8.encode(key); final decrypted = []; for (var i = 0; i < encryptedBytes.length; i++) { decrypted.add(encryptedBytes[i] ^ keyBytes[i % keyBytes.length]); } return utf8.decode(decrypted); } } class EncryptedKey { final String encryptedData; final String salt; EncryptedKey({required this.encryptedData, required this.salt}); Map toJson() => { 'encryptedData': encryptedData, 'salt': salt, }; } class AuthService { /// Generate JWT token for user static String generateToken(String userId, String username) { final payload = { 'sub': userId, 'username': username, }; final jwt = JWT(payload); return jwt.sign( SecretKey(Config.jwtSecret), expiresIn: Config.tokenExpiry, ); } /// Verify JWT token and return payload static Map? verifyToken(String token) { try { final jwt = JWT.verify(token, SecretKey(Config.jwtSecret)); return Map.from(jwt.payload as Map); } catch (_) { return null; } } /// Hash password with bcrypt static String hashPassword(String password) { return BCrypt.hashpw(password, BCrypt.gensalt()); } /// Verify password against hash static bool verifyPassword(String password, String hash) { return BCrypt.checkpw(password, hash); } /// Generate a nonce for signature verification static String generateNonce() { final bytes = List.generate(32, (_) => DateTime.now().microsecondsSinceEpoch % 256); final randomBytes = sha256.convert(bytes as Uint8List); return randomBytes.toString().substring(0, 32); } }