Move to XChaCha for thumbnail and metadata encryption
This commit is contained in:
parent
bdd2e35a66
commit
27f019af57
11 changed files with 137 additions and 206 deletions
|
@ -1,7 +1,6 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:photos/models/decryption_params.dart';
|
||||
import 'package:photos/models/file_type.dart';
|
||||
import 'package:photos/models/location.dart';
|
||||
import 'package:photos/models/file.dart';
|
||||
|
@ -32,9 +31,11 @@ class FilesDB {
|
|||
static final columnCreationTime = 'creation_time';
|
||||
static final columnModificationTime = 'modification_time';
|
||||
static final columnUpdationTime = 'updation_time';
|
||||
static final columnFileDecryptionParams = 'file_decryption_params';
|
||||
static final columnThumbnailDecryptionParams = 'thumbnail_decryption_params';
|
||||
static final columnMetadataDecryptionParams = 'metadata_decryption_params';
|
||||
static final columnEncryptedKey = 'encrypted_key';
|
||||
static final columnKeyDecryptionNonce = 'key_decryption_nonce';
|
||||
static final columnFileDecryptionHeader = 'file_decryption_header';
|
||||
static final columnThumbnailDecryptionHeader = 'thumbnail_decryption_header';
|
||||
static final columnMetadataDecryptionHeader = 'metadata_decryption_header';
|
||||
|
||||
// make this a singleton class
|
||||
FilesDB._privateConstructor();
|
||||
|
@ -76,9 +77,12 @@ class FilesDB {
|
|||
$columnCreationTime TEXT NOT NULL,
|
||||
$columnModificationTime TEXT NOT NULL,
|
||||
$columnUpdationTime TEXT,
|
||||
$columnFileDecryptionParams TEXT,
|
||||
$columnThumbnailDecryptionParams TEXT,
|
||||
$columnMetadataDecryptionParams TEXT
|
||||
$columnEncryptedKey TEXT,
|
||||
$columnKeyDecryptionNonce TEXT,
|
||||
$columnUpdationTime TEXT,
|
||||
$columnFileDecryptionHeader TEXT,
|
||||
$columnThumbnailDecryptionHeader TEXT,
|
||||
$columnMetadataDecryptionHeader TEXT
|
||||
)
|
||||
''');
|
||||
}
|
||||
|
@ -227,18 +231,21 @@ class FilesDB {
|
|||
int generatedID,
|
||||
int uploadedID,
|
||||
int updationTime,
|
||||
DecryptionParams fileDecryptionParams,
|
||||
DecryptionParams thumbnailDecryptionParams,
|
||||
DecryptionParams metadataDecryptionParams,
|
||||
String encryptedKey,
|
||||
String keyDecryptionNonce,
|
||||
String fileDecryptionHeader,
|
||||
String thumbnailDecryptionHeader,
|
||||
String metadataDecryptionHeader,
|
||||
) async {
|
||||
final db = await instance.database;
|
||||
final values = new Map<String, dynamic>();
|
||||
values[columnUploadedFileID] = uploadedID;
|
||||
values[columnUpdationTime] = updationTime;
|
||||
values[columnFileDecryptionParams] = fileDecryptionParams.toJson();
|
||||
values[columnThumbnailDecryptionParams] =
|
||||
thumbnailDecryptionParams.toJson();
|
||||
values[columnMetadataDecryptionParams] = metadataDecryptionParams.toJson();
|
||||
values[columnEncryptedKey] = encryptedKey;
|
||||
values[columnKeyDecryptionNonce] = keyDecryptionNonce;
|
||||
values[columnFileDecryptionHeader] = fileDecryptionHeader;
|
||||
values[columnThumbnailDecryptionHeader] = thumbnailDecryptionHeader;
|
||||
values[columnMetadataDecryptionHeader] = metadataDecryptionHeader;
|
||||
return await db.update(
|
||||
table,
|
||||
values,
|
||||
|
@ -390,16 +397,11 @@ class FilesDB {
|
|||
row[columnCreationTime] = file.creationTime;
|
||||
row[columnModificationTime] = file.modificationTime;
|
||||
row[columnUpdationTime] = file.updationTime;
|
||||
row[columnFileDecryptionParams] = file.fileDecryptionParams == null
|
||||
? null
|
||||
: file.fileDecryptionParams.toJson();
|
||||
row[columnThumbnailDecryptionParams] =
|
||||
file.thumbnailDecryptionParams == null
|
||||
? null
|
||||
: file.thumbnailDecryptionParams.toJson();
|
||||
row[columnMetadataDecryptionParams] = file.metadataDecryptionParams == null
|
||||
? null
|
||||
: file.metadataDecryptionParams.toJson();
|
||||
row[columnEncryptedKey] = file.encryptedKey;
|
||||
row[columnKeyDecryptionNonce] = file.keyDecryptionNonce;
|
||||
row[columnFileDecryptionHeader] = file.fileDecryptionHeader;
|
||||
row[columnThumbnailDecryptionHeader] = file.thumbnailDecryptionHeader;
|
||||
row[columnMetadataDecryptionHeader] = file.metadataDecryptionHeader;
|
||||
return row;
|
||||
}
|
||||
|
||||
|
@ -422,12 +424,11 @@ class FilesDB {
|
|||
file.updationTime = row[columnUpdationTime] == null
|
||||
? -1
|
||||
: int.parse(row[columnUpdationTime]);
|
||||
file.fileDecryptionParams =
|
||||
DecryptionParams.fromJson(row[columnFileDecryptionParams]);
|
||||
file.thumbnailDecryptionParams =
|
||||
DecryptionParams.fromJson(row[columnThumbnailDecryptionParams]);
|
||||
file.metadataDecryptionParams =
|
||||
DecryptionParams.fromJson(row[columnMetadataDecryptionParams]);
|
||||
file.encryptedKey = row[columnEncryptedKey];
|
||||
file.keyDecryptionNonce = row[columnKeyDecryptionNonce];
|
||||
file.fileDecryptionHeader = row[columnFileDecryptionHeader];
|
||||
file.thumbnailDecryptionHeader = row[columnThumbnailDecryptionHeader];
|
||||
file.metadataDecryptionHeader = row[columnMetadataDecryptionHeader];
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
|
8
lib/models/chacha_encryption_result.dart
Normal file
8
lib/models/chacha_encryption_result.dart
Normal file
|
@ -0,0 +1,8 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
class ChaChaEncryptionResult {
|
||||
final Uint8List encryptedData;
|
||||
final Uint8List header;
|
||||
|
||||
ChaChaEncryptionResult(this.encryptedData, this.header);
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
import 'dart:convert';
|
||||
|
||||
class DecryptionParams {
|
||||
final String encryptedKey;
|
||||
final String keyDecryptionNonce;
|
||||
String header;
|
||||
String nonce;
|
||||
|
||||
DecryptionParams({
|
||||
this.encryptedKey,
|
||||
this.keyDecryptionNonce,
|
||||
this.header,
|
||||
this.nonce,
|
||||
});
|
||||
|
||||
DecryptionParams copyWith({
|
||||
String encryptedKey,
|
||||
String keyDecryptionNonce,
|
||||
String header,
|
||||
String nonce,
|
||||
}) {
|
||||
return DecryptionParams(
|
||||
encryptedKey: encryptedKey ?? this.encryptedKey,
|
||||
keyDecryptionNonce: keyDecryptionNonce ?? this.keyDecryptionNonce,
|
||||
header: header ?? this.header,
|
||||
nonce: nonce ?? this.nonce,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'encryptedKey': encryptedKey,
|
||||
'keyDecryptionNonce': keyDecryptionNonce,
|
||||
'header': header,
|
||||
'nonce': nonce,
|
||||
};
|
||||
}
|
||||
|
||||
factory DecryptionParams.fromMap(Map<String, dynamic> map) {
|
||||
if (map == null) return null;
|
||||
|
||||
return DecryptionParams(
|
||||
encryptedKey: map['encryptedKey'],
|
||||
keyDecryptionNonce: map['keyDecryptionNonce'],
|
||||
header: map['header'],
|
||||
nonce: map['nonce'],
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory DecryptionParams.fromJson(String source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return DecryptionParams.fromMap(json.decode(source));
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DecryptionParams(encryptedKey: $encryptedKey, keyDecryptionNonce: $keyDecryptionNonce, header: $header, nonce: $nonce)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object o) {
|
||||
if (identical(this, o)) return true;
|
||||
|
||||
return o is DecryptionParams &&
|
||||
o.encryptedKey == encryptedKey &&
|
||||
o.keyDecryptionNonce == keyDecryptionNonce &&
|
||||
o.header == header &&
|
||||
o.nonce == nonce;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return encryptedKey.hashCode ^
|
||||
keyDecryptionNonce.hashCode ^
|
||||
header.hashCode ^
|
||||
nonce.hashCode;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:photo_manager/photo_manager.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/models/decryption_params.dart';
|
||||
import 'package:photos/models/file_type.dart';
|
||||
import 'package:photos/models/location.dart';
|
||||
|
||||
|
@ -19,9 +18,11 @@ class File {
|
|||
int updationTime;
|
||||
Location location;
|
||||
FileType fileType;
|
||||
DecryptionParams fileDecryptionParams;
|
||||
DecryptionParams thumbnailDecryptionParams;
|
||||
DecryptionParams metadataDecryptionParams;
|
||||
String encryptedKey;
|
||||
String keyDecryptionNonce;
|
||||
String fileDecryptionHeader;
|
||||
String thumbnailDecryptionHeader;
|
||||
String metadataDecryptionHeader;
|
||||
|
||||
File();
|
||||
|
||||
|
@ -137,10 +138,7 @@ class File {
|
|||
@override
|
||||
String toString() {
|
||||
return '''File(generatedId: $generatedID, uploadedFileId: $uploadedFileID,
|
||||
localId: $localID, title: $title, deviceFolder: $deviceFolder,
|
||||
fileDecryptionParams: $fileDecryptionParams,
|
||||
thumbnailDecryptionParams: $thumbnailDecryptionParams,
|
||||
metadataDecryptionParams: $metadataDecryptionParams,
|
||||
localId: $localID, title: $title, deviceFolder: $deviceFolder,
|
||||
location: $location, fileType: $fileType, creationTime: $creationTime,
|
||||
modificationTime: $modificationTime, updationTime: $updationTime)''';
|
||||
}
|
||||
|
|
5
lib/services/collections_service.dart
Normal file
5
lib/services/collections_service.dart
Normal file
|
@ -0,0 +1,5 @@
|
|||
import 'package:logging/logging.dart';
|
||||
|
||||
class CollectionsService {
|
||||
final _logger = Logger("CollectionsService");
|
||||
}
|
|
@ -74,9 +74,11 @@ class FolderSharingService {
|
|||
existingPhoto.generatedID,
|
||||
file.uploadedFileID,
|
||||
file.updationTime,
|
||||
file.fileDecryptionParams,
|
||||
file.thumbnailDecryptionParams,
|
||||
file.metadataDecryptionParams,
|
||||
file.encryptedKey,
|
||||
file.keyDecryptionNonce,
|
||||
file.fileDecryptionHeader,
|
||||
file.thumbnailDecryptionHeader,
|
||||
file.metadataDecryptionHeader,
|
||||
);
|
||||
} catch (e) {
|
||||
await FilesDB.instance.insert(file);
|
||||
|
|
|
@ -229,9 +229,11 @@ class SyncService {
|
|||
file.generatedID,
|
||||
uploadedFile.uploadedFileID,
|
||||
uploadedFile.updationTime,
|
||||
file.fileDecryptionParams,
|
||||
file.thumbnailDecryptionParams,
|
||||
file.metadataDecryptionParams,
|
||||
file.encryptedKey,
|
||||
file.keyDecryptionNonce,
|
||||
file.fileDecryptionHeader,
|
||||
file.thumbnailDecryptionHeader,
|
||||
file.metadataDecryptionHeader,
|
||||
);
|
||||
Bus.instance.fire(PhotoUploadEvent(
|
||||
completed: i + 1, total: filesToBeUploaded.length));
|
||||
|
@ -245,20 +247,18 @@ class SyncService {
|
|||
Future _storeDiff(List<File> diff, String prefKey) async {
|
||||
for (File file in diff) {
|
||||
try {
|
||||
final existingPhoto = await _db.getMatchingFile(
|
||||
file.localID,
|
||||
file.title,
|
||||
file.deviceFolder,
|
||||
file.creationTime,
|
||||
file.modificationTime,
|
||||
final existingFile = await _db.getMatchingFile(file.localID, file.title,
|
||||
file.deviceFolder, file.creationTime, file.modificationTime,
|
||||
alternateTitle: getHEICFileNameForJPG(file));
|
||||
await _db.update(
|
||||
existingPhoto.generatedID,
|
||||
existingFile.generatedID,
|
||||
file.uploadedFileID,
|
||||
file.updationTime,
|
||||
file.fileDecryptionParams,
|
||||
file.thumbnailDecryptionParams,
|
||||
file.metadataDecryptionParams,
|
||||
file.encryptedKey,
|
||||
file.keyDecryptionNonce,
|
||||
file.fileDecryptionHeader,
|
||||
file.thumbnailDecryptionHeader,
|
||||
file.metadataDecryptionHeader,
|
||||
);
|
||||
} catch (e) {
|
||||
file.localID = null; // File uploaded from a different device
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'dart:io' as io;
|
|||
import 'package:computer/computer.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:photos/models/chacha_encryption_result.dart';
|
||||
|
||||
import 'package:photos/models/encrypted_data_attributes.dart';
|
||||
import 'package:photos/models/encrypted_file_attributes.dart';
|
||||
|
@ -32,7 +33,7 @@ bool cryptoPwhashStrVerify(Map<String, dynamic> args) {
|
|||
return Sodium.cryptoPwhashStrVerify(args["hash"], args["input"]) == 0;
|
||||
}
|
||||
|
||||
ChaChaAttributes chachaEncrypt(Map<String, dynamic> args) {
|
||||
ChaChaAttributes chachaEncryptFile(Map<String, dynamic> args) {
|
||||
final encryptionStartTime = DateTime.now().millisecondsSinceEpoch;
|
||||
final logger = Logger("ChaChaEncrypt");
|
||||
final sourceFile = io.File(args["sourceFilePath"]);
|
||||
|
@ -111,15 +112,33 @@ class CryptoUtil {
|
|||
args["source"] = source;
|
||||
args["nonce"] = nonce;
|
||||
args["key"] = key;
|
||||
final encryptedData =
|
||||
await Computer().compute(cryptoSecretboxEasy, param: args);
|
||||
|
||||
final encryptedData = cryptoSecretboxEasy(args);
|
||||
return EncryptedData(
|
||||
EncryptionAttribute(bytes: key),
|
||||
EncryptionAttribute(bytes: nonce),
|
||||
EncryptionAttribute(bytes: encryptedData));
|
||||
}
|
||||
|
||||
static ChaChaEncryptionResult encryptStream(Uint8List source, Uint8List key) {
|
||||
final initPushResult =
|
||||
Sodium.cryptoSecretstreamXchacha20poly1305InitPush(key);
|
||||
final encryptedData = Sodium.cryptoSecretstreamXchacha20poly1305Push(
|
||||
initPushResult.state,
|
||||
source,
|
||||
null,
|
||||
Sodium.cryptoSecretstreamXchacha20poly1305TagFinal);
|
||||
return ChaChaEncryptionResult(encryptedData, initPushResult.header);
|
||||
}
|
||||
|
||||
static Uint8List decryptStream(
|
||||
Uint8List source, Uint8List key, Uint8List header) {
|
||||
final pullState =
|
||||
Sodium.cryptoSecretstreamXchacha20poly1305InitPull(header, key);
|
||||
final pullResult =
|
||||
Sodium.cryptoSecretstreamXchacha20poly1305Pull(pullState, source, null);
|
||||
return pullResult.m;
|
||||
}
|
||||
|
||||
static Future<Uint8List> decrypt(
|
||||
Uint8List cipher, Uint8List key, Uint8List nonce,
|
||||
{bool background = false}) async {
|
||||
|
@ -141,7 +160,7 @@ class CryptoUtil {
|
|||
final args = Map<String, dynamic>();
|
||||
args["sourceFilePath"] = sourceFilePath;
|
||||
args["destinationFilePath"] = destinationFilePath;
|
||||
return Computer().compute(chachaEncrypt, param: args);
|
||||
return Computer().compute(chachaEncryptFile, param: args);
|
||||
}
|
||||
|
||||
static Future<void> decryptFile(
|
||||
|
|
|
@ -6,9 +6,9 @@ import 'package:logging/logging.dart';
|
|||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/events/remote_sync_event.dart';
|
||||
import 'package:photos/models/decryption_params.dart';
|
||||
import 'package:photos/models/file.dart';
|
||||
import 'package:photos/utils/crypto_util.dart';
|
||||
import 'package:photos/utils/file_util.dart';
|
||||
|
||||
class DiffFetcher {
|
||||
final _logger = Logger("FileDownloader");
|
||||
|
@ -36,21 +36,16 @@ class DiffFetcher {
|
|||
file.ownerID = item["ownerID"];
|
||||
file.updationTime = item["updationTime"];
|
||||
file.isEncrypted = true;
|
||||
file.fileDecryptionParams =
|
||||
DecryptionParams.fromMap(item["file"]["decryptionParams"]);
|
||||
file.thumbnailDecryptionParams = DecryptionParams.fromMap(
|
||||
item["thumbnail"]["decryptionParams"]);
|
||||
file.metadataDecryptionParams = DecryptionParams.fromMap(
|
||||
item["metadata"]["decryptionParams"]);
|
||||
final metadataDecryptionKey = await CryptoUtil.decrypt(
|
||||
Sodium.base642bin(file.metadataDecryptionParams.encryptedKey),
|
||||
Configuration.instance.getKey(),
|
||||
Sodium.base642bin(
|
||||
file.metadataDecryptionParams.keyDecryptionNonce));
|
||||
final encodedMetadata = await CryptoUtil.decrypt(
|
||||
file.encryptedKey = item["encryptedKey"];
|
||||
file.keyDecryptionNonce = item["keyDecryptionNonce"];
|
||||
file.fileDecryptionHeader = item["fileDecryptionHeader"];
|
||||
file.thumbnailDecryptionHeader =
|
||||
item["thumbnailDecryptionHeader"];
|
||||
file.metadataDecryptionHeader = item["metadataDecryptionHeader"];
|
||||
final encodedMetadata = CryptoUtil.decryptStream(
|
||||
Sodium.base642bin(item["metadata"]["encryptedData"]),
|
||||
metadataDecryptionKey,
|
||||
Sodium.base642bin(file.metadataDecryptionParams.nonce),
|
||||
await decryptFileKey(file),
|
||||
Sodium.base642bin(file.metadataDecryptionHeader),
|
||||
);
|
||||
Map<String, dynamic> metadata =
|
||||
jsonDecode(utf8.decode(encodedMetadata));
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io' as io;
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import 'package:photos/core/constants.dart';
|
||||
import 'package:photos/models/decryption_params.dart';
|
||||
import 'package:photos/models/file.dart';
|
||||
import 'package:photos/models/upload_url.dart';
|
||||
import 'package:photos/utils/crypto_util.dart';
|
||||
|
@ -56,16 +56,6 @@ class FileUploader {
|
|||
final fileUploadURL = await getUploadURL();
|
||||
String fileObjectKey = await putFile(fileUploadURL, encryptedFile);
|
||||
|
||||
final encryptedFileKey = await CryptoUtil.encrypt(
|
||||
fileAttributes.key.bytes,
|
||||
key: Configuration.instance.getKey(),
|
||||
);
|
||||
final fileDecryptionParams = DecryptionParams(
|
||||
encryptedKey: encryptedFileKey.encryptedData.base64,
|
||||
keyDecryptionNonce: encryptedFileKey.nonce.base64,
|
||||
header: fileAttributes.header.base64,
|
||||
);
|
||||
|
||||
final thumbnailData = (await (await file.getAsset()).thumbDataWithSize(
|
||||
THUMBNAIL_LARGE_SIZE,
|
||||
THUMBNAIL_LARGE_SIZE,
|
||||
|
@ -74,47 +64,37 @@ class FileUploader {
|
|||
final encryptedThumbnailName =
|
||||
file.generatedID.toString() + "_thumbnail.encrypted";
|
||||
final encryptedThumbnailPath = tempDirectory + encryptedThumbnailName;
|
||||
final encryptedThumbnail = await CryptoUtil.encrypt(thumbnailData);
|
||||
final encryptedThumbnail =
|
||||
CryptoUtil.encryptStream(thumbnailData, fileAttributes.key.bytes);
|
||||
io.File(encryptedThumbnailPath)
|
||||
.writeAsBytesSync(encryptedThumbnail.encryptedData.bytes);
|
||||
.writeAsBytesSync(encryptedThumbnail.encryptedData);
|
||||
|
||||
final thumbnailUploadURL = await getUploadURL();
|
||||
String thumbnailObjectKey =
|
||||
await putFile(thumbnailUploadURL, io.File(encryptedThumbnailPath));
|
||||
|
||||
final encryptedThumbnailKey = await CryptoUtil.encrypt(
|
||||
encryptedThumbnail.key.bytes,
|
||||
final encryptedMetadata = CryptoUtil.encryptStream(
|
||||
utf8.encode(jsonEncode(file.getMetadata())), fileAttributes.key.bytes);
|
||||
|
||||
final encryptedFileKey = await CryptoUtil.encrypt(
|
||||
fileAttributes.key.bytes,
|
||||
key: Configuration.instance.getKey(),
|
||||
);
|
||||
final thumbnailDecryptionParams = DecryptionParams(
|
||||
encryptedKey: encryptedThumbnailKey.encryptedData.base64,
|
||||
keyDecryptionNonce: encryptedThumbnailKey.nonce.base64,
|
||||
nonce: encryptedThumbnail.nonce.base64,
|
||||
);
|
||||
|
||||
final metadata = jsonEncode(file.getMetadata());
|
||||
final encryptedMetadata = await CryptoUtil.encrypt(utf8.encode(metadata));
|
||||
final encryptedMetadataKey = await CryptoUtil.encrypt(
|
||||
encryptedMetadata.key.bytes,
|
||||
key: Configuration.instance.getKey(),
|
||||
);
|
||||
final metadataDecryptionParams = DecryptionParams(
|
||||
encryptedKey: encryptedMetadataKey.encryptedData.base64,
|
||||
keyDecryptionNonce: encryptedMetadataKey.nonce.base64,
|
||||
nonce: encryptedMetadata.nonce.base64,
|
||||
);
|
||||
final data = {
|
||||
"encryptedKey": encryptedFileKey.encryptedData.base64,
|
||||
"keyDecryptionNonce": encryptedFileKey.nonce.base64,
|
||||
"file": {
|
||||
"objectKey": fileObjectKey,
|
||||
"decryptionParams": fileDecryptionParams.toMap(),
|
||||
"header": fileAttributes.header.base64,
|
||||
},
|
||||
"thumbnail": {
|
||||
"objectKey": thumbnailObjectKey,
|
||||
"decryptionParams": thumbnailDecryptionParams.toMap(),
|
||||
"header": Sodium.bin2base64(encryptedThumbnail.header),
|
||||
},
|
||||
"metadata": {
|
||||
"encryptedData": encryptedMetadata.encryptedData.base64,
|
||||
"decryptionParams": metadataDecryptionParams.toMap(),
|
||||
"encryptedData": Sodium.bin2base64(encryptedMetadata.encryptedData),
|
||||
"header": Sodium.bin2base64(encryptedMetadata.header),
|
||||
}
|
||||
};
|
||||
return _dio
|
||||
|
@ -131,9 +111,13 @@ class FileUploader {
|
|||
file.uploadedFileID = data["id"];
|
||||
file.updationTime = data["updationTime"];
|
||||
file.ownerID = data["ownerID"];
|
||||
file.fileDecryptionParams = fileDecryptionParams;
|
||||
file.thumbnailDecryptionParams = thumbnailDecryptionParams;
|
||||
file.metadataDecryptionParams = metadataDecryptionParams;
|
||||
file.encryptedKey = encryptedFileKey.encryptedData.base64;
|
||||
file.keyDecryptionNonce = encryptedFileKey.nonce.base64;
|
||||
file.fileDecryptionHeader = fileAttributes.header.base64;
|
||||
file.thumbnailDecryptionHeader =
|
||||
Sodium.bin2base64(encryptedThumbnail.header);
|
||||
file.metadataDecryptionHeader =
|
||||
Sodium.bin2base64(encryptedMetadata.header);
|
||||
return file;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -178,12 +178,9 @@ Future<io.File> _downloadAndDecrypt(File file, BaseCacheManager cacheManager,
|
|||
logger.info("File downloaded: " + file.uploadedFileID.toString());
|
||||
var attributes = ChaChaAttributes(
|
||||
EncryptionAttribute(
|
||||
bytes: await CryptoUtil.decrypt(
|
||||
Sodium.base642bin(file.fileDecryptionParams.encryptedKey),
|
||||
Configuration.instance.getKey(),
|
||||
Sodium.base642bin(file.fileDecryptionParams.keyDecryptionNonce),
|
||||
)),
|
||||
EncryptionAttribute(base64: file.fileDecryptionParams.header),
|
||||
bytes: await decryptFileKey(file),
|
||||
),
|
||||
EncryptionAttribute(base64: file.fileDecryptionHeader),
|
||||
);
|
||||
await CryptoUtil.decryptFile(
|
||||
encryptedFilePath, decryptedFilePath, attributes);
|
||||
|
@ -209,14 +206,11 @@ Future<io.File> _downloadAndDecryptThumbnail(File file) async {
|
|||
"_thumbnail.decrypted";
|
||||
return Dio().download(file.getThumbnailUrl(), temporaryPath).then((_) async {
|
||||
final encryptedFile = io.File(temporaryPath);
|
||||
final thumbnailDecryptionKey = await CryptoUtil.decrypt(
|
||||
Sodium.base642bin(file.thumbnailDecryptionParams.encryptedKey),
|
||||
Configuration.instance.getKey(),
|
||||
Sodium.base642bin(file.thumbnailDecryptionParams.keyDecryptionNonce));
|
||||
final data = await CryptoUtil.decrypt(
|
||||
final thumbnailDecryptionKey = await decryptFileKey(file);
|
||||
final data = CryptoUtil.decryptStream(
|
||||
encryptedFile.readAsBytesSync(),
|
||||
thumbnailDecryptionKey,
|
||||
Sodium.base642bin(file.thumbnailDecryptionParams.nonce),
|
||||
Sodium.base642bin(file.thumbnailDecryptionHeader),
|
||||
);
|
||||
encryptedFile.deleteSync();
|
||||
return ThumbnailCacheManager().putFile(
|
||||
|
@ -227,3 +221,10 @@ Future<io.File> _downloadAndDecryptThumbnail(File file) async {
|
|||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<Uint8List> decryptFileKey(File file) {
|
||||
return CryptoUtil.decrypt(
|
||||
Sodium.base642bin(file.encryptedKey),
|
||||
Configuration.instance.getKey(),
|
||||
Sodium.base642bin(file.keyDecryptionNonce));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue