- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我一直在做一个项目,我们必须在 android sd 卡中安全地保存一个 pdf。我们希望它在 .net 中加密,因为它必须通过 API 传输。我已经在 .NET 中实现,但无法在 android 中解密。
加密文件的代码
public static void EncryptFile(string inputFile, string outputFile)
{
try
{
string password = @"myKey123"; // Your Key Here
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
string cryptFile = outputFile;
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged RMCrypto = new RijndaelManaged();
RMCrypto.Mode = CipherMode.CBC; //remember this parameter
RMCrypto.Padding = PaddingMode.PKCS7; //remember this parameter
RMCrypto.KeySize = 0x80;
RMCrypto.BlockSize = 0x80;
CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
{
cs.WriteByte((byte)data);
}
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
catch
{
Console.WriteLine("Encryption failed!", "Error");
}
}
解密文件的代码
public static void DecryptFile(string inputFile, string outputFile)
{
{
string password = @"myKey123"; // Your Key Here
UnicodeEncoding UE = new UnicodeEncoding();
byte[] key = UE.GetBytes(password);
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
RijndaelManaged RMCrypto = new RijndaelManaged();
RMCrypto.Mode = CipherMode.CBC; //remember this parameter
RMCrypto.Padding = PaddingMode.PKCS7; //remember this parameter
RMCrypto.KeySize = 0x80;
RMCrypto.BlockSize = 0x80;
CryptoStream cs = new CryptoStream(fsCrypt,
RMCrypto.CreateDecryptor(key, key),
CryptoStreamMode.Read);
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
int data;
while ((data = cs.ReadByte()) != -1)
fsOut.WriteByte((byte)data);
fsOut.Close();
cs.Close();
fsCrypt.Close();
}
}
我在 Android 中尝试使用以下代码
public static byte[] decodeFile(String key, byte[] fileData) throws Exception
{
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //this parameters should not be changed
byte[] keyBytes = new byte[16];
byte[] b = key.getBytes("UTF-16");
System.out.println("RAM"+b);
int len = b.length;
if (len > keyBytes.length)
len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(fileData);
return decrypted;
}
运行这段代码时出现错误:
error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
最佳答案
所以我发现您的代码和您使用的架构存在问题。当您选择在不同语言程序和不同环境(Android(“unix”)和 Windows)中加密文件时,您需要记住小端和大端的概念。 - the wikipedia Endianness。
Aperently 在 Java 中,它总是使用 BIG endian 的威胁,因此最高有效字节 (MSB) 与使用最低有效字节 (LSB) 的 C# 不同,此步骤导致难以追踪的问题。
我基于您的代码创建了一个代码,但使用的是 Java 而不是 android,并且无法使代码正常工作,因为我总是收到相同的错误消息 BadPaddingException: Given final block not properly padded
。错误消息并没有说明 key
文件的真正问题。
当您使用 Java 阅读时,它与 .NET 不同,因为当您将 key 转换为字节时,Java 体系结构会威胁到 MSB,而您的真实 key 使用的是 LSB。
所以真正的答案是这个 你需要将你的 key 转换为字节数组,告诉你使用最低有效字节,这样你在 .NET 和 Java 中总是有相同的字节数组
是这样的:
//the bKey it's the array of bytes and the key it's the String your are using.
byte[] bKey = key.getBytes("UTF-16LE");
我发现了 LE 的问题,因为我从 .NET 和 Java 读取了字节数组,它们不同,所以这让我开始发现这个问题
祝你的系统好运!
Ps.:我在解码时遇到了问题,因为解码和解码字节数组时遇到了问题。我找到了一条路径,您应该使用 Apache Commons Base64 来解码 Java 中的字符串。
引用资料
-Big/Little endian - Difference between Big Endian and little Endian Byte order
-填充错误-BadPaddingException: Given final block not properly padded
-提示问题出在关键 - Given final block not properly padded
-解码Base64 - Decoding a Base64 string in Java
我用来测试的代码。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class HelloWorld {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Path p = Paths
.get("C:\\Users\\casilva\\workspace\\StackOverflow\\src\\tst.enc");
byte[] a = Files.readAllBytes(p);
byte[] result = decodeFile("myKey123", a);
System.out.println("Result=" + new String(result, "UTF-8"));
}
public static byte[] decodeFile(String key, byte[] fileData)
throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] bKey = key.getBytes("UTF-16LE");
SecretKeySpec keySpec = new SecretKeySpec(bKey, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(bKey);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(fileData);
return decrypted;
}
}
关于c# - 如何在 .net 中加密文件并在 android 中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32331503/
我是一名优秀的程序员,十分优秀!