(Reprinted in the preface: a good article I found on the Internet has summarized everything I 've been looking for a few days. I am very grateful to the author: Li Suke was actually looking for materials, the main unsolved problem is how to obtain the privatekey in the keystore file. You can check the jsdk 1.4 API documentation, but I did not find this method after reading it twice from top to bottom: load ().......)
A certificate (also known as Public-Key Certificate) uses a signature algorithm) digital Certificate obtained after digital signature can be used as a trusted relationship intermediary. The certificate issuing authority issues a certificate to inform the certificate user or entity of its Public Key (public-key) as well as other auxiliary information certificates are widely used in e-commerce security transactions. The Certificate Issuer is also known as Ca (Certificate Authority)
Application Certificate
The role of a certificate in public key encryption applications is to ensure that the public key is published in certain trusted organizations, it has important applications in SSL Electronic Transaction Protocol set. Figure 1 shows a simple certificate application method:
Figure 1 Certificate Application Method
The application steps of the certificate are as follows:
(1) A sends its own public key (KA) to Ca (Certificate Authority );
(2) ca uses its own private key and a's public key to generate a certificate. The certificate includes the CA's digital signature object, including the content to be described in the certificate, for example, the Public Key timestamp serial number of A. to simplify the process, assume that the certificate contains only three items: the time stamp of the public key of a is time1 serial number Ida. Then the simple certificate issued by CA to A can be displayed as: certa = ECA [time1, Ida, Ka];
(3) B also sends its own public key PKB to CA;
(4) B. obtain the certificate certb issued by the CA;
(5) A informs B of the certificate certa;
(6) B inform a of the certificate certb
After each AB obtains the certificate from the other party, it verifies the validity of the certificate from the CA's public key (in the CA's self-signed certificate, the public key of each other can be used to encrypt data or verify the digital signature of the other party.
For convenience, this document does not use the certificate obtained from the ca. Instead, both parties generate a self-signed certificate, that is, A and B in Figure 1 do not pass through the CA, however, the premise is that A and B have the certificate of each other.
The content and meaning of the certificate are shown in table 1 (Here we use the general X. 509 certificate format as an example)
Table 1 certificate content and meaning
| Certificate content |
Meaning |
| Version |
Which version of the X.509 Certificate is provided? Currently, v1v2v3 is available. |
| Serial number |
Serial number of the certificate set by the certificate distributor |
| Signature Algorithm identifier |
What signature algorithm does the certificate use? |
| Issuer name |
The name of the certificate issuer, that is, the name of the organization that signs the certificate. |
| Validity Period |
Certificate validity period |
| Subject name |
The name of the public key owner or entity signed by the certificate authority. The X.500 protocol is used. The identifier on the internet is unique, for example, Cn = Java, ou = Infosec, O = Infosec lab, c = cn indicates a subject name |
For detailed definitions of certificates and various protocols related to their applications, see rfc2450rfc2510rfc2511rfc2527rfc2528rfc2559rfc2560rfc2585rfc2587 for details.
Self-generated visa document
An individual or organization can apply for a certificate from a trusted Certificate distributor. For example, you can obtain a certificate from a http://ca.pku.edu.cn that belongs to an individual. Here you can use the j2sdk security tool keytool to manually generate a self-signed certificate, the self-signed certificate refers to the certificate with the same subject name and issuer name in the certificate
The following generates a self-signed certificate to install j2sdk (j2sdk1.4 is used here), in the bin directory of the j2sdk installation directory, there is a keytool executable program using keytool to generate a self-Visa book as follows:
Step 1: Use the-genkey Command Option to generate a public/private key pair. Enter the following in the console: keytool-genkey-alias testkeypair-keyalg RSA-keysize 1024-sigalg md5withrsa-alias indicates the alias for using this pair of public/private keys to generate a new keystore entry (keystore is used to store management key pairs and certificate chain, the default location is in the user's main directory. you can also specify a path to store hidden files in the name of keystore. keystore file);-keyalg is the algorithm used to generate a public/private key pair. Here it is RSA;-keysize defines the length of the key;-sigalg is the signature algorithm. Select md5withrsa to use RSA signature, next, use the MD5 hash algorithm to digest the data. Then, the system will prompt you to enter the following information:
Enter the keystore password: ABC123. What is your first name and last name? [UNKNOWN]: Li what is the name of your organization? [UNKNOWN]: infoseclab what is your organization name? [UNKNOWN]: What is the name of your city or region in infoseclab group? [UNKNOWN]: What is the name of your state or province? [UNKNOWN]: Beijing what is the two-letter country code of this Unit [UNKNOWN]: CNCN = Li, ou = infoseclab, O = infoseclab group, L = Beijing, St = Beijing, is c = cn correct? [No]: Y enter the <testkeypair> Primary password (if the same as the keystore password, press Enter ): |
Step 2: generate a self-signed certificate and enter the following command:
Keytool-selfcert-alias testkeypair-dname "cn = Li, ou = infoseclab, O = infoseclab group, L = Beijing, St = Beijing, c = cn" Enter the keystore password: ABC123 |
Step 3: export the self-signed certificate. The certificate generated in the preceding two steps has been stored at the keystore entry with testkeypair as the alias. If you use the file, you must export the certificate input:
Keytool-export-RFC-alias testkeypair-file mycert. CRT enter the keystore password: ABC123 authentication stored in the file <mycert. CRT> |
In this way, a self-signed certificate mycert. CRT is obtained. Note that the RFC option outputs the certificate as the final encoded format defined in rfc1421 using base64.
Read Certificate
Java provides a wide range of APIS for secure applications. JSSE (javatm Secure Socket Extension) of j2sdk1.4 includes javax. security. the certificate package, and provides the certificate read operations, only Java. security. cert. certificatefactory and Java. security. cert. x509certificate:
Import javax. swing. *; import Java. AWT. *; import Java. AWT. event. *; import javax. swing. table. *; import Java. security. cert. certificatefactory; import Java. security. cert. x509certificate; import Java. io. *; public class caread extends jpanel {private string ca_name; private string ca_itemdata [] [] = new string [9] [2]; private string [] columnnames = {"Certificate field tag", "content"}; Public caread (string certname) {ca_name = certname; /* three panels are used to display the certificate content */jtabbedpane tabbedpane = new jtabbedpane (); jpanel panelnormal = new jpanel (); tabbedpane. addtab ("normal information", panelnormal); jpanel panelall = new jpanel (); panelall. setlayout (New borderlayout (); tabbedpane. addtab ("all information", panelall); jpanel panelbase64 = new jpanel (); panelbase64.setlayout (New borderlayout (); tabbedpane. addtab ("base64 encoding information", panelbase64);/* read General Certificate Information */read_normal (panelnormal);/* read the Certificate file string to indicate the content */read_bin (panelall ); /* read the original base64 encoded Certificate file */read_raw (panelbase64); tabbedpane. setselectedindex (0); setlayout (New gridlayout (1, 1); add (tabbedpane);}/* the following are the defined read_normal (), read_bin (), read_raw () and main () is omitted here... */} |
The READ function that defines certificate information is as follows:
Private int read_normal (jpanel) {string field; try {certificatefactory certificate_factory = certificatefactory. getinstance ("X.509"); fileinputstream file_inputstream = new fileinputstream (ca_name); x509certificate x509certificate = (certificate) convert (file_inputstream); field = x509certificate. getType (); ca_itemdata [0] [0] = "type"; ca_itemdata [0] [1] = field; field = integer. tostring (x509certificate. getversion (); ca_itemdata [1] [0] = "version"; ca_itemdata [1] [1] = field; field = x509certificate. getsubjectdn (). getname (); ca_itemdata [2] [0] = "title"; ca_itemdata [2] [1] = field;/* similar to the following, field = x509certificate is omitted here. getnotbefore (). tostring (); get the start date field = x509certificate. getnotafter (). tostring (); get the end date field = x509certificate. getserialnumber (). tostring (16); obtain the serial number field = x509certificate. getissuerdn (). getname (); obtain the issuer Name field = x509certificate. getsigalgname (); obtain the signature algorithm field = x509certificate. getpublickey (). getalgorithm (); get the public key algorithm */file_inputstream.close (); Final jtable table = new jtable (ca_itemdata, columnnames); tablecolumn Tc = NULL; tc = table. getcolumnmodel (). getcolumn (1); TC. setpreferredwidth (600); panel. add (table);} catch (exception) {exception. printstacktrace (); Return-1;} return 0 ;} |
If you read the certificate as a string, add the following read_bin function. The certificatefactory. generatecertificate () function can extract the readable information from the standard certificate code (defined in rfc1421). The read_bin Function Code is as follows:
private int Read_Bin(JPanel panel){ try{ FileInputStream file_inputstream=new FileInputStream(CA_Name); DataInputStream data_inputstream=new DataInputStream(file_inputstream); CertificateFactory certificatefactory=CertificateFactory.getInstance("X.509"); byte[] bytes=new byte[data_inputstream.available()]; data_inputstream.readFully(bytes); ByteArrayInputStream bais=new ByteArrayInputStream(bytes); JEditorPane Cert_EditorPane; Cert_EditorPane=new JEditorPane(); while(bais.available()>0){ X509Certificate Cert=(X509Certificate)certificatefactory.generateCertificate(bais); Cert_EditorPane.setText(Cert_EditorPane.getText()+Cert.toString()); } Cert_EditorPane.disable(); JScrollPane edit_scroll=new JScrollPane(Cert_EditorPane); panel.add(edit_scroll); file_inputstream.close(); data_inputstream.close(); }catch( Exception exception){ exception.printStackTrace(); return -1; } return 0; } |
To obtain the encoded information of the original certificate, the following code is available:
private int Read_Raw(JPanel panel){ try{ JEditorPane Cert_EditorPane=new JEditorPane(); String CertText=null; File inputFile = new File(CA_Name); FileReader in = new FileReader(inputFile); char[] buf=new char[2000]; int len=in.read(buf,0,2000); for(int i=1;i<len;i++) { CertText=CertText+buf[i]; } in.close(); Cert_EditorPane.setText(CertText); Cert_EditorPane.disable(); JScrollPane edit_scroll=new JScrollPane(Cert_EditorPane); panel.add(edit_scroll); }catch( Exception exception){ exception.printStackTrace(); return -1; } return 0; } |
Finally, use this applet to check the generated certificate mycert. CRT and write the file name to main:
Public static void main (string [] ARGs) {jframe frame = new jframe ("Certificate reader"); frame. addwindowlistener (New windowadapter () {public void windowclosing (invalid wevent e) {system. exit (0) ;}}); frame. getcontentpane (). add (New caread ("mycert. CRT "), borderlayout. center); frame. setsize (700,425); frame. setvisible (true );} |
The certificate mycert. CRT content is shown in 2. All information and base64 display content are not listed here
Figure 2 certificate mycert. CRT content display
Now I have read some contents of the Certificate. How can I use the certificate? We can assume that A and B share a top secret file F, B trusts and owns a certificate, that is to say, if B owns the public key of a, then a first encrypts the file F through the symmetric key algorithm (such as the DES algorithm) that a and B know, then, sign and hash the encrypted F (such as the MD5 algorithm, to ensure the integrity of the file), and then send F to BB after receiving the file, first, use the public key in the Certificate A to verify the signature, and then use the known encryption algorithm to decrypt it. Then, you can obtain the original file. The digital signature used here can ensure that the file obtained by B can be obtained, A is a, and a cannot deny that a does not own file F, because only a has the private key that allows a's public key to verify its signature. At the same time, the DES algorithm is used to encrypt the file, making the file confidential.
The encryption and decryption functions using the DES algorithm are similar. The encryption algorithm is not further discussed here. For details, see the JSE part of j2sdk. The structure of the file for encryption and decryption is shown in figure 3.
Figure 3 structure of encryption signature decryption verification file
The encryption eydata in the encryption function stores the DES encryption key. If you want to specify it in the program, you can set it:
static byte[] desKeyData = { (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08 }; |
The encryption function is written as follows:
public static void crypt(byte[] cipherText,String outFileName){ try{ DESKeySpec desKeySpec = new DESKeySpec(desKeyData); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(desKeySpec); Cipher cdes = Cipher.getInstance("DES"); cdes.init(Cipher.ENCRYPT_MODE, secretKey); byte[] ct = cdes.doFinal(cipherText); try{ FileOutputStream out=new FileOutputStream(outFileName); out.write(ct); out.close(); }catch(IOException e){ e.printStackTrace(); } }catch (Exception e){ e.printStackTrace(); }} |
CT is the encrypted content, and outfilename stores the encrypted file name to put the CDES. init (cipher. encrypt_mode, secretkey) to CDES. init (cipher. decrypt_mode, secretkey) is used to decrypt the file.
After the file is encrypted, it is necessary to sign the file to ensure that the files sent by A to B cannot be forged. The following files are stored in. the private key in the keystore is used for signing. The Digest algorithm used for signing is MD5. sigtext is the input array of the signed content, and outfilename is the name of the output file after saving the signature, keypassword is the password used to read the keystore, and keystorepath is stored. the path of the keystore file. The function code is as follows:
public static void sig(byte[] sigText, String outFileName,String KeyPassword,String KeyStorePath){ char[] kpass; int i; try{ KeyStore ks = KeyStore.getInstance("JKS"); FileInputStream ksfis = new FileInputStream(KeyStorePath); BufferedInputStream ksbufin = new BufferedInputStream(ksfis); kpass=new char[KeyPassword.length()]; for(i=0;i<KeyPassword.length();i++) kpass[i]=KeyPassword.charAt(i); ks.load(ksbufin, kpass); PrivateKey priv = (PrivateKey) ks.getKey(KeystoreAlias,kpass ); Signature rsa=Signature.getInstance("MD5withRSA"); rsa.initSign(priv); rsa.update(sigText); byte[] sig=rsa.sign(); System.out.println("sig is done"); try{ FileOutputStream out=new FileOutputStream(outFileName); out.write(sig); out.close(); }catch(IOException e){ e.printStackTrace(); } }catch(Exception e){ e.printStackTrace(); }} |
To verify the signature, you need to store the signature file, the signed file, and the certificate. updatedata stores the content of the signed file, and sigedtext stores the signature content. certname is the signature code for Certificate Name verification as follows:
public static void veriSig(byte[] updateData, byte[] sigedText){ try{ CertificateFactory certificatefactory=CertificateFactory.getInstance("X.509"); FileInputStream fin=new FileInputStream(CertName); X509Certificate certificate=(X509Certificate)certificatefactory.generateCertificate(fin); PublicKey pub = certificate.getPublicKey(); Signature rsa=Signature.getInstance("MD5withRSA"); rsa.initVerify(pub); rsa.update(updateData); boolean verifies=rsa.verify(sigedText); System.out.println("verified "+verifies); if(verifies){ System.out.println("Verify is done!"); }else{ System.out.println("verify is not successful"); } }catch(Exception e){ e.printStackTrace(); }} |
You can use keytool to generate two self-signed certificates, or go to a CA to apply for two certificates and use Java to write encryption and verification programs. The above example is just a very simple certificate application, actually, the use of certificates (such as SSL) is much more complicated than this.