Skip to content

Instantly share code, notes, and snippets.

@ologunB
Created March 12, 2023 17:42
Show Gist options
  • Save ologunB/f37afe92a78c6193981fd225f1d35120 to your computer and use it in GitHub Desktop.
Save ologunB/f37afe92a78c6193981fd225f1d35120 to your computer and use it in GitHub Desktop.
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:mms_app/core/storage/local_storage.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sodium_libs/sodium_libs_sumo.dart';
class EncryptionTool {
static late Sodium sodium;
static Future<void> init() async {
sodium = await SodiumSumoInit.init();
}
static KeyPair generatePair() {
KeyPair keyPair = sodium.crypto.box.keyPair();
return keyPair;
}
static bool shitTestKeyPair(String pubKey, String secretKey) {
try {
Uint8List data = base64Decode('data');
Uint8List pub = base64Decode(pubKey);
Uint8List secret = base64Decode(secretKey);
/// seal the [data] with public key
final encrypted = sodium.crypto.box.seal(message: data, publicKey: pub);
/// unseal the [data] with given public and private keys
final decryptedKeys = sodium.crypto.box.sealOpen(
cipherText: encrypted,
publicKey: pub,
secretKey: SecureKey.fromList(sodium, secret),
);
return listEquals(decryptedKeys, data);
} catch (e) {
print(e);
return false;
}
}
static Future<EncryptedFile> encryptData(File file) async {
final Uint8List messageBytes = await file.readAsBytes();
print('normal data in mb: ${0.000001 * messageBytes.length}');
final nonce = sodium.randombytes.buf(sodium.crypto.secretBox.nonceBytes);
final SecureKey key = sodium.crypto.secretBox.keygen();
// encrypt data here
final encryptedData = sodium.crypto.secretBox.easy(
message: messageBytes,
nonce: nonce,
key: key,
);
Map<String, List> keys = {
'nonce': nonce,
'key': key.extractBytes(),
};
// seal the key with public key
final encryptedKeys = sodium.crypto.box.seal(
message: Uint8List.fromList(jsonEncode(keys).codeUnits),
publicKey: AppCache.getUser()!.getPubKey(),
);
print('encrypted data in mb: ${0.000001 * encryptedData.length}');
return EncryptedFile(encryptedData, base64Encode(encryptedKeys));
}
static Future<Uint8List> decryptData(
Uint8List cipherText, String encryptedKey) async {
print('decrypted data in mb: ${0.000001 * cipherText.length}');
// get private key
Uint8List? key = await readPrivateKey();
// unseal the key with public and private keys
final decryptedKeys = sodium.crypto.box.sealOpen(
cipherText: base64Decode(encryptedKey),
publicKey: AppCache.getUser()!.getPubKey(),
secretKey: SecureKey.fromList(sodium, key!),
);
Map<String, dynamic> keys = jsonDecode(String.fromCharCodes(decryptedKeys));
// decrypt data here
final decryptedData = sodium.crypto.secretBox.openEasy(
cipherText: cipherText,
nonce: Uint8List.fromList(keys['nonce']!.cast<int>()),
key: SecureKey.fromList(
sodium, Uint8List.fromList(keys['key']!.cast<int>())),
);
return decryptedData;
}
static Future<String> shareData(String key, String receiverPubKey) async {
// get private key
Uint8List? secretKey = await readPrivateKey();
// unseal the [key] with public and private keys
final decryptedKeys = sodium.crypto.box.sealOpen(
cipherText: base64Decode(key),
publicKey: AppCache.getUser()!.getPubKey(),
secretKey: SecureKey.fromList(sodium, secretKey!),
);
// seal the receiver public key
final encryptedKeys = sodium.crypto.box.seal(
message: decryptedKeys,
publicKey: base64Decode(receiverPubKey),
);
return base64Encode(encryptedKeys);
}
static savePrivateKey(String key) async {
Directory dir = await getApplicationDocumentsDirectory();
String filesPath = dir.path;
String? name = AppCache.getUser()?.id;
final file = File('$filesPath/$name.secret');
if (!file.existsSync()) file.createSync();
IOSink s = file.openWrite(mode: FileMode.write);
s.write(key);
await s.close();
}
static Future<String?> readKey() async {
Directory dir = await getApplicationDocumentsDirectory();
String filesPath = dir.path;
String? name = AppCache.getUser()?.id;
if (name == null) return null;
final file = File('$filesPath/$name.secret');
if (!file.existsSync()) return null;
return file.readAsStringSync();
}
static Future<Uint8List?> readPrivateKey() async {
String? val = await readKey();
if (val == null) return null;
return base64Decode(val);
}
}
class EncryptedFile {
String key;
Uint8List file;
EncryptedFile(this.file, this.key);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment