Add API to chacha encrypt and decrypt a file

This commit is contained in:
Vishnu Mohandas 2020-09-25 21:15:00 +05:30
parent 74a43bf425
commit 3bad6a7c94
2 changed files with 101 additions and 0 deletions

View file

@ -0,0 +1,8 @@
import 'dart:typed_data';
class EncryptedFileAttributes {
final Uint8List key;
final Uint8List header;
EncryptedFileAttributes(this.key, this.header);
}

View file

@ -4,12 +4,105 @@ import 'dart:io' as io;
import 'package:aes_crypt/aes_crypt.dart';
import 'package:computer/computer.dart';
import 'package:encrypt/encrypt.dart';
import 'package:flutter_sodium/flutter_sodium.dart';
import 'package:logging/logging.dart';
import 'package:photos/core/configuration.dart';
import 'package:photos/models/encrypted_file_attributes.dart';
import 'package:steel_crypt/steel_crypt.dart' as steel;
import 'package:uuid/uuid.dart';
class CryptoUtil {
static Logger _logger = Logger("CryptoUtil");
static int encryptionBlockSize = 4 * 1024 * 1024;
static int decryptionBlockSize =
encryptionBlockSize + Sodium.cryptoSecretstreamXchacha20poly1305Abytes;
static Future<EncryptedFileAttributes> chachaEncrypt(
io.File sourceFile,
io.File destinationFile,
) async {
var encryptionStartTime = DateTime.now().millisecondsSinceEpoch;
final sourceFileLength = sourceFile.lengthSync();
_logger.info("Encrypting file of size " + sourceFileLength.toString());
final inputFile = await (sourceFile.open(mode: io.FileMode.read));
final outputFile =
await (destinationFile.open(mode: io.FileMode.writeOnlyAppend));
final key = Sodium.cryptoSecretstreamXchacha20poly1305Keygen();
final initPushResult =
Sodium.cryptoSecretstreamXchacha20poly1305InitPush(key);
var bytesRead = 0;
var encryptionTag = Sodium.cryptoSecretstreamXchacha20poly1305TagMessage;
while (
encryptionTag != Sodium.cryptoSecretstreamXchacha20poly1305TagFinal) {
bool isLastBlock = false;
var blockLength = encryptionBlockSize;
if (bytesRead + blockLength >= sourceFileLength) {
blockLength = sourceFileLength - bytesRead;
isLastBlock = true;
}
final blockData = await inputFile.read(blockLength);
bytesRead += blockLength;
if (isLastBlock) {
encryptionTag = Sodium.cryptoSecretstreamXchacha20poly1305TagFinal;
}
final encryptedData = Sodium.cryptoSecretstreamXchacha20poly1305Push(
initPushResult.state, blockData, null, encryptionTag);
outputFile.writeFromSync(encryptedData);
}
await inputFile.close();
await outputFile.close();
_logger.info("ChaCha20 Encryption time: " +
(DateTime.now().millisecondsSinceEpoch - encryptionStartTime)
.toString());
return EncryptedFileAttributes(key, initPushResult.header);
}
static Future<void> chachaDecrypt(
io.File sourceFile,
io.File destinationFile,
EncryptedFileAttributes attributes,
) async {
var decryptionStartTime = DateTime.now().millisecondsSinceEpoch;
final sourceFileLength = sourceFile.lengthSync();
_logger.info("Decrypting file of size " + sourceFileLength.toString());
final inputFile = await (sourceFile.open(mode: io.FileMode.read));
final outputFile =
await (destinationFile.open(mode: io.FileMode.writeOnlyAppend));
final pullState = Sodium.cryptoSecretstreamXchacha20poly1305InitPull(
attributes.header, attributes.key);
var bytesRead = 0;
var tag = Sodium.cryptoSecretstreamXchacha20poly1305TagMessage;
while (tag != Sodium.cryptoSecretstreamXchacha20poly1305TagFinal) {
var blockLength = decryptionBlockSize;
if (bytesRead + blockLength >= sourceFileLength) {
blockLength = sourceFileLength - bytesRead;
}
final blockData = await inputFile.read(blockLength);
bytesRead += blockLength;
final pullResult = Sodium.cryptoSecretstreamXchacha20poly1305Pull(
pullState, blockData, null);
outputFile.writeFromSync(pullResult.m);
tag = pullResult.tag;
}
await inputFile.close();
await outputFile.close();
_logger.info("ChaCha20 Decryption time: " +
(DateTime.now().millisecondsSinceEpoch - decryptionStartTime)
.toString());
}
static Uint8List getSecureRandomBytes({int length = 32}) {
return SecureRandom(length).bytes;
}