import 'dart:typed_data'; import 'dart:math'; class RSA { final RSAPublicKey publicKey; final RSAPrivateKey privateKey; RSA._(this.publicKey, this.privateKey); static RSA generate({int keySize = 2048}) { final random = Random.secure(); // Generate RSA Key Pair final p = _generatePrime(keySize ~/ 2, random); final q = _generatePrime(keySize ~/ 2, random); final n = p * q; final phi = (p - BigInt.one) * (q - BigInt.one); final e = BigInt.from(65537); // Common public exponent final d = _modInverse(e, phi); final publicKey = RSAPublicKey(n, e); final privateKey = RSAPrivateKey(n, d); return RSA._(publicKey, privateKey); } static RSA fromKeyPair(RSAPrivateKey priv, RSAPublicKey pub) { RSA rsa = RSA._(pub, priv); return rsa; } Uint8List encrypt(Uint8List data) { return publicKey.encrypt(data); } Uint8List decrypt(Uint8List encryptedData) { return privateKey.decrypt(encryptedData); } Uint8List sign(Uint8List data) { return privateKey.sign(data); } bool verify(Uint8List data, Uint8List signature) { return publicKey.verify(data, signature); } static BigInt _generatePrime(int bitLength, Random random) { while (true) { final candidate = BigInt.from(random.nextInt(1 << (bitLength - 1)) | 1); if (_isPrime(candidate)) { return candidate; } } } static bool _isPrime(BigInt n) { if (n < BigInt.two) return false; for (BigInt i = BigInt.two; i * i <= n; i += BigInt.one) { if (n % i == BigInt.zero) return false; } return true; } static BigInt _modInverse(BigInt a, BigInt m) { BigInt m0 = m; BigInt y = BigInt.zero, x = BigInt.one; while (a > BigInt.one) { BigInt q = a ~/ m; BigInt t = m; m = a % m; a = t; t = y; y = x - q * y; x = t; } if (x < BigInt.zero) { x += m0; } return x; } } class RSAPublicKey { final BigInt modulus; final BigInt exponent; RSAPublicKey(this.modulus, this.exponent); Uint8List encrypt(Uint8List data) { final message = BigInt.parse( data.toList().map((b) => b.toRadixString(16).padLeft(2, '0')).join(), radix: 16); final encrypted = message.modPow(exponent, modulus); return Uint8List.fromList(encrypted .toRadixString(16) .padLeft((modulus.bitLength + 7) ~/ 8 * 2, '0') .codeUnits); } bool verify(Uint8List data, Uint8List signature) { final signedBigInt = BigInt.parse( signature .toList() .map((b) => b.toRadixString(16).padLeft(2, '0')) .join(), radix: 16); final decryptedSignature = signedBigInt.modPow(exponent, modulus); final message = BigInt.parse( data.toList().map((b) => b.toRadixString(16).padLeft(2, '0')).join(), radix: 16); return message == decryptedSignature; } } class RSAPrivateKey { final BigInt modulus; final BigInt exponent; RSAPrivateKey(this.modulus, this.exponent); Uint8List decrypt(Uint8List encryptedData) { final encryptedBigInt = BigInt.parse( encryptedData .toList() .map((b) => b.toRadixString(16).padLeft(2, '0')) .join(), radix: 16); final decrypted = encryptedBigInt.modPow(exponent, modulus); return Uint8List.fromList(decrypted .toRadixString(16) .padLeft((modulus.bitLength + 7) ~/ 8 * 2, '0') .codeUnits); } Uint8List sign(Uint8List data) { final message = BigInt.parse( data.toList().map((b) => b.toRadixString(16).padLeft(2, '0')).join(), radix: 16); final signed = message.modPow(exponent, modulus); return Uint8List.fromList(signed .toRadixString(16) .padLeft((modulus.bitLength + 7) ~/ 8 * 2, '0') .codeUnits); } }