Преглед на файлове

Make no assumptions about the encoding type of the key

Vishnu Mohandas преди 4 години
родител
ревизия
4cd93610f7
променени са 6 файла, в които са добавени 56 реда и са изтрити 45 реда
  1. 17 9
      lib/core/configuration.dart
  2. 14 11
      lib/file_upload_manager.dart
  3. 1 1
      lib/models/file.dart
  4. 1 1
      lib/photo_sync_manager.dart
  5. 1 1
      lib/ui/settings_page.dart
  6. 22 22
      lib/utils/crypto_util.dart

+ 17 - 9
lib/core/configuration.dart

@@ -1,5 +1,6 @@
 import 'dart:convert';
 import 'dart:io' as io;
+import 'dart:typed_data';
 
 import 'package:flutter_secure_storage/flutter_secure_storage.dart';
 import 'package:path_provider/path_provider.dart';
@@ -43,17 +44,20 @@ class Configuration {
   }
 
   Future<KeyAttributes> generateAndSaveKey(String passphrase) async {
-    final key = CryptoUtil.getBase64EncodedSecureRandomString(length: 32);
+    final key = CryptoUtil.getSecureRandomBytes(length: 32);
     final kekSalt = CryptoUtil.getSecureRandomBytes(length: 32);
     final kek = CryptoUtil.scrypt(utf8.encode(passphrase), kekSalt);
     final kekHashSalt = CryptoUtil.getSecureRandomBytes(length: 32);
     final kekHash = CryptoUtil.scrypt(kek, kekHashSalt);
-    final iv = CryptoUtil.getBase64EncodedSecureRandomString(length: 16);
-    final encryptedKey =
-        CryptoUtil.encryptToBase64(key, base64.encode(kek), iv);
-    final attributes = KeyAttributes(base64.encode(kekSalt),
-        base64.encode(kekHash), base64.encode(kekHashSalt), encryptedKey, iv);
-    await setKey(key);
+    final iv = CryptoUtil.getSecureRandomBytes(length: 16);
+    final encryptedKey = CryptoUtil.aesEncrypt(key, kek, iv);
+    final attributes = KeyAttributes(
+        base64.encode(kekSalt),
+        base64.encode(kekHash),
+        base64.encode(kekHashSalt),
+        base64.encode(encryptedKey),
+        base64.encode(iv));
+    await setKey(base64.encode(key));
     await setKeyAttributes(attributes);
     return attributes;
   }
@@ -149,7 +153,11 @@ class Configuration {
     _key = key;
   }
 
-  String getKey() {
+  Uint8List getKey() {
+    return base64.decode(_key);
+  }
+
+  String getBase64EncodedKey() {
     return _key;
   }
 
@@ -166,6 +174,6 @@ class Configuration {
   }
 
   bool hasConfiguredAccount() {
-    return getToken() != null && getKey() != null;
+    return getToken() != null && getBase64EncodedKey() != null;
   }
 }

+ 14 - 11
lib/file_upload_manager.dart

@@ -41,16 +41,19 @@ class FileUploadManager {
   }
 
   Future<File> encryptAndUploadFile(File file) async {
-    final key = CryptoUtil.getBase64EncodedSecureRandomString(length: 32);
-    final iv = CryptoUtil.getBase64EncodedSecureRandomString(length: 16);
+    final key = CryptoUtil.getSecureRandomBytes(length: 32);
+    final base64EncodedKey = base64.encode(key);
+    final iv = CryptoUtil.getSecureRandomBytes(length: 16);
+    final base64EncodedIV = base64.encode(iv);
     final encryptedKey =
-        CryptoUtil.encryptToBase64(key, Configuration.instance.getKey(), iv);
+        CryptoUtil.aesEncrypt(key, Configuration.instance.getKey(), iv);
+    final base64EncodedEncryptedKey = base64.encode(encryptedKey);
 
     final encryptedFileName = file.generatedID.toString() + ".aes";
     final tempDirectory = Configuration.instance.getTempDirectory();
     final encryptedFilePath = tempDirectory + encryptedFileName;
     await CryptoUtil.encryptDataToFile(
-        await getBytesFromDisk(file), encryptedFilePath, key);
+        await getBytesFromDisk(file), encryptedFilePath, base64EncodedKey);
 
     final fileUploadURL = await getUploadURL();
     String fileObjectKey =
@@ -62,21 +65,21 @@ class FileUploadManager {
         file.generatedID.toString() + "_thumbnail.aes";
     final encryptedThumbnailPath = tempDirectory + encryptedThumbnailName;
     await CryptoUtil.encryptDataToFile(
-        thumbnailData, encryptedThumbnailPath, key);
+        thumbnailData, encryptedThumbnailPath, base64EncodedKey);
 
     final thumbnailUploadURL = await getUploadURL();
     String thumbnailObjectKey =
         await putFile(thumbnailUploadURL, io.File(encryptedThumbnailPath));
 
     final metadata = jsonEncode(file.getMetadata());
-    final encryptedMetadata =
-        await CryptoUtil.encryptDataToData(utf8.encode(metadata), key);
+    final encryptedMetadata = await CryptoUtil.encryptDataToData(
+        utf8.encode(metadata), base64EncodedKey);
     final data = {
       "fileObjectKey": fileObjectKey,
       "thumbnailObjectKey": thumbnailObjectKey,
       "metadata": encryptedMetadata,
-      "encryptedKey": encryptedKey,
-      "encryptedKeyIV": iv,
+      "encryptedKey": base64EncodedEncryptedKey,
+      "encryptedKeyIV": base64EncodedIV,
     };
     return _dio
         .post(
@@ -92,8 +95,8 @@ class FileUploadManager {
       file.uploadedFileID = data["id"];
       file.updationTime = data["updationTime"];
       file.ownerID = data["ownerID"];
-      file.encryptedKey = encryptedKey;
-      file.encryptedKeyIV = iv;
+      file.encryptedKey = base64EncodedEncryptedKey;
+      file.encryptedKeyIV = base64EncodedIV;
       return file;
     });
   }

+ 1 - 1
lib/models/file.dart

@@ -140,7 +140,7 @@ class File {
       return null;
     }
     return CryptoUtil.decryptFromBase64(
-        encryptedKey, Configuration.instance.getKey(), encryptedKeyIV);
+        encryptedKey, Configuration.instance.getBase64EncodedKey(), encryptedKeyIV);
   }
 
   @override

+ 1 - 1
lib/photo_sync_manager.dart

@@ -290,7 +290,7 @@ class PhotoSyncManager {
               file.encryptedKey = json["encryptedKey"];
               file.encryptedKeyIV = json["encryptedKeyIV"];
               final key = CryptoUtil.decryptFromBase64(file.encryptedKey,
-                  Configuration.instance.getKey(), file.encryptedKeyIV);
+                  Configuration.instance.getBase64EncodedKey(), file.encryptedKeyIV);
               Map<String, dynamic> metadata = jsonDecode(utf8.decode(
                   await CryptoUtil.decryptDataToData(json["metadata"], key)));
               file.applyMetadata(metadata);

+ 1 - 1
lib/ui/settings_page.dart

@@ -208,7 +208,7 @@ class DebugWidget extends StatelessWidget {
       content: SingleChildScrollView(
         child: Column(children: [
           Text("Key", style: TextStyle(fontWeight: FontWeight.bold)),
-          Text(Configuration.instance.getKey()),
+          Text(Configuration.instance.getBase64EncodedKey()),
           Padding(padding: EdgeInsets.all(12)),
           Text("Encrypted Key", style: TextStyle(fontWeight: FontWeight.bold)),
           Text(keyAttributes.encryptedKey),

+ 22 - 22
lib/utils/crypto_util.dart

@@ -11,10 +11,6 @@ import 'package:steel_crypt/steel_crypt.dart' as steel;
 import 'package:uuid/uuid.dart';
 
 class CryptoUtil {
-  static String getBase64EncodedSecureRandomString({int length = 32}) {
-    return SecureRandom(length).base64;
-  }
-
   static Uint8List getSecureRandomBytes({int length = 32}) {
     return SecureRandom(length).bytes;
   }
@@ -28,15 +24,15 @@ class CryptoUtil {
     return base64.encode(scrypt(plainText, salt)) == base64.encode(hash);
   }
 
-  static String encryptToBase64(
-      String plainText, String base64Key, String base64IV) {
-    final encrypter = AES(Key.fromBase64(base64Key));
+  static Uint8List aesEncrypt(
+      Uint8List plainText, Uint8List key, Uint8List iv) {
+    final encrypter = AES(Key(key));
     return encrypter
         .encrypt(
-          utf8.encode(plainText),
-          iv: IV.fromBase64(base64IV),
+          plainText,
+          iv: IV(iv),
         )
-        .base64;
+        .bytes;
   }
 
   static String decryptFromBase64(
@@ -58,18 +54,20 @@ class CryptoUtil {
   }
 
   static Future<String> encryptDataToFile(
-      Uint8List source, String destinationPath, String key) async {
+      Uint8List source, String destinationPath, String base64EncodedKey) async {
     final args = Map<String, dynamic>();
-    args["key"] = key;
+    args["key"] = base64EncodedKey;
     args["source"] = source;
     args["destination"] = destinationPath;
     return Computer().compute(runEncryptDataToFile, param: args);
   }
 
-  static Future<String> encryptDataToData(Uint8List source, String key) async {
+  static Future<String> encryptDataToData(
+      Uint8List source, String base64EncodedKey) async {
     final destinationPath =
         Configuration.instance.getTempDirectory() + Uuid().v4();
-    return encryptDataToFile(source, destinationPath, key).then((value) {
+    return encryptDataToFile(source, destinationPath, base64EncodedKey)
+        .then((value) {
       final file = io.File(destinationPath);
       final data = file.readAsBytesSync();
       file.deleteSync();
@@ -77,27 +75,29 @@ class CryptoUtil {
     });
   }
 
-  static Future<void> decryptFileToFile(
-      String sourcePath, String destinationPath, String key) async {
+  static Future<void> decryptFileToFile(String sourcePath,
+      String destinationPath, String base64EncodedKey) async {
     final args = Map<String, String>();
-    args["key"] = key;
+    args["key"] = base64EncodedKey;
     args["source"] = sourcePath;
     args["destination"] = destinationPath;
     return Computer().compute(runDecryptFileToFile, param: args);
   }
 
-  static Future<Uint8List> decryptFileToData(String sourcePath, String key) {
+  static Future<Uint8List> decryptFileToData(
+      String sourcePath, String base64EncodedKey) {
     final args = Map<String, String>();
-    args["key"] = key;
+    args["key"] = base64EncodedKey;
     args["source"] = sourcePath;
     return Computer().compute(runDecryptFileToData, param: args);
   }
 
-  static Future<Uint8List> decryptDataToData(String source, String key) {
+  static Future<Uint8List> decryptDataToData(
+      Uint8List source, String base64EncodedKey) {
     final sourcePath = Configuration.instance.getTempDirectory() + Uuid().v4();
     final file = io.File(sourcePath);
-    file.writeAsBytesSync(base64.decode(source));
-    return decryptFileToData(sourcePath, key).then((value) {
+    file.writeAsBytesSync(source);
+    return decryptFileToData(sourcePath, base64EncodedKey).then((value) {
       file.deleteSync();
       return value;
     });