Android:随机解密的文件被破坏
我有一个应用程序,它可以对文件进行加密以用于存储,并对其进行解密以上载到我们的服务器。在大多数情况下,它工作正常,我们收到的解密文件都是好文件 但是,在半定期的基础上(每隔几天几百个文件中就有一个或两个文件),解密的文件会损坏。可能原始文件也已损坏,且问题不在加密/解密过程中,但这已发生在不同的用户身上,他们可能会首先确保文件未损坏,但我不知道如何验证这一点,因为我与我们的用户没有直接联系 我想确保我的代码不是问题的根源,或者我可以做些什么来检查应用程序中的文件是否安全加密/解密,以确保我们收到的所有文件都是好的 奇怪的是,我有一个ExceptionManager类,它向我发送任何发生的异常,当处理和上传这些损坏的文件时,我没有收到任何异常,所以我无法知道出了什么问题 这是我的加密代码:Android:随机解密的文件被破坏,android,xamarin,encryption,Android,Xamarin,Encryption,我有一个应用程序,它可以对文件进行加密以用于存储,并对其进行解密以上载到我们的服务器。在大多数情况下,它工作正常,我们收到的解密文件都是好文件 但是,在半定期的基础上(每隔几天几百个文件中就有一个或两个文件),解密的文件会损坏。可能原始文件也已损坏,且问题不在加密/解密过程中,但这已发生在不同的用户身上,他们可能会首先确保文件未损坏,但我不知道如何验证这一点,因为我与我们的用户没有直接联系 我想确保我的代码不是问题的根源,或者我可以做些什么来检查应用程序中的文件是否安全加密/解密,以确保我们收到
static string aesTransform = "AES/CBC/PKCS5Padding"
public static bool EncryptFile(Context context, string fileLocation, ref string encryptedFileLocation)
{
bool success;
try
{
Log logger = new Log(context);
logger.Debug("starting encryption");
if (File.Exists(fileLocation))
{
encryptedFileLocation = (encryptedFileLocation ?? fileLocation) + ".aes";
using (FileStream fInput = File.Open(fileLocation, FileMode.Open))
using (FileStream fOutput = File.Open(encryptedFileLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
byte[] keyBytes = Encoding.UTF8.GetBytes(encryptKey);
SecretKeySpec key = new SecretKeySpec(keyBytes, 0, keyBytes.Length, "AES");
Cipher cipher = Cipher.GetInstance(aesTransform);
cipher.Init(CipherMode.EncryptMode, key, new IvParameterSpec(new byte[cipher.BlockSize]));
CipherOutputStream cos = new CipherOutputStream(fOutput, cipher);
byte[] buffer = new byte[1024];
int numBytesWritten = 0;
while ((numBytesWritten = fInput.Read(buffer, 0, buffer.Length)) > 0)
{
cos.Write(buffer, 0, numBytesWritten);
}
cos.Flush();
cos.Close();
}
logger.WriteLog(Log.LogType.Misc, fileLocation + " encrypted");
Delete(context, fileLocation);
}
success = true;
}
catch(Exception ex)
{
if (File.Exists(fileLocation) && File.Exists(encryptedFileLocation))
{
Delete(context, encryptedFileLocation);
}
if(encryptedFileLocation.EndsWith(".aes"))
{
encryptedFileLocation = encryptedFileLocation.Remove(encryptedFileLocation.ToUpper().LastIndexOf(".AES"));
}
ex.Data.Add("fileLocation", fileLocation);
ex.Data.Add("encryptedFileLocation", encryptedFileLocation);
ExceptionManager.ManageException(context, ex);
success = false;
}
return success;
}
这是我的解密代码:
static string aesTransform = "AES/CBC/PKCS5Padding"
public static bool DecryptFile(Context context, string fileLocation, ref string decryptedFileLocation)
{
bool decrypted = false;
try
{
if (File.Exists(fileLocation))
{
if(fileLocation.ToUpper().EndsWith(".AES"))
{
decryptedFileLocation = fileLocation.Remove(fileLocation.ToUpper().LastIndexOf(".AES"));
}
else
{
decryptedFileLocation = fileLocation;
}
using (FileStream fInput = File.Open(fileLocation, FileMode.Open))
using (FileStream fOutput = File.Open(decryptedFileLocation, FileMode.OpenOrCreate))
{
FileInfo info = new FileInfo(fileLocation);
byte[] keyBytes = Encoding.UTF8.GetBytes(encryptKey);
SecretKeySpec key = new SecretKeySpec(keyBytes, 0, keyBytes.Length, "AES");
Cipher cipher = Cipher.GetInstance(aesTransform);
cipher.Init(CipherMode.DecryptMode, key, new IvParameterSpec(new byte[cipher.BlockSize]));
CipherInputStream cis = new CipherInputStream(fInput, cipher);
byte[] buffer = new byte[1024];
int numBytesWritten = 0;
while ((numBytesWritten = cis.Read(buffer, 0, buffer.Length)) > 0)
{
fOutput.Write(buffer, 0, numBytesWritten);
}
cis.Close();
decrypted = true;
Log logger = new Log(context);
logger.WriteLog(Log.LogType.Misc, fileLocation + " decrypted");
}
}
}
catch (Exception ex)
{
if (File.Exists(fileLocation) && File.Exists(decryptedFileLocation))
{
Delete(context, decryptedFileLocation);
}
decryptedFileLocation = fileLocation;
ex.Data.Add("fileLocation", fileLocation);
ExceptionManager.ManageException(context, ex);
decrypted = false;
}
return decrypted;
}
encrypt和Decrypt方法的加密密钥都相同,都引用了该类前面声明的静态字符串,因此密钥匹配。Hi,欢迎使用so!我认为问题不在于加密和解密的代码。我不知道加密和解密的频率是否太快。这将导致某些文件在加密完成之前终止。如果是这种情况,建议使用async/await实现异步加密。你可以参考。首先,终于成为SO社区的一部分真是太好了!谢谢@姜师弟,你能详细解释一下频率太快导致文件提前终止是什么意思吗?为什么加密会终止?如何通过异步加密来解决这个问题呢?通读之后,我没有发现任何错误。我也没有看到任何由异步构造引起或可以由异步构造解决的问题。如何识别这些腐败事件?大多数情况下,使用
PKCS5Padding
,如果密文文件已损坏,解密将失败,出现BadPaddingException
。然而,这并不能保证。如果你偶尔收到贪污事件,但从来没有得到<代码> BADPADION异常< /代码>,那么我猜想数据在加密之前就被破坏了。考虑切换到像AES-GCM的认证加密方法,并对每个加密使用实际的随机IV/NONCE。在加密时将IV/nonce前置到密文,并在解密前将其剥离。有了GCM和16字节的MAC,损坏的密文总是会被检测出来。@JeffreyBeitsch我同意James的观点。如果async/await不能作为原因,另一个原因是文件在被加密之前已损坏。我想你应该先检查一下文件在本地存储后是否损坏。