Self-Signed X.509 digital certificate generation and Verification
Self-Signed X.509 digital certificate generation and Verification
Digital Certificates are used to mark the identity of network users. In Web applications, digital certificates are widely used, such as secure email, secure website access, Secure Electronic Transaction Processing, and secure electronic transactions.
The format of digital certificates generally adopts the X.509 international standard. At present, the digital certificate certification center mainly issues Security Email certificates, personal and enterprise ID certificates, server certificates, and code signature certificates.
Digital certificates are issued by the Certificate Authority. Generally, the Certificate Authority must register and authenticate the Certificate Authority. In enterprise applications, enterprises are often used to issue digital certificates as the issuing authority (without prior authentication). The scope of use of certificates is also within the enterprise, such a certificate is called "Self-signed.
The digital certificate uses a public key and password system. Each user has a private key (Private Key) that is only owned by himself, which is used for decryption and signature. At the same time, the digital certificate has a Public Key (Public Key) it can also be made public for encryption and signature verification.
The following describes the generation and verification methods of self-signed certificates commonly used in projects. For simplicity, we assume that all website users use the same digital certificate clientca.
I. Server Side
Log on to the remote server, generate a certificate on the server, and download the certificate. Jdk1.5 and above should be installed on the server, because we need to use the built-in JDK keytool, which is located in the bin directory of the JDK installation directory.
1. Generate the key database and root certificate
If the certificate is used for 1st times, it is likely that no key database is available on the server. You can use the following command to create a key database (keystore ).
Keytool-genkey-dname "cn = issuer name, ou = issuer's department, O = issuer's company, L = Kunming, St = Yunnan, C = China "-alias ipccca-keyalg RSA-keysize 1024-keystore ipccca-keypass root certificate password-storepass library Password
After the script is run, the private key database file ipccca is generated in the current user's home directory (for example, C:/Documents and Settings/Administrator directory. Note: You need to set two passwords, one is the root certificate password keypass, and the other is the Database Password storepass. If you are not sure about the difference between the two, it is best to set them to the same.
2. Generate a self-signed certificate
Run the following command to generate a self-signed certificate:
Keytool-genkey-dname "cn = issuer name, ou = issuer's department, O = issuer's company, L = Kunming, St = Yunnan, C = China "-alias clientca-keyalg RSA-keysize 1024-keystore ipccca-keypass 123456-storepass Database Password-validity 1
This certificate is a self-signed certificate, and its alias is clientca, which is stored in the previously generated keystore file (ipccca. This requires the Database Password (storepass) to access the database, which must be the same as that in step 1. Kepass is the public key of the Certificate. You must provide this key when verifying the certificate.
To facilitate testing, we set the certificate validity period to one day. In this way, you must download the certificate again every day.
3. view the keystore
You can use the following command to view the two generated keys:
Keytool-list-keystore ipccca-storepass Database Password
The two keys are listed as follows:
Your keystore contains 2 Inputs
Clientca, 2011-3-30, keyentry,
Authentication fingerprint (MD5): 10: B8: 51: 54: 7b: 1c: 60: 7c: 89: E7: B6: 8e: 71: E5: E1: E7
Ipccca, 2011-3-30, keyentry,
Authentication fingerprint (MD5): C3: E3: 7d: 7c: 9B: AA: 05: 84: 92: AF: 93: 18: 42: D2: 1c: 07
4. Download the certificate
We can place a servlet on the server to provide download of the Self-signed certificate:
Private Static final long serialversionuid = 1l;
// Validity period days
Private Static final int max_days = 1;
// Keystore Password
Private Static final char [] Password = "b7-@ 95598". tochararray ();
// Keystore file path
Private Static final string keystorefilename = "C: // Documents and Settings // administrator // ipccca ";
// Certificate file name
Private Static final string certfilename = "client. Cer ";
// Certificate alias
Private Static final string alias = "clientca ";
Private keystore;
Private string sigalgrithm;
// Read the keystore
Private keystore loadkeystore (string keystorepath ){
Keystore Ks = NULL;
Try {
Fileinputstream fin = new fileinputstream (keystorepath );
Ks = keystore. getinstance ("jks ");
KS. Load (FIN, password );
Fin. Close ();
Return KS;
} Catch (exception e ){
System. Out. println (E. getmessage ());
}
Return KS;
}
// Obtain certinfo
Private x509certinfo getcertinfo (certificate C, string alias ){
X509certinfo certinfo = NULL;
Try {
// Extract certificate information from the certificate to be issued
Byte [] encod2 = C. getencoded (); // obtain the certificate content (encoded bytes)
X509certimpl cimp2 = new x509certimpl (encod2); // create an x509certimpl Image
Sigalgrithm = cimp2.getsigalgname ();
// Obtain the x509certinfo object
Certinfo = (x509certinfo) cimp2.get (x509certimpl. Name
+ "." + X509certimpl. info );
} Catch (exception e ){
System. Out. println (E. getmessage ());
}
Return certinfo;
}
// Modify the validity period
Private void updatevalidity (x509certinfo Cinfo, int days ){
// Obtain the current time
Date d1 = new date ();
// The validity period is extended by N days after the current date
Date D2 = new date (d1.gettime () + days * 24*60*60 * 1000l );
// Create a validity period object
Certificatevalidity CV = new certificatevalidity (D1, D2 );
Try {
Cinfo. Set (x509certinfo. validity, CV); // set the validity period
} Catch (exception e ){
E. printstacktrace ();
}
}
// Store the certificate
Private void savecert (keystore KS, char [] storepass, string alias,
Privatekey pkey, char [] keypass, x509certinfo Cinfo, string algrithm ){
Try {
X509certimpl Cert = new x509certimpl (Cinfo); // create a certificate
CERT. Sign (pkey, algrithm); // sign it with the CA private key
// Obtain the certificate chain of the corresponding entry of the alias
Certificate [] Chain = new certificate [] {Cert };
// Add entries to the keystore. If an existing alias is used, the existing entries are overwritten.
KS. setkeyentry (alias, pkey, keypass, chain );
// Store the keystore to a file
Fileoutputstream fout = new fileoutputstream (keystorefilename );
Keystore. Store (fout, password );
Fout. Close ();
} Catch (exception e ){
E. printstacktrace ();
}
}
// Export the certificate
Private void exportcert (keystore KS, string alias, httpservletresponse response ){
Try {
Certificate Cert = keystore. getcertificate (alias );
// Obtain the certificate content (in the encoded format)
Byte [] Buf = cert. getencoded ();
// Write the Certificate file
Response. setcontenttype ("application/X-download ");
Response. addheader ("content-disposition", "attachment; filename ="
+ Certfilename );
Outputstream out = response. getoutputstream ();
Out. Write (BUF );
Out. Close ();
} Catch (exception e ){
E. printstacktrace ();
}
}
/**
* @ See httpservlet # httpservlet ()
*/
Public getnewcert (){
Super ();
// Todo auto-generated constructor stub
}
/**
* @ See httpservlet # doget (httpservletrequest request, httpservletresponse response)
*/
Protected void doget (httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
Try {
Keystore = loadkeystore (keystorefilename); // read the keystore
Certificate c = keystore. getcertificate (alias); // read the certificate
X509certinfo Cinfo = getcertinfo (C, alias); // obtain the certinfo Certificate
Updatevalidity (Cinfo, max_days); // modify the certificate validity period
// Read the private key of the CA from the keystore
Privatekey pkey = (privatekey) keystore. getkey (alias, "123456"
. Tochararray ());
// Store the keystore to the keystore File
Savecert (keystore, password, alias, pkey, "123456". tochararray (), Cinfo, sigalgrithm );
Exportcert (keystore, alias, response );
} Catch (exception e ){
E. printstacktrace ();
}
}
/**
* @ See httpservlet # dopost (httpservletrequest request, httpservletresponse response)
*/
Protected void dopost (httpservletrequest request, httpservletresponse response) throws servletexception, ioexception {
Doget (request, response );
}
}
The role of this servlet is:
When you request this Serlvet, extract the clientca certificate from the keystore and change the certificate validity period to the next day.
That is to say, when the user client requests the servlet, a new certificate can be obtained. The validity period of this certificate has been extended for one day.
The purpose is to check the certificate downloaded by the user after each login. If the certificate has expired, request this servlet to obtain a valid new certificate.
Ii. Client
The client may be any device, including PCs and mobile terminals. Assume that the client is a mobile terminal based on android1.6 or above, the following is the certificate verification class mycertificate of the Java client:
Public class mycertificate {
Private Static string tag = "mycertificate ";
Public static certificate readcert (File file ){
Certificate c = NULL;
Try {
Certificatefactory cf = certificatefactory. getinstance ("X.509 ");
Fileinputstream in1 = new fileinputstream (File );
C = Cf. generatecertificate (in1 );
In1.close ();
} Catch (exception e ){
Log. E (TAG, E. tostring ());
}
Return C;
}
// Verify the certificate validity
Public static Boolean verifycert (certificate c ){
Publickey pBK = C. getpublickey ();
Try {
C. Verify (pbk );
Return true;
} Catch (exception e ){
Log. E (TAG, "certificate is invalid ");
}
Return false;
}
// Verify the certificate validity period
Public static int verifycertvalidity (date, certificate c ){
Int I = 0;
X509certificate t = (x509certificate) C;
Try {// valid
T. checkvalidity (date );
} Catch (certificateexpiredexception e) {// expiration
Log. E (TAG, "certificate expired ");
I =-1;
} Catch (certificatenotyetvalidexception e) {// not activated
Log. E (TAG, "certificate too early ");
I =-2;
}
Return I;
}
Public static Boolean verify (context CTX ){
Activity Act = (activity) CTX;
Boolean B = false;
// Check whether the certificate file exists
File file = new file (environment. getexternalstoragedirectory () + act. getstring (R. String. cert_dir) + act. getstring (R. String. cert_file ));
If (! File. exists ()){
Act. showdialog (1 );
} Else {
Date d = new date (); // obtain the current time
Certificate c = mycertificate. readcert (File); // read the Certificate file
// Verify the certificate validity
If (! Mycertificate. verifycert (c )){
Act. showdialog (0); // invalid certificate
} Else {
// Verify the certificate validity period
Int I = mycertificate. verifycertvalidity (D, C );
Switch (I ){
Case 0: // valid
B = true;
Break;
Case-1: // expired
Act. showdialog (2 );
Break;
Case-2: // not effective
Act. showdialog (3 );
Break;
}
}
}
Return B;
}
}
You can use it in related activities as follows:
Private void login (string ACC, string pass ){
String url = This. getstring (R. String. port_login_url );
Url = string. Format (URL, ACC, pass );
// Log. I (TAG, URL );
Mainloginhandler handler = new mainloginhandler ();
Modules = saxhelper. getmodules (URL, Handler );
// Log. I (TAG, systems. tostring ());
Log. I ("modules:", "" + modules );
If (modules! = NULL ){
String status = (string) modules. Get ("loginstatus ");
If ("true". Equals (Status )){//Logon successful
If (! Verifycert ()){
Return;
}
Bundle bundle = new bundle ();
Bundle. putserializable ("data ",
(Serializable) modules. Get ("modules "));
Gotoactivity (main. Class, bundle );
} Else {
Toast. maketext (getbasecontext (), "the user name or password is incorrect! ",
Toast. length_short). Show ();
}
}
}
Private Boolean verifycert (){
Return mycertificate. Verify (this );
}
// Create activity hosting dialog box
Protected dialog oncreatedialog (int id ){
Log. E ("::::", "showdialog! ");
String MSG = "";
Switch (ID ){
Case 1:
MSG = "the certificate has not been downloaded! Click "yes" to download the certificate. ";
Break;
Case 2:
MSG = "certificate expired! Click "yes" to download the certificate again. ";
Break;
Case 3:
MSG = "the certificate has not taken effect! Please log on again after the certificate takes effect. ";
// For an invalid certificate, you do not need to download it again.
Return new alertdialog. Builder (this)
. Setmessage (MSG)
. Setnegativebutton ("yes ",
New dialoginterface. onclicklistener (){
Public void onclick (dialoginterface dialog,
Int which ){
Dialog. Dismiss (); // removedialog (0); remove dialog box
}
}). Create ();
Case 4:
Return new alertdialog. Builder (this)
. Setmessage ("location source not set! Are you sure you want to set the location source? ")
. Setpositivebutton ("yes ",
New dialoginterface. onclicklistener (){
Public void onclick (dialoginterface dialog,
Int which ){
// Go to the GPS settings page
Intent intent = new intent (
Settings. action_security_settings );
Startactivityforresult (intent, 0 );
}
})
. Setnegativebutton ("no ",
New dialoginterface. onclicklistener (){
Public void onclick (dialoginterface dialog,
Int which ){
Dialog. Dismiss (); // removedialog (0); remove dialog box
}
}). Create ();
Default:
MSG = "invalid certificate! Click "yes" to download the certificate again. ";
}
Return new alertdialog. Builder (this). setmessage (MSG)
. Setpositivebutton ("yes", new dialoginterface. onclicklistener (){
Public void onclick (dialoginterface dialog, int which ){
// Start to download the certificate
Downloadcert ();
}
})
. Setnegativebutton ("no", new dialoginterface. onclicklistener (){
Public void onclick (dialoginterface dialog, int which ){
Dialog. Dismiss (); // removedialog (0); remove dialog box
}
}). Create ();
}
The code in the bold red part calls mycertificate. Verify (). The oncreatedialog method returns the certificate verification result in the dialog box.
Http://www.cnblogs.com/encounter/archive/2011/05/13/2188492.html