The X.509 Certificate corresponds to the system. Security. cryptography. x509certificates. x509certificate2 class in. net. X509certificate2 supports RSA and DSA encryption. The RSA encryption method has been clearly stated on msdn, but the DSA encryption method is not mentioned on msdn.
This article describes the difference in DSA encryption between the two platforms.
I. Certificate and Key Generation
Under. Net framework, you can use the self-carried makecert.exe tool to generate keys and certificates. The compiler tool generates. SPC files, and uses pvk2pfx. Ext to generate the. pfx files we want. The use of makecert.exe、cert2spc.exe and pvk2pfx. Ext tools can be found on msdn.
OpenSSL is required to generate the key and public key in the DSA format in. net. After finding the Win32 version of OpenSSL, follow these steps:
① generate the DSA parameter file OpenSSL dsaparam-rand-genkey-out ca. PEM 1024 ② generate the DSA Private Key OpenSSL gendsa-des3-out ca. key ca. PEM ③ generate ca self-signed certificate OpenSSL req-New-X509-key ca. key-out ca. CRT-config OpenSSL. CNF ④ generate client csropenssl req-New-key ca. key-out jfsc_public.csr-days 1460-config OpenSSL. CNF ⑤ uses the CA private key for signature. You can also apply to the Authority for Ca signature OpenSSL ca-In jfsc_public.csr-out jfsc_public.crt-Cert CA. CRT-days 1460-Keyfile ca. key-notext-config OpenSSL. CNF 6 generates a PKCS12 certificate OpenSSL PKCS12-export-inkey ca. key-In jfsc_public.crt-out jfsc_private.p12 7 import the PKCS12 certificate to the local certificate storage unit, and export jfsc_public.cerc = CH, O = iflytek, ou = jfsc, L = BJ, S = BJ, CN = UAM, E = xuf22@hotmail.com
When a private key is generated, the system prompts you to enter the password. Here, 12345678 is used, jfsc_private.p12 is the private key, and jfsc_public.cer is the public key.
In the jdkplatform, use keytool.exe to generate the private key keystore and public key. CRT files encrypted by DSA.
Ii. How to Use the JDK Public Key. CRT file to verify the signature in. Net?
The Java Private Key keystore file cannot be read in. net, while the Public Key. CRT file can be loaded into the x509certificate2 class. On the Java platform, use the private key signature to obtain the hexadecimal string as follows:
30 2C
02 14
1c fa 3A BB 5C 0f 37 FB D7 74 CB 51 E5 64 B5 76 B9 26 4f 7A
02 14
62 7E FF 2D 11 4B 2D D3 27 F3 8B 30 D1 6D B4 D2 78 5A 72 5b
It can be found that the Java signature is 43 bytes, And the. NET signature can only be 40 bits. The Java signature must be converted.
/* DER encoding rules the DSA Signature generates the R and S integers. For dsawithsha1, both integers are no more than 20 bytes. Because a random number is required for the DSA Signature, the result of each signature is different. The signature result of the dsawithsha1 generated by Java is the DER code of the following ASN.1 structure: DSS-sig-value ::= sequence {r integer, s integer }. net requires a signature result of 40 bytes. The first 20 bytes are R, and the last 20 bytes are S. DER encoding adopts the form of TLV. Each type has a tag encoding, which is the T part encoding, followed by the length encoding, which is the L part encoding, the last part is the content encoding, which is the V Part encoding. For sequence, the tag is encoded as 0x30, and its content encoding is the one-by-one TLV encoding of the ASN.1 object it holds. For integer, the tag is encoded as 0x02, and its content encoding is a complement of the smallest byte. The first 9 digits cannot be all 1 or all 0. 0 indicates a positive number, and 1 indicates a negative number. Because it is a positive number, if the highest bit is 1, the first part must be supplemented with 0, that is, the encoding length of the longest integer content is 20 + 1 = 21 bytes. The Length Encoding occupies only one byte for no more than 127, and the encoding is the value itself. This is the case. Example: java Signature 30 2c02 141c fa 3A BB 5C 0f 37 FB D7 74 CB 51 E5 64 B5 76 B9 26 4f 7a02 1462 7E FF 2D 11 4B 2D D3 27 F3 8B 30 D1 6D B4 d2 78 5A 72 5b30 indicates sequence2c indicates that 0x2c bytes are encoded later. 02 indicates that integer14 indicates that 0x14 bytes are encoded later. 1C fa 3A BB 5C 0f 37 FB D7 74 CB 51 E5 64 B5 76 b9 26 4f 7A this part is the R content encoding. Here the r content encoding is exactly 20, copy the file directly. If the value is less than 20 bytes, the first byte is 0 to 20 bytes. If it is 21 bytes, the first byte is removed. This byte should be 0, indicating that R is a positive number. If this byte is not 0, the signature is incorrect. 02 indicates that integer14 indicates that the code is followed by 0x14 bytes 62 7E FF 2D 11 4B 2D D3 27 F3 8B 30 D1 6D B4 D2 78 5A 72 5B. This part is the encoding of s content. The processing method is the same as R content encoding. Finally, convert. net signature 1C fa 3A BB 5C 0f 37 FB D7 74 CB 51 E5 64 B5 76 B9 26 4f 7A 62 7E FF 2D 11 4B 2D D3 27 F3 8B 30 D1 6D B4 D2 78 5A 72 5B **/
Code :
Public byte [] fromhex (byte [] SC) {byte [] res = new byte [SC. length/2]; for (INT I = 0; I <SC. length; I ++) {byte C1 = (byte) (SC [I]-48 <17? SC [I]-48: SC [I]-55); I ++; byte C2 = (byte) (SC [I]-48 <17? SC [I]-48: SC [I]-55); Res [I/2] = (byte) (C1*16 + C2);} return res ;} public byte [] fromhexstring (string HEX) {return fromhex (system. text. encoding. default. getbytes (HEX);} private bool verifysignature (string originalstring) {try {byte [] hashbytetoverify; byte [] signbyte; string signatureconvert = derdecode (signature ); signbyte = fromhexstring (signatureconvert); x509certificate2 x509_cer2 = new x509certificate2 ("path/paths"); DSA = (dsacryptoserviceprovider) complete; hashbytetoverify = System. text. encoding. default. getbytes (originalstring); bool B = DSA. verifydata (hashbytetoverify, signbyte); return B ;}} Public String derdecode (string derstr) {string result = ""; string r = ""; string S = ""; byte [] rbyte = new byte [20]; byte [] sbyte = new byte [20]; byte [] content = fromhexstring (derstr); string intrstr = content [3]. tostring (); int intrlength = int. parse (intrstr); Int J = 0; If (intrlength = 20) {for (INT I = 0; I <20; I ++) {rbyte [I] = content [4 + I];} J = 24;} else if (intrlength> 20) {for (INT I = 0; I <20; I ++) {rbyte [I] = content [5 + I];} J = 25;} else {int notenough = 20-intrlength; For (INT I = 0; I <notenough; I ++) {byte [] TMP = new byte [] {00}; rbyte [I] = TMP [0];} For (INT I = 0; I <notenough; I ++) {rbyte [notenough + I] = content [4 + I];} J = 24-intrlength;} int intslength = int. parse (content [J + 1]. tostring (); If (intslength = 20) {for (INT I = 0; I <20; I ++) {sbyte [I] = content [J + 2 + I] ;}} else if (intslength> 20) {for (INT I = 0; I <20; I ++) {sbyte [I] = content [J + 3 + I] ;}} else {int notenough = 20-intslength; For (INT I = 0; I <notenough; I ++) {byte [] TMP = new byte [] {00}; sbyte [I] = TMP [0] ;}for (INT I = 0; I <intslength; I ++) {sbyte [notenough + I] = content [J + 2 + I] ;}} r = tohexstring (rbyte); s = tohexstring (sbyte ); result = R + S; return result ;}
Iii. Transfer the. NET signature to the Java platform for Signature Verification
Public String derencode (byte [] B) {string STR = tohexstring (B); string newstr1 = Str. substring (0, 40); string newstr2 = Str. substring (40, 40); string newstr = "302c0214" + newstr1 + "0214" + newstr2; return newstr;} private string sigexml (string originalstring) {x509certificate2 x509_cer2 = new x509certificate2 ("path/jfsc_private.p12"); DSA = (dsacryptoserviceprovider) callback; byte [] xmlbyte = encoding. default. getbytes (originalstring); byte [] hashbyte = RSA. signdata (xmlbyte); Return derencode (hashbyte );}
Thank you for the help of the unknown Support Team.