SoFunction
Updated on 2025-03-01

C# and Java TCP channel encryption communication example

1. Background description

The company's charging system needs to be connected with the bank in real-time collection, and the business agreement uses the standards of our charging system. However, banks require the use of bank encryption rules based on business agreements.

  • useMD5Calculate the message digest to ensure data integrity
  • useRSA256Sign the digest to ensure the legality of the message
  • useAESPerform symmetric encryption to ensure the privacy of messages

After we evaluated, we added a set of encryption solutions to the business packets. The encryption method is general. What problems can this be done? No problem.

2. Test certificate

The test certificate sent by the bank is here

I later found out that this should be calledjavaThe format of the certificate is verified to be correct and can be signed and verified normally.

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDllhc9gw7aIuv8
URnf8PtPRJZww26OeSsTa1GHtuqHdjCaosBXKWaC2/SxV3lsURizFVY+HhvH6zgq
NCWhSbnwd5ucq8ZiBkb29kIbb9oVKftxpsMTfZdAgXReUPg1cE5zxLvpmSM8ggw9
2fOq/CgYgbingzAScYR5MmMgH5PwIEVh7MiloS5fMx9HWDuKAZgdXjaZHB5UL8uu
vb83iytKJIEmS346X41jCM8UQwL4hRaPvtouGSIz+oiDpotPfJQtJVzP1P/bvlQs
RJHSn1a5aDo+ygH231+PKdfKzhwxDDMeI3Yy2zxqJKtHpVc033O2yfvn5TlQ79P0
j/hswY0fAgMBAAECggEBAKZKkWjHfcF4W+91GsW+uXiP2Fuy4mgl0ZKOQA6J6dPW
Qpwu2BwJ66tLADBXiKZxEu/bu4zgqASlFhhTjxIE4b4QFFFlhhrIKyyD8BwJZy+/
KdYHEPMUG7LoUU5jXXTvdJOb4vPvLLuOAqnmLP0jCTO++e2zMuWY/Xf/jBbfaHsa
tSM3PHYN/zlTMDyFqfDc6ig+iKejW0dnNBQZpFytijpYgW3QS6XKknDRoQ0V1vpj
oCCUMlfe8tottGoBt1Q8qrNKxFb9dyXXkGx/QgDfv8A+kWv1WuwYQGose9Gu0L28
TWGOfHS399oJffJdwa/o2no+KCaKjjL5dCIjzLDm8QECgYEA/t4JgS32JS8cxyEK
Hh0tGOZhvsh/f2IOi1+pAtBKCQan34n/NCBUeyn8Ep/K95A+bPMIltaoUZYkBTGF
bVsqdkcyG19qsV5B2ldyfvBoSpwsS7oLcV78EUPLBClCpYfmbq/MEdYTysJsjKRc
ROR0p30Cu/VEP72WTyY4zMy6yp8CgYEA5ptKmDAud48hlI7gNWkKIVEH16cg+0fS
a1JgrBUZHOoVTuK8xMUxsGyYeYYolXd7I5Q4vdZwTzjGkAzCMtHzhMUSbzt6i04o
rDkfB3HEXgoIiGvChh+CjYOhc6aqKd3vFOwVyqZ0s5slc7EF4qWy9ZWD3hwWGfEE
XkO1Zc/MrYECgYANq2UBG7D2/5bgi0IaqV/w1PJrJB/Kejzjdsb+0qMV5th8Ic+h
QRam4HKXoSBmtMLUXxiX1n2CmrXl3WkVm20kmN70HuL/Dloj1sraShSd49BwY1MX
yotkdale2MOtUyOlziH41u2K03C0/l/AhixHi2npINd/P7DfH+KuAVEHawKBgA2I
c3o26aMujSPwtour3GJUJQes0Syt7FVMAkxW+KBPxGxatgU+JUpbNR98lgkfd+SA
oEvTt8eOZ2iwtvzQgV/7SLeqX+io744b1AxVytZR9Go9GK9SThEL9n+Y+kd2tL8f
k6/O0O5xXmNJsjS40KXE3nY8Y7emA0Gc65pL9ZEBAoGBANPd8FP04tTtyqiunE8G
JrOIQGtCUoEnp4gJV5VVGus19qVf6rVMr1YEMlojxgujcaQJtE878Zep6ur2WeZu
VEQOqqXRLwKBTaWYA0iabhUDd/nAh5cCjBfcYrfdnQonNrBJi5AccbfUl6FEhkoF
XQUoc1mnauKcCB1ACvtBRNGI
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5ZYXPYMO2iLr/FEZ3/D7
T0SWcMNujnkrE2tRh7bqh3YwmqLAVylmgtv0sVd5bFEYsxVWPh4bx+s4KjQloUm5
8HebnKvGYgZG9vZCG2/aFSn7cabDE32XQIF0XlD4NXBOc8S76ZkjPIIMPdnzqvwo
GIG4p4MwEnGEeTJjIB+T8CBFYezIpaEuXzMfR1g7igGYHV42mRweVC/Lrr2/N4sr
SiSBJkt+Ol+NYwjPFEMC+IUWj77aLhkiM/qIg6aLT3yULSVcz9T/275ULESR0p9W
uWg6PsoB9t9fjynXys4cMQwzHiN2Mts8aiSrR6VXNN9ztsn75+U5UO/T9I/4bMGN
HwIDAQAB
-----END PUBLIC KEY-----


C#The version certificate is here, this is the correct test certificate conversion laterC#Version, with the abovejavaVersion correspondence

Private key

<RSAKeyValue><Modulus>5ZYXPYMO2iLr/FEZ3/D7T0SWcMNujnkrE2tRh7bqh3YwmqLAVylmgtv0sVd5bFEYsxVWPh4bx+s4KjQloUm58HebnKvGYgZG9vZCG2/aFSn7cabDE32XQIF0XlD4NXBOc8S76ZkjPIIMPdnzqvwoGIG4p4MwEnGEeTJjIB+T8CBFYezIpaEuXzMfR1g7igGYHV42mRweVC/Lrr2/N4srSiSBJkt+Ol+NYwjPFEMC+IUWj77aLhkiM/qIg6aLT3yULSVcz9T/275ULESR0p9WuWg6PsoB9t9fjynXys4cMQwzHiN2Mts8aiSrR6VXNN9ztsn75+U5UO/T9I/4bMGNHw==</Modulus><Exponent>AQAB</Exponent><P>/t4JgS32JS8cxyEKHh0tGOZhvsh/f2IOi1+pAtBKCQan34n/NCBUeyn8Ep/K95A+bPMIltaoUZYkBTGFbVsqdkcyG19qsV5B2ldyfvBoSpwsS7oLcV78EUPLBClCpYfmbq/MEdYTysJsjKRcROR0p30Cu/VEP72WTyY4zMy6yp8=</P><Q>5ptKmDAud48hlI7gNWkKIVEH16cg+0fSa1JgrBUZHOoVTuK8xMUxsGyYeYYolXd7I5Q4vdZwTzjGkAzCMtHzhMUSbzt6i04orDkfB3HEXgoIiGvChh+CjYOhc6aqKd3vFOwVyqZ0s5slc7EF4qWy9ZWD3hwWGfEEXkO1Zc/MrYE=</Q><DP>DatlARuw9v+W4ItCGqlf8NTyayQfyno843bG/tKjFebYfCHPoUEWpuByl6EgZrTC1F8Yl9Z9gpq15d1pFZttJJje9B7i/w5aI9bK2koUnePQcGNTF8qLZHWpXtjDrVMjpc4h+NbtitNwtP5fwIYsR4tp6SDXfz+w3x/irgFRB2s=</DP><DQ>DYhzejbpoy6NI/C2i6vcYlQlB6zRLK3sVUwCTFb4oE/EbFq2BT4lSls1H3yWCR935ICgS9O3x45naLC2/NCBX/tIt6pf6KjvjhvUDFXK1lH0aj0Yr1JOEQv2f5j6R3a0vx+Tr87Q7nFeY0myNLjQpcTedjxjt6YDQZzrmkv1kQE=</DQ><InverseQ>093wU/Ti1O3KqK6cTwYms4hAa0JSgSeniAlXlVUa6zX2pV/qtUyvVgQyWiPGC6NxpAm0Tzvxl6nq6vZZ5m5URA6qpdEvAoFNpZgDSJpuFQN3+cCHlwKMF9xit92dCic2sEmLkBxxt9SXoUSGSgVdBShzWadq4pwIHUAK+0FE0Yg=</InverseQ><D>pkqRaMd9wXhb73Uaxb65eI/YW7LiaCXRko5ADonp09ZCnC7YHAnrq0sAMFeIpnES79u7jOCoBKUWGFOPEgThvhAUUWWGGsgrLIPwHAlnL78p1gcQ8xQbsuhRTmNddO90k5vi8+8su44CqeYs/SMJM7757bMy5Zj9d/+MFt9oexq1Izc8dg3/OVMwPIWp8NzqKD6Ip6NbR2c0FBmkXK2KOliBbdBLpcqScNGhDRXW+mOgIJQyV97y2i20agG3VDyqs0rEVv13JdeQbH9CAN+/wD6Ra/Va7BhAaix70a7QvbxNYY58dLf32gl98l3Br+jaej4oJoqOMvl0IiPMsObxAQ==</D></RSAKeyValue>
Public Key

<RSAKeyValue><Modulus>5ZYXPYMO2iLr/FEZ3/D7T0SWcMNujnkrE2tRh7bqh3YwmqLAVylmgtv0sVd5bFEYsxVWPh4bx+s4KjQloUm58HebnKvGYgZG9vZCG2/aFSn7cabDE32XQIF0XlD4NXBOc8S76ZkjPIIMPdnzqvwoGIG4p4MwEnGEeTJjIB+T8CBFYezIpaEuXzMfR1g7igGYHV42mRweVC/Lrr2/N4srSiSBJkt+Ol+NYwjPFEMC+IUWj77aLhkiM/qIg6aLT3yULSVcz9T/275ULESR0p9WuWg6PsoB9t9fjynXys4cMQwzHiN2Mts8aiSrR6VXNN9ztsn75+U5UO/T9I/4bMGNHw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

3. Copy and paste encryption algorithm

BaiduC#RSAThe signature is quite similar, and it is concise and clear. The signature and verification method will be released soon.

/// &lt;summary&gt;
/// RSA signature/// &lt;/summary&gt;
/// <param name="privateKey">Private Key</param>/// <param name="data">Content to be signed</param>/// &lt;returns&gt;&lt;/returns&gt;
public static string RSASignCSharp(string data, string privateKey, string hashAlgorithm = "SHA256", string encoding = "UTF-8")
{
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    (privateKey); //Load the private key    var dataBytes = (encoding).GetBytes(data);
    var HashbyteSignature = (dataBytes, hashAlgorithm);
    return Convert.ToBase64String(HashbyteSignature);
}

/// &lt;summary&gt; 
/// Verify the signature/// &lt;/summary&gt;
/// &lt;param name="data"&gt;&lt;/param&gt;
/// &lt;param name="signature"&gt;&lt;/param&gt;
/// &lt;param name="encoding"&gt;&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
public static bool VerifyCSharp(string data, string publicKey, string signature, string hashAlgorithm = "SHA256", string encoding = "UTF-8")
{
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    //Import the public key and prepare to verify the signature    (publicKey);
    //Return data verification results    byte[] Data = (encoding).GetBytes(data);
    byte[] rgbSignature = Convert.FromBase64String(signature);
    return (Data, hashAlgorithm, rgbSignature);
}

Wang Po sells melons and boasts about himself.

Let’s sign and verify it yourself, but it’s not. Why is that not? The simpler the more you feel, the less you have nowhere to start debugging. The algorithms are all encapsulated, which may only be a problem with parameters.

4. Certificate format conversion

The main reason isjavaandC#The public and private key storage formats used are inconsistent, resulting in the inability to directly use the bank providedjavaversion certificate, need to be converted intoC#A identifiable certificate. Here is the conversion method

/// &lt;summary&gt;
/// RSA public key format conversion, java->.net/// &lt;/summary&gt;
/// <param name="publicKey">java generated public key</param>/// &lt;returns&gt;&lt;/returns&gt;
public static string RSAPublicKeyJava2DotNet(string publicKey)
{
    RsaKeyParameters publicKeyParam = (RsaKeyParameters)(Convert.FromBase64String(publicKey));
    return ("&lt;RSAKeyValue&gt;&lt;Modulus&gt;{0}&lt;/Modulus&gt;&lt;Exponent&gt;{1}&lt;/Exponent&gt;&lt;/RSAKeyValue&gt;",
        Convert.ToBase64String(()),
        Convert.ToBase64String(()));

}
/// &lt;summary&gt;
/// RSA private key format conversion, java->.net/// &lt;/summary&gt;
/// <param name="privateKey">java generated private key</param>/// &lt;returns&gt;&lt;/returns&gt;
public static string RSAPrivateKeyJava2DotNet(string privateKey)
{
    RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)(Convert.FromBase64String(privateKey));

    return ("&lt;RSAKeyValue&gt;&lt;Modulus&gt;{0}&lt;/Modulus&gt;&lt;Exponent&gt;{1}&lt;/Exponent&gt;&lt;P&gt;{2}&lt;/P&gt;&lt;Q&gt;{3}&lt;/Q&gt;&lt;DP&gt;{4}&lt;/DP&gt;&lt;DQ&gt;{5}&lt;/DQ&gt;&lt;InverseQ&gt;{6}&lt;/InverseQ&gt;&lt;D&gt;{7}&lt;/D&gt;&lt;/RSAKeyValue&gt;",
        Convert.ToBase64String(()),
        Convert.ToBase64String(()),
        Convert.ToBase64String(()),
        Convert.ToBase64String(()),
        Convert.ToBase64String(()),
        Convert.ToBase64String(()),
        Convert.ToBase64String(()),
        Convert.ToBase64String(()));
}

As a result, the certificate conversion is not the same, and the exception is thrown directly. Then I repeated the code logic and always felt that the conversion method was wrong, and I was all kinds of Baidu.

He was searching for him thousands of times in the crowd. Looking back suddenly, the man was there, in the dim lights.

This is probably the entanglement of this incredible issue. Can't the certificate be wrong, right?

For the purpose of verification, we found the normal certificate used online, and converted it normally, and signed and signed verification is normal. Not sure, I've found it againjavaconversion method.Below isjavaCode, conversionjavaThe certificate isC#Format:

package ;


import .Base64;

import ;
import ;
import ;
import ;
import .PKCS8EncodedKeySpec;
import .X509EncodedKeySpec;

public class CerJava2CSharp {
    public static void main(String[] args)
    {
        String tes="Java version private key certificate";
        byte[] temp=b64decode(tes);
        String ver=getRSAPrivateKeyAsNetFormat(temp);//Convert private key
        String tes1="Java version public key certificate";
        byte[] temp1=b64decode(tes1);
        String ver1=getRSAPublicKeyAsNetFormat(temp1);//Convert public key        String temp2= ver1;

    }
    
    public static String getRSAPrivateKeyAsNetFormat(byte[] encodedPrivkey) {
        try {
            StringBuffer buff = new StringBuffer(1024);

            PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(
                    encodedPrivkey);
            KeyFactory keyFactory = ("RSA");
            RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) keyFactory
                    .generatePrivate(pvkKeySpec);

            ("&lt;RSAKeyValue&gt;");
            ("&lt;Modulus&gt;"
                    + b64encode(removeMSZero(().toByteArray()))
                    + "&lt;/Modulus&gt;");

            ("&lt;Exponent&gt;"
                    + b64encode(removeMSZero(()
                    .toByteArray())) + "&lt;/Exponent&gt;");

            ("&lt;P&gt;"
                    + b64encode(removeMSZero(().toByteArray()))
                    + "&lt;/P&gt;");

            ("&lt;Q&gt;"
                    + b64encode(removeMSZero(().toByteArray()))
                    + "&lt;/Q&gt;");

            ("&lt;DP&gt;"
                    + b64encode(removeMSZero(()
                    .toByteArray())) + "&lt;/DP&gt;");

            ("&lt;DQ&gt;"
                    + b64encode(removeMSZero(()
                    .toByteArray())) + "&lt;/DQ&gt;");

            ("&lt;InverseQ&gt;"
                    + b64encode(removeMSZero(()
                    .toByteArray())) + "&lt;/InverseQ&gt;");

            ("&lt;D&gt;"
                    + b64encode(removeMSZero(()
                    .toByteArray())) + "&lt;/D&gt;");
            ("&lt;/RSAKeyValue&gt;");

            return ().replaceAll("[ \t\n\r]", "");
        } catch (Exception e) {
            (e);
            return null;
        }
    }

    public static String getRSAPublicKeyAsNetFormat(byte[] encodedPrivkey) {
        try {
            StringBuffer buff = new StringBuffer(1024);

            PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(encodedPrivkey);
            KeyFactory keyFactory = ("RSA");
            RSAPublicKey pukKey=(RSAPublicKey) (new X509EncodedKeySpec(encodedPrivkey));
            // RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) (pvkKeySpec);

            //PublicKey publicKey =("RSA").generatePublic(pvkKeySpec);
            ("&lt;RSAKeyValue&gt;");
            ("&lt;Modulus&gt;"
                    + b64encode(removeMSZero(().toByteArray()))
                    + "&lt;/Modulus&gt;");
            ("&lt;Exponent&gt;"
                    + b64encode(removeMSZero(()
                    .toByteArray())) + "&lt;/Exponent&gt;");
            ("&lt;/RSAKeyValue&gt;");
            return ().replaceAll("[ \t\n\r]", "");
        } catch (Exception e) {
            (e);
            return null;
        }
    }

    public static String encodePublicKeyToXml(PublicKey key) {
        if (!(key)) {
            return null;
        }
        RSAPublicKey pubKey = (RSAPublicKey) key;
        StringBuilder sb = new StringBuilder();

        ("&lt;RSAKeyValue&gt;");
        ("&lt;Modulus&gt;")
                .append((().toByteArray()))
                .append("&lt;/Modulus&gt;");
        ("&lt;Exponent&gt;")
                .append((()
                        .toByteArray())).append("&lt;/Exponent&gt;");
        ("&lt;/RSAKeyValue&gt;");
        return ();
    }

    public static byte[] removeMSZero(byte[] data) {
        byte[] data1;
        int len = ;
        if (data[0] == 0) {
            data1 = new byte[ - 1];
            (data, 1, data1, 0, len - 1);
        } else
            data1 = data;

        return data1;
    }

    public static String b64encode(byte[] data) {

        String b64str = new String((data));
        return b64str;
    }

    public static byte[] b64decode(String data) {
        byte[] decodeData = (data);
        return decodeData;
    }
}

Verified, still not able to convert, OK, it's true, there is a problem with the certificate. As for the reasons for the certificate problem, I am not sure. After changing the certificate, convert, sign and verify everything is OK.

5. PS1 RSA certificate format

We usually see more certificate pairs,pfxThe certificate contains public key information and private key information.cerThe certificate only contains public key information. PFX certificates can be exported as pfx certificates or ascerCertificate. When exporting a pfx certificate, it will prompt whether to export the private key. The private key is the pfx certificate. If it fails to export, it is true.cerCertificate. When importing, exporting and loading a pfx certificate, you need to provide a certificate password.

  • Common formats for private key certificates:pfx p12 pem key
  • Common formats of public key certificates:pem crt/cer key

Here's the article aboutC#andjava TCPThis is all about the article on channel encryption communication instances, more relatedC#andjava TCPFor channel encrypted communication content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!

6. Reference blog posts

The difference between certificate formats and format conversion in OpenSSL

RSA key—The difference and connection between JAVA and C#