RSA, JAVA private key encryption, C # Public Key decryption,
It took three days to climb this thing in the pit and record it for reference by park friends. C # A programmer. The project needs to interact with Java. The other party throws the segment ciphertext and sends a CER certificate to me. Then I want to decrypt the ciphertext. RSA asymmetric encryption. The other party uses the private key for encryption. I use the public key for decryption. One note about the certificate: There are two types of certificates:. pfx and. cer. The. pfx certificate contains both the public key and the private key, and the. cer certificate contains only the public key.
C # by default, RSA only supports public key encryption and Private Key decryption. The current requirements are the opposite. Therefore, it is not feasible to directly use the C # built-in Encryption Class. In addition, C # and Java RSA encryption are not interconnected. The third-party library BouncyCastle is used to meet the current requirements. For more information, see the code. Here we post the main code snippet:
1. Read the public key from the cer certificate. The Public Key format in C # is an xml string, which is different from the Public Key format in java.
/// <Summary> /// obtain the public key from the certificate /// </summary> /// <param name = "cerPath"> </param> // <returns> </returns> private string GetPublicKeyFromCer (string cerPath) {X509Certificate2 pubcrt = new X509Certificate2 (cerPath); RSACryptoServiceProvider pubkey = (RSACryptoServiceProvider) pubcrt. publicKey. key; return pubkey. toXmlString (false );}
2. Convert the C # Public Key to the Java Public Key
/// <Summary> /// convert the C # public key to a Java Public Key // </summary> /// <param name = "publicKey"> </param> /// <returns> </returns> public static RsaKeyParameters RSAPublicKeyDotNet2Java (string publicKey) {XmlDocument doc = new XmlDocument (); doc. loadXml (publicKey); BigInteger m = new BigInteger (1, Convert. fromBase64String (doc. documentElement. getElementsByTagName ("Modulus") [0]. innerText); BigInteger p = new BigInteger (1, Convert. fromBase64String (doc. documentElement. getElementsByTagName ("Exponent") [0]. innerText); RsaKeyParameters pub = new RsaKeyParameters (false, m, p); return pub ;}
3. Public Key decryption. Because the ciphertext given by the other party is base64-encoded, it must be decoded first. In addition, the encryption fill mode should be set to the same as that in java. Here I set "RSA/ECB/PKCS1Padding ".
/// <Summary> // Public Key decryption /// </summary> /// <param name = "xmlPublicKey"> C # format Public Key </param> /// <param name = "strEncryptString"> ciphertext </param> // <returns> </returns> public static string RSADecryptByPublicKey (string xmlPublicKey, string strEncryptString) {// obtain the Public Key RsaKeyParameters keyParams = RSAPublicKeyDotNet2Java (xmlPublicKey); // The parameter is consistent with the encryption and decryption parameters in Java. IBufferedCipher c = CipherUtilities. getCipher ("RSA/ECB/PKCS1Padding"); // The first parameter is true-encrypted, false-decrypted, and the second parameter is the key c. init (false, keyParams); // base64 decodes the ciphertext. byte [] dataFromEncrypt = Convert. fromBase64String (strEncryptString); // decrypt byte [] outBytes = c. doFinal (dataFromEncrypt); // plaintext string clearText = Encoding. default. getString (outBytes); return clearText ;}
The above Code depends on BouncyCastle. Remember to add reference before using it. Why have you stayed in the trap for three days? The reason is that the ciphertext format returned to me by Java is incorrect, So that I cannot solve it. At that time, I thought that Java and C # could not achieve intercommunication and decryption! Finally, I found this problem myself and lost one of them.
This is why I added two days of work .... when you encounter an Unknown block type error during decryption, it is very likely that the encoding is incorrect, that is, the ciphertext format is incorrect.