这是本系列的第一个帖子,我将向您展示如何在Java程序中生成SSL证书。证书经常用于需要服务器到客户端身份验证的SSL通信。这是为了让客户端相信服务器确实是它声称的那一个。证书在互联网上非常重要。互联网上的所有HTTPS通信都需要服务器端提供由受信任的CA签名的证书。
请求生成的流程是这样的:我们首先使用某些工具生成证书请求,此证书请求将发送给受信任的CA进行签名,签名证书后,此证书将发送给请求者。请求者之后可以在其服务器上安装证书。
您可以使用许多库来完成这些步骤。例如openssl、Java keytool、iKeyman。此外,在Java中,您可以自己编写代码来生成证书。
如果您使用的是keytool,则以下命令可以帮助您创建一个私钥及其关联的自签名证书。
keytool -genkeypair -alias rsakey -keyalg rsa -storepass passphrase -keystore mytestkeys.jks -storetype JKS -dname "CN=ROOT"
在本篇文章中,我们将首先展示创建可用证书(自签名证书)最简单的方法。自签名证书是指证书的发行者是证书的主题,即您使用自己的私钥签名自己的证书。
在Java中,有一个名为CertAndKeyGen的类,可用于生成密钥和证书。生成一对密钥,并提供对它们的访问权限。此类主要为了易用性而提供。它提供了一些简单的证书管理功能。具体来说,它允许您创建自签名X.509证书以及基于PKCS 10的证书签名请求。
以下是生成自签名证书的代码片段:
import java.security.cert.X509Certificate;
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.X500Name;
public class SelfSignedCertificateGeneration {
public static void main(String[] args){
try{
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
keyGen.generate(1024);
//生成自签名证书
X509Certificate[] chain=new X509Certificate[1];
chain[0]=keyGen.getSelfCertificate(new X500Name("CN=ROOT"), (long)365*24*3600);
System.out.println("Certificate : "+chain[0].toString());
}catch(Exception ex){
ex.printStackTrace();
}
}
}
让我们看看证书数据是什么:
Certificate : [
[
Version: V3
Subject: CN=ROOT
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 1024 bits
modulus: 114391309107542773913020327258312183039826043488144930936432429784366769808118582358673188617553493179715429490538390339548553158770231498533107085203543482991384318715251748594629731873902297622858400215317090155179482056595085606008433735465924998820797111761561551868239613864908732016915661242341876829949
public exponent: 65537
Validity: [From: Wed Jul 30 21:06:29 SGT 2014,
To: Thu Jul 30 21:06:29 SGT 2015]
Issuer: CN=ROOT
SerialNumber: [ 0b000b59]
]
Algorithm: [SHA1withRSA]
Signature:
0000: 94 F9 DD 3D 95 4F BC 63 A6 A3 09 9E 63 EF CA 91 ...=.O.c....c...
0010: 97 55 C1 9E B2 12 52 13 7A 7B 73 B1 B8 ED A8 EF .U....R.z.s.....
0020: F5 1C EB 27 71 F2 60 22 BC E9 0B 01 1D 70 C1 5E ...'q.`".....p.^
0030: D6 D1 E8 AB 4D 2C CC F6 70 2B 7A D4 37 95 7A CC ....M,..p+z.7.z.
0040: E2 A1 FE F9 3F 11 18 FD 36 CB 22 62 FB 5A E2 5D ....?...6."b.Z.]
0050: E6 6C BF 61 C7 1F 03 BA FE B5 85 47 DD 7F C0 CB .l.a.......G....
0060: F3 F1 A0 79 35 0F 2A F7 79 0E 1E 79 A1 11 2E 44 ...y5.*.y..y...D
0070: 85 10 F2 B3 9F 07 F0 24 D3 1A AC 28 0C CE 4B 04 .......$...(..K.
]
从证书数据中,您可以看到主题和发行者是相同的。
在下一篇帖子中,我将向您展示如何使用Java程序生成证书链。
Great start for developers who are working in security field
While running outside eclipse i am getting following error
SelfSignedCertificateGeneration.java:3: error: package sun.security.tools.keytoo
l does not exist
import sun.security.tools.keytool.CertAndKeyGen;
^
SelfSignedCertificateGeneration.java:4: warning: X500Name is internal proprietar
y API and may be removed in a future release
import sun.security.x509.X500Name;
^
SelfSignedCertificateGeneration.java:9: error: cannot find symbol
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class SelfSignedCertificateGeneration
SelfSignedCertificateGeneration.java:9: error: cannot find symbol
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class SelfSignedCertificateGeneration
SelfSignedCertificateGeneration.java:14: warning: X500Name is internal proprieta
ry API and may be removed in a future release
chain[0]=keyGen.getSelfCertificate(new X500Name("CN=ROOT"), (long)36
5*24*3600);
^
3 errors
2 warnings
D:\JAVA Learning\Program\Rohit>java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b26)
Java HotSpot(TM) Client VM (build 25.40-b25, mixed mode, sharing)
In latest Java 8, there are some changes with respect to the source code structure. Now you need to use below command to compile the source code to remove the errors ad warnings:
javac -XDignore.symbol.file SelfSignedCertificateGeneration.java
When javac is compiling code it doesn't link against
rt.jarby default in latest Java 8. Instead it uses special symbol filelib/ct.symwith class stubs. The option -XDignore.symbol.file is to ignore the symbol file so that it will link against rt.jar.For this change, please refer to JDK JEP 201 : Modular Source Code.
Thanks for your reply. And its working you saved me
One question how to compile with maven
Put below into your pom.xml and then mvn -X clean compile.
Note prior to maven-compiler-plugin 3.1, you should use <compilerArgument>-XDignore.symbol.file</compilerArgument> instead.
This is not working facing the same errors
C:\Users\z018653>javac -XDignore.symbol.file SelfSignedCertificateGeneration.java
d:\SelfSignedCertificate
Generation.java:5: error: package sun.security.tools.keytool does not exist
import sun.security.tools.keytool.CertAndKeyGen;
^
d:\SelfSignedCertificate
Generation.java:11: error: cannot find symbol
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class SelfSignedCertificateGeneration
d:\SelfSignedCertificate
Generation.java:11: error: cannot find symbol
CertAndKeyGen keyGen=new CertAndKeyGen("RSA","SHA1WithRSA",null);
^
symbol: class CertAndKeyGen
location: class SelfSignedCertificateGeneration
3 errors
Can you post your Java version?
I tried with Java 1.7, 1.6 and also with 1.8
I just tried on my machine with Java 8 and it works. See below:
Can you try this version?
Thank you very much
This shouldn't be that easy
I am using a server - client architecture, server has self signed certificate, through the eclipse i am calling REST API to the server but i am getting the error
Exception: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
can you please help me.
Well, Subject Alternative Names(SAN) allow you to specify a list of host names to be protected by a single SSL certificate. It's an X509 certificate extension. So you need to add an SAN extension in your generated certificate.
If you are in a development environment where you are doing some testing, you can implement below workaround in your code:
static { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { // ip address of the service URL if (hostname.equals("<ip_address>")) return true; return false; } }); }This will add a default hostname verifier which you can determine which host to trust here.
Hi,
How can I compute the size of the Self Signed Certificate Generation.
Thanks
Size? Can you be more specific?
Hello;
I will begin by thanking you for answering me. Concerning my question I would like to know how to get the size (in bit or byte) of the entire self signed certificate. I mean the following certificate:
importjava.security.cert.X509Certificate;importsun.security.tools.keytool.CertAndKeyGen;importsun.security.x509.X500Name;publicclassSelfSignedCertificateGeneration {publicstaticvoidmain(String[] args){try{CertAndKeyGen keyGen=newCertAndKeyGen("RSA","SHA1WithRSA",null);keyGen.generate(1024);//Generate self signed certificateX509Certificate[] chain=newX509Certificate[1];chain[0]=keyGen.getSelfCertificate(newX500Name("CN=ROOT"), (long)365*24*3600);System.out.println("Certificate : "+chain[0].toString());}catchU just need to get its encoded data in byte array representive and get its size or save the encoded data into a certificate file and then should be using File logic to get its size.
Can anyone please provide complete code to sign a csr (which I have received from a client) and generate certificate for the client.
It's really urgent..please consider.
Where can we find the keypair which is generated here?...where is it stored after generation??
You can refer to https://www.pixelstech.net/article/1408524957-Generate-certificate-in-Java----Store-certificate-in-KeyStore on how to store