· 4 years ago · Jun 02, 2021, 12:58 PM
1package np.com.sarbagyastha.file_encrypter
2
3import android.util.Base64
4import androidx.annotation.NonNull
5import io.flutter.embedding.engine.plugins.FlutterPlugin
6import io.flutter.plugin.common.MethodCall
7import io.flutter.plugin.common.MethodChannel
8import io.flutter.plugin.common.MethodChannel.MethodCallHandler
9import io.flutter.plugin.common.MethodChannel.Result
10import io.flutter.plugin.common.PluginRegistry.Registrar
11import kotlinx.coroutines.CoroutineScope
12import kotlinx.coroutines.Dispatchers.IO
13import kotlinx.coroutines.Dispatchers.Main
14import kotlinx.coroutines.launch
15import kotlinx.coroutines.withContext
16import java.io.FileInputStream
17import java.io.FileOutputStream
18import javax.crypto.Cipher
19import javax.crypto.CipherInputStream
20import javax.crypto.CipherOutputStream
21import javax.crypto.KeyGenerator
22import javax.crypto.spec.IvParameterSpec
23import javax.crypto.spec.SecretKeySpec
24
25class FileEncrypterPlugin : FlutterPlugin, MethodCallHandler {
26 private lateinit var channel: MethodChannel
27 private lateinit var result: Result
28 private val algorithm = "AES"
29 private val transformation = "AES/CBC/PKCS5Padding"
30
31 override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
32 channel = MethodChannel(flutterPluginBinding.binaryMessenger, "file_encrypter")
33 channel.setMethodCallHandler(this)
34 }
35
36 companion object {
37 @JvmStatic
38 fun registerWith(registrar: Registrar) {
39 val channel = MethodChannel(registrar.messenger(), "file_encrypter")
40 channel.setMethodCallHandler(FileEncrypterPlugin())
41 }
42 }
43
44 override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
45 this.result = result
46 CoroutineScope(IO).launch {
47 when (call.method) {
48 "encrypt" -> encrypt(call.argument("inFileName"), call.argument("outFileName"))
49 "decrypt" -> decrypt(call.argument("key"), call.argument("inFileName"), call.argument("outFileName"))
50 else -> withContext(Main) {
51 result.notImplemented()
52 }
53 }
54 }
55 }
56
57 override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
58 channel.setMethodCallHandler(null)
59 }
60
61 private suspend fun successResult(data: String?) {
62 withContext(Main) {
63 result.success(data)
64 }
65 }
66
67 private suspend fun errorResult(message: String?) {
68 withContext(Main) {
69 result.error("", message, message)
70 }
71 }
72
73 private suspend fun encrypt(inFileName: String?, outFileName: String?) {
74 val cipher = Cipher.getInstance(transformation)
75 val secretKey = KeyGenerator.getInstance("AES").generateKey()
76
77 try {
78 FileOutputStream(outFileName!!).use { fileOut ->
79 cipher.init(Cipher.ENCRYPT_MODE, secretKey)
80 CipherOutputStream(fileOut, cipher).use { cipherOut ->
81 fileOut.write(cipher.iv)
82 val buffer = ByteArray(8192)
83 FileInputStream(inFileName!!).use { fileIn ->
84 var byteCount = fileIn.read(buffer)
85 while (byteCount != -1) {
86 cipherOut.write(buffer, 0, byteCount)
87 byteCount = fileIn.read(buffer)
88 }
89 }
90 }
91 }
92 } catch (e: Exception) {
93 e.printStackTrace()
94 errorResult(e.message)
95 return
96 }
97
98 val keyString = Base64.encodeToString(secretKey.encoded, Base64.DEFAULT)
99 successResult(keyString)
100 }
101
102 private suspend fun decrypt(key: String?, inFileName: String?, outFileName: String?) {
103 val cipher = Cipher.getInstance(transformation)
104 val encodedKey = Base64.decode(key, Base64.DEFAULT)
105 val secretKey = SecretKeySpec(encodedKey, 0, encodedKey.size, algorithm)
106
107 try {
108 FileInputStream(inFileName!!).use { fileIn ->
109 val fileIv = ByteArray(16)
110 fileIn.read(fileIv)
111 cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(fileIv))
112 CipherInputStream(fileIn, cipher).use { cipherIn ->
113 val buffer = ByteArray(8192)
114 FileOutputStream(outFileName!!).use { fileOut ->
115 var byteCount = cipherIn.read(buffer)
116 while (byteCount != -1) {
117 fileOut.write(buffer, 0, byteCount)
118 byteCount = cipherIn.read(buffer)
119 }
120 }
121 }
122 }
123 } catch (e: Exception) {
124 e.printStackTrace()
125 errorResult(e.message)
126 return
127 }
128 successResult(null)
129 }
130}
131