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.
- use
MD5
Calculate the message digest to ensure data integrity - use
RSA256
Sign the digest to ensure the legality of the message - use
AES
Perform 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 calledjava
The 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 abovejava
Version 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#RSA
The signature is quite similar, and it is concise and clear. The signature and verification method will be released soon.
/// <summary> /// RSA signature/// </summary> /// <param name="privateKey">Private Key</param>/// <param name="data">Content to be signed</param>/// <returns></returns> 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); } /// <summary> /// Verify the signature/// </summary> /// <param name="data"></param> /// <param name="signature"></param> /// <param name="encoding"></param> /// <returns></returns> 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 isjava
andC#
The public and private key storage formats used are inconsistent, resulting in the inability to directly use the bank providedjava
version certificate, need to be converted intoC#
A identifiable certificate. Here is the conversion method
/// <summary> /// RSA public key format conversion, java->.net/// </summary> /// <param name="publicKey">java generated public key</param>/// <returns></returns> public static string RSAPublicKeyJava2DotNet(string publicKey) { RsaKeyParameters publicKeyParam = (RsaKeyParameters)(Convert.FromBase64String(publicKey)); return ("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>", Convert.ToBase64String(()), Convert.ToBase64String(())); } /// <summary> /// RSA private key format conversion, java->.net/// </summary> /// <param name="privateKey">java generated private key</param>/// <returns></returns> public static string RSAPrivateKeyJava2DotNet(string privateKey) { RsaPrivateCrtKeyParameters privateKeyParam = (RsaPrivateCrtKeyParameters)(Convert.FromBase64String(privateKey)); return ("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>", 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 againjava
conversion method.Below isjava
Code, conversionjava
The 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); ("<RSAKeyValue>"); ("<Modulus>" + b64encode(removeMSZero(().toByteArray())) + "</Modulus>"); ("<Exponent>" + b64encode(removeMSZero(() .toByteArray())) + "</Exponent>"); ("<P>" + b64encode(removeMSZero(().toByteArray())) + "</P>"); ("<Q>" + b64encode(removeMSZero(().toByteArray())) + "</Q>"); ("<DP>" + b64encode(removeMSZero(() .toByteArray())) + "</DP>"); ("<DQ>" + b64encode(removeMSZero(() .toByteArray())) + "</DQ>"); ("<InverseQ>" + b64encode(removeMSZero(() .toByteArray())) + "</InverseQ>"); ("<D>" + b64encode(removeMSZero(() .toByteArray())) + "</D>"); ("</RSAKeyValue>"); 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); ("<RSAKeyValue>"); ("<Modulus>" + b64encode(removeMSZero(().toByteArray())) + "</Modulus>"); ("<Exponent>" + b64encode(removeMSZero(() .toByteArray())) + "</Exponent>"); ("</RSAKeyValue>"); 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(); ("<RSAKeyValue>"); ("<Modulus>") .append((().toByteArray())) .append("</Modulus>"); ("<Exponent>") .append((() .toByteArray())).append("</Exponent>"); ("</RSAKeyValue>"); 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,pfx
The certificate contains public key information and private key information.cer
The certificate only contains public key information. PFX certificates can be exported as pfx certificates or ascer
Certificate. 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.cer
Certificate. 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 TCP
This is all about the article on channel encryption communication instances, more relatedC#
andjava TCP
For 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#