Add encryption routines to the server
This commit is contained in:
parent
d7cc626144
commit
38eb7c6acd
6 changed files with 472 additions and 13 deletions
151
lib/encryption/rsa.dart
Normal file
151
lib/encryption/rsa.dart
Normal file
|
@ -0,0 +1,151 @@
|
|||
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);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue