[英]Error while decrypting file in java which is encrypted in.Net using Rijndael
I am given a Rijndael .Net encrypted file and .Net RSA XML Key and asked to decrypt it in Java. 我得到了Rijndael .Net加密文件和.Net RSA XML密钥,并要求用Java对其解密。
The key provided to me is 256 bit. 提供给我的密钥是256位。
I have parsed the RSA XML file and generated the public Key in Java. 我已经解析了RSA XML文件并用Java生成了公共密钥。 I tried to decrypt using the generated key, however I am getting the exception
Illegal Key Size
, I think I am doing something wrong in my Java code. 我尝试使用生成的密钥解密,但是我收到异常的
Illegal Key Size
异常,我认为我的Java代码做错了什么。
Can any one please help to check if anything is wrong with my code? 任何人都可以帮助检查我的代码是否有问题吗?
.Net encryption code: .Net加密代码:
public static void EncryptFile(string fileIn, string fileOut,
string publicKeyName, string publicKeyFile)
{
try
{
// Read the public key from key file
StreamReader sr = new StreamReader(publicKeyFile);
string strKeyText = sr.ReadToEnd();
sr.Close();
//Initialize Key container and Crypto service provider
RSACryptoServiceProvider rsa;
CspParameters cspp = new CspParameters();
cspp.KeyContainerName = publicKeyName;
rsa = new RSACryptoServiceProvider(cspp);
rsa.FromXmlString(strKeyText);
rsa.PersistKeyInCsp = true;
// Create instance of Rijndael for
// symetric encryption of the data.
RijndaelManaged alg = new RijndaelManaged();
// Key size is set to 256 for strong encryption
alg.KeySize = 256;
alg.BlockSize = 256;
// Cipher Mode is set to CBC to process the file in chunks
alg.Mode = CipherMode.CBC;
// Set padding mode to process the last block of the file
alg.Padding = PaddingMode.ISO10126;
ICryptoTransform transform = alg.CreateEncryptor();
// Use RSACryptoServiceProvider to
// enrypt the Rijndael key.
byte[] KeyEncrypted = rsa.Encrypt(alg.Key, false);
// Create byte arrays to contain
// the length values of the key and IV.
int intKeyLength = KeyEncrypted.Length;
byte[] LenK = BitConverter.GetBytes(intKeyLength);
int intIVLength = alg.IV.Length;
byte[] LenIV = BitConverter.GetBytes(intIVLength);
using (FileStream fsOut = new FileStream(fileOut, FileMode.Create))
{
// Write the following to the FileStream
// for the encrypted file (fsOut):
// - length of the key
// - length of the IV
// - ecrypted key
// - the IV
// - the encrypted cipher content
fsOut.Write(LenK, 0, 4);
fsOut.Write(LenIV, 0, 4);
fsOut.Write(KeyEncrypted, 0, intKeyLength);
fsOut.Write(alg.IV, 0, intIVLength);
// Now write the cipher text using
// a CryptoStream for encrypting.
using (CryptoStream cs = new CryptoStream(fsOut, transform, CryptoStreamMode.Write))
{
// intBlockSizeBytes can be any arbitrary size.
int intBlockSizeBytes = alg.BlockSize / 8;
byte[] DataBytes = new byte[intBlockSizeBytes];
int intBytesRead = 0;
using (FileStream fsIn = new FileStream(fileIn, FileMode.Open))
{
// By encrypting a chunk at
// a time, you can save memory
// and accommodate large files.
int intCount;
int intOffset = 0;
do
{
// if last block size is less than encryption chunk size
// use the last block size and padding character is used
// for remaining bytes
if (intBlockSizeBytes > (fsIn.Length - fsIn.Position))
{
intBlockSizeBytes = ((int)(fsIn.Length - fsIn.Position));
DataBytes = new byte[intBlockSizeBytes];
}
// read data bytes
intCount = fsIn.Read(DataBytes, 0, intBlockSizeBytes);
intOffset += intCount;
// write it into crypto stream
cs.Write(DataBytes, 0, intCount);
intBytesRead += intBlockSizeBytes;
} while (intCount > 0);
// close input file
fsIn.Close();
}
// close crypto stream
cs.FlushFinalBlock();
cs.Close();
}
// close output file
fsOut.Close();
}
}
catch
{
throw;
}
}
Java Code that I wrote to decrypt it: 我写来解密的Java代码:
byte[] expBytes = Base64.decodeBase64(pkey.getExponentEle().trim());
byte[] modBytes = Base64.decodeBase64(pkey.getModulusEle().trim());
byte[] dBytes = Base64.decodeBase64(pkey.getdEle().trim());
BigInteger modules = new BigInteger(1, modBytes);
BigInteger exponent = new BigInteger(1, expBytes);
BigInteger d = new BigInteger(1, dBytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modules, exponent);
PublicKey pubKey = factory.generatePublic(pubSpec);
final byte[] keyData = Arrays.copyOf(pubKey.getEncoded(), 256
/ Byte.SIZE);
final byte[] ivBytes = Arrays.copyOf(keyData, cipher.getBlockSize());
AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyData, "AES"), paramSpec);
byte[] decrypted = cipher.doFinal(encrypted);
System.out.println("decrypted: " + new String(decrypted));
If I change cipher initialization to cipher.init(Cipher.DECRYPT_MODE, pubKey);
如果我将密码初始化更改为
cipher.init(Cipher.DECRYPT_MODE, pubKey);
, then I am getting the error Invalid AES key length: 162 bytes
,然后出现错误
Invalid AES key length: 162 bytes
You are using the public key wrong way. 您使用公钥的方式错误。 Do you really understad how the C# program works?
您真的了解C#程序的工作原理吗? what parameters is it using?
它使用什么参数?
You are just using the public key bits as the AES key (even I don't realy understand how do you get 162 bytes from it). 您只是将公共密钥位用作AES密钥(即使我不太了解如何从中获取162个字节)。
This is example of "hybrid encryption" - the data themselves are encrypted by a random AES key (in this you claim it's 256 bit) and the AES key (in this case the IV too) is encrypted by the RSA public key. 这是“混合加密”的示例-数据本身通过随机AES密钥(在此您声明为256位)加密,而AES密钥(在本例中为IV)也由RSA公钥加密。 In Java there are many examples how to do that .
在Java中,有很多示例如何做到这一点 。
Even to decrypt the AES key you should know parameters used to encrypt it (RSA/ECB/PKCS5Padding, RSA-AOEP, ...), though it should be inside the XML. 即使解密AES密钥,您也应该知道用于加密它的参数(RSA / ECB / PKCS5Padding,RSA-AOEP等),尽管它应该位于XML内。
Comming to the parameters - you are using PKCS5Padding
, but check the .NET code, it's different 输入参数-您正在使用
PKCS5Padding
,但是检查.NET代码,则有所不同
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.