Reputation: 5635
Want to use generated RSA public key in java, in c# function to encrypt data and decrypt it in Java decrypt function.
Generated Java public key has been replaced in Modulus tag in c#:
static string publicKey = "<RSAKeyValue><Modulus>MFwwDQ...wEAAQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
C# Encrypt function:
static string Encrypt(string text)
{
const int PROVIDER_RSA_FULL = 1;
const string CONTAINER_NAME = "Tracker";
CspParameters cspParams;
cspParams = new CspParameters(PROVIDER_RSA_FULL);
cspParams.KeyContainerName = CONTAINER_NAME;
RSACryptoServiceProvider rsa1 = new RSACryptoServiceProvider(512,cspParams);
rsa1.FromXmlString(publicKey);
byte[] textBytes = Encoding.UTF8.GetBytes(text);
byte[] encryptedOutput = rsa1.Encrypt(textBytes, RSAEncryptionPadding.Pkcs1);
string outputB64 = Convert.ToBase64String(encryptedOutput);
return outputB64;
}
Java Decrypt function:
static String Decrypt(String encodedString,PrivateKey privKey) {
try {
Cipher cipher = Cipher.getInstance(cipherInstancename);
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encodedString));
return new String(decrypted, "UTF-8");
} catch (Exception err) {
return err.fillInStackTrace().toString();
}
}
First question: Is it correct to replace Java public key in Modulus tag in c# XML string? What about the Exponent tag? I used AQAB value for it.
The Second question: Why on decrypting in Java got this error:
javax.crypto.IllegalBlockSizeException: Data must not be longer than 64 bytes
After some research I found, it's a general error what cause can make this type of error?
Upvotes: 4
Views: 845
Reputation: 49121
First question: Is it correct to replace Java public key in Modulus tag in c# XML string?
No! The key is not identical to the modulus, but contains the modulus and the exponent. Therefore, in your case both must be determined from the key generated in Java.
A public key can be given in different formats. For example, a public key generated in native Java will usually have the X.509/SPKI format and will probably be a byte[]
, i.e. in DER encoding. If the byte[]
is Base64 encoded (this corresponds to the posted MFwwDQ...wEAAQ==
) and the header -----BEGIN PUBLIC KEY----- and the footer -----END PUBLIC KEY----- are added (usually in the Base64 encoded body there is also a line break after every 64 characters), the key will be in PEM encoding.
The easiest way to determine the modulus and exponent manually is to load the PEM key in an ASN.1 parser, e.g. here, or to convert it directly into the XML format on a suitable website, e.g. here.
What about the Exponent tag? I used AQAB value for it.
This question has already been answered implicitly with what was said before. But one remark: For the exponent the value 65537 (hex encoded 0x010001 and Base64 encoded AQAB) is often chosen. But this is not always the case. So if the exponent of an existing key is blindly replaced by this value, there is a high probability that it will work, but you cannot rely on it, see e.g. here and here.
The Second question: Why on decrypting in Java got this error: javax.crypto.IllegalBlockSizeException: Data must not be longer than 64 bytes?
This has already been answered in Michael Fehr's comment, among other important points (such as security, performance and hybrid encryption): The key length limits the length of the plaintext, with a 512 bit key a maximum of 64 bytes can be encrypted.
Additionally, it should be noted that not only the length of the key but also the padding used limits the length of the plaintext, e.g. PKCS#1 v1.5 Padding requires 11 bytes, so the maximum plaintext length for a 512 bit key is 64 - 11 = 53 bytes, here. In the case of OAEP the digest used determines how many bytes the padding requires, see e.g. here. If no padding is used (tetxbook RSA), the maximum length of the plaintext corresponds to the key length. In practice, however, padding must always be used for security reasons.
Starting with .NET Core 3.0 the import of an X.509/SPKI key (in DER encoding) and similar formats is directly supported, see e.g. here and especially RSA.ImportSubjectPublicKey
. In earlier .NET Core versions and in .NET Framework these functions are not available, but BouncyCastle can be used instead.
Upvotes: 4