java原始碼實現生成,簽發,驗證使用者證書功能
阿新 • • 發佈:2019-02-08
NOTE:已安裝的jdk(gnu jdk 1.5)預設keystore型別是gkr,而下面程式碼要求keystore型別是jks,故產生invalid keystore format錯誤。解決方法:用sun jdk產生keystore。
1. 生成CA金鑰對
在sun jdk 1.6 bin下執行
./keytool -genkey -alias caroot -keyalg RSA -keysize 1024 -keystore /root.keystore
(CA的DN: CN=caroot, OU=CS, O=HUST, L=Wuhan, ST=Hubei, C=CN)
2. chmod a+w /root/.keystore
3. Generate user certificate signed by ca private key.
(原始碼可以gnu jdk下編譯通過)
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.x509.X509V3CertificateGenerator;
public class CertificateChainDemo {
public String caName = "caroot";
public String caPasswd = "******";
public String keyStorePasswd = "******";
public String keyStorePath = "/root/.keystore";
public String userDN = "CN=loong, OU=CS, O=HUST ,L=Wuhan, ST=Hubei, C=CN";
public String userAlias = "loong"; // 使用者別名
public CertificateChainDemo() {
}
public boolean generateX509Certificate(String userCertPath) {
try {
FileInputStream in = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, keyStorePasswd.toCharArray());
in.close();
// Get CA private key.
PrivateKey caPrivateKey = (PrivateKey) ks.getKey(caName, caPasswd.toCharArray());
System.out.println("\nCA private key:\n" + caPrivateKey);
// Get CA DN.
Certificate c = ks.getCertificate(caName);
X509Certificate t = (X509Certificate) c;
String caDN = t.getIssuerDN().toString();
// CN:姓氏、名字 OU:組織單位名稱 O:組織名稱 L:城市、區域 C:國家程式碼
System.out.println("\nCA DN:\n" + caDN);
X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
KeyPair KPair = RSAKeyPairGenDemo.getRSAKeyPair(1024);
System.out.println("\nuser private key:\n" + KPair.getPrivate());
System.out.println("\nuser public key:\n" + KPair.getPublic());
v3CertGen.setSerialNumber(BigInteger.valueOf(1));
v3CertGen.setIssuerDN(new X509Principal(caDN));
// 證書有效期起
v3CertGen.setNotBefore(new Date(System.currentTimeMillis()));
// 證書有效期止
v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 365)));
v3CertGen.setSubjectDN(new X509Principal(userDN));
v3CertGen.setPublicKey(KPair.getPublic());
v3CertGen.setSignatureAlgorithm("SHA1WithRSA");
// Generate user certificate signed by ca private key.
X509Certificate cert = v3CertGen.generateX509Certificate(caPrivateKey);
FileOutputStream out = new FileOutputStream(userCertPath);
out.write(cert.getEncoded());
out.close();
// Add user entry into keystore
ks.setCertificateEntry(userAlias, cert);
out = new FileOutputStream(keyStorePath);
ks.store(out, caPasswd.toCharArray());
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
public void listX509CertificateInfo(String certFile) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X509");
X509Certificate x509Cert = (X509Certificate) cf.generateCertificate(new FileInputStream(certFile));
System.out.println("\nIssuerDN:" + x509Cert.getIssuerDN());
System.out.println("Signature alg:" + x509Cert.getSigAlgName());
System.out.println("Version:" + x509Cert.getVersion());
System.out.println("Serial Number:" + x509Cert.getSerialNumber());
System.out.println("Subject DN:" + x509Cert.getSubjectDN());
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean Verify(String certPath) {
Certificate cert;
PublicKey caPublicKey;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream(certPath);
cert = cf.generateCertificate(in);
in.close();
X509Certificate t = (X509Certificate) cert;
Date timeNow = new Date();
t.checkValidity(timeNow);
in = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, keyStorePasswd.toCharArray());
in.close();
caPublicKey = ks.getCertificate(caName).getPublicKey();
System.out.println("\nCA public key:\n" + caPublicKey);
try {
cert.verify(caPublicKey);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("no pass.\n");
e.printStackTrace();
}
System.out.println("\npass.\n");
} catch (CertificateExpiredException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (CertificateNotYetValidException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (CertificateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (KeyStoreException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return true;
}
public static void main(String args[]) {
String userCertPath = "/home/loong/loong.crt";
CertificateChainDemo ccd = new CertificateChainDemo();
ccd.generateX509Certificate(userCertPath);
ccd.listX509CertificateInfo(userCertPath);
ccd.Verify(userCertPath);
}
}
另附RSAKeyPairGenDemo原始碼如下:
public class RSAKeyPairGenDemo {
public final static int PUBLIC_KEY = 0;
public final static int PRIVATE_KEY = 1;
public static KeyPair getRSAKeyPair(int keySize) {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
keyGen.initialize(keySize, random);
KeyPair pair = keyGen.generateKeyPair();
return pair;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean SaveKeyFile(KeyPair keyPair, String keyFile,
int keyType) {
boolean succ = true;
// File fKey = new File(keyFile);
FileOutputStream os = null;
try {
if (keyType != 1 && keyType != 0) {
throw new Exception("Invalid keyType!");
}
os = new FileOutputStream(keyFile);
Key key = (keyType == PUBLIC_KEY ? (Key) keyPair.getPublic()
: (Key) keyPair.getPrivate());
os.write(key.getEncoded());
// ObjectOutputStream objOs = new ObjectOutputStream(os);
// objOs.writeObject((keyType == PUBLIC_KEY ? (Key) keyPair
// .getPublic() : (Key) keyPair.getPrivate()));
// objOs.close();
} catch (Exception e) {
e.printStackTrace();
succ = false;
}
return succ;
}
public static Key LoadKeyObjFromFile(boolean ispk, String keyFile) {
Key key = null;
FileInputStream is = null;
ObjectInputStream objIs = null;
try {
is = new FileInputStream(keyFile);
byte[] buf = new byte[is.available()];
KeyFactory kf = KeyFactory.getInstance("RSA");
is.read(buf);
EncodedKeySpec ks;
if (ispk) {
ks = new PKCS8EncodedKeySpec(buf);
} else {
ks = new X509EncodedKeySpec(buf);
}
key = (!ispk ? (Key) kf.generatePublic(ks) : (Key) kf
.generatePrivate(ks));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException iex) {
iex.printStackTrace();
}
}
return key;
}
}
1. 生成CA金鑰對
在sun jdk 1.6 bin下執行
./keytool -genkey -alias caroot -keyalg RSA -keysize 1024 -keystore /root.keystore
(CA的DN: CN=caroot, OU=CS, O=HUST, L=Wuhan, ST=Hubei, C=CN)
2. chmod a+w /root/.keystore
3. Generate user certificate signed by ca private key.
(原始碼可以gnu jdk下編譯通過)
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.x509.X509V3CertificateGenerator;
public class CertificateChainDemo {
public String caName = "caroot";
public String caPasswd = "******";
public String keyStorePasswd = "******";
public String keyStorePath = "/root/.keystore";
public String userDN = "CN=loong, OU=CS, O=HUST ,L=Wuhan, ST=Hubei, C=CN";
public String userAlias = "loong"; // 使用者別名
public CertificateChainDemo() {
}
public boolean generateX509Certificate(String userCertPath) {
try {
FileInputStream in = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, keyStorePasswd.toCharArray());
in.close();
// Get CA private key.
PrivateKey caPrivateKey = (PrivateKey) ks.getKey(caName, caPasswd.toCharArray());
System.out.println("\nCA private key:\n" + caPrivateKey);
// Get CA DN.
Certificate c = ks.getCertificate(caName);
X509Certificate t = (X509Certificate) c;
String caDN = t.getIssuerDN().toString();
// CN:姓氏、名字 OU:組織單位名稱 O:組織名稱 L:城市、區域 C:國家程式碼
System.out.println("\nCA DN:\n" + caDN);
X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
KeyPair KPair = RSAKeyPairGenDemo.getRSAKeyPair(1024);
System.out.println("\nuser private key:\n" + KPair.getPrivate());
System.out.println("\nuser public key:\n" + KPair.getPublic());
v3CertGen.setSerialNumber(BigInteger.valueOf(1));
v3CertGen.setIssuerDN(new X509Principal(caDN));
// 證書有效期起
v3CertGen.setNotBefore(new Date(System.currentTimeMillis()));
// 證書有效期止
v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 365)));
v3CertGen.setSubjectDN(new X509Principal(userDN));
v3CertGen.setPublicKey(KPair.getPublic());
v3CertGen.setSignatureAlgorithm("SHA1WithRSA");
// Generate user certificate signed by ca private key.
X509Certificate cert = v3CertGen.generateX509Certificate(caPrivateKey);
FileOutputStream out = new FileOutputStream(userCertPath);
out.write(cert.getEncoded());
out.close();
// Add user entry into keystore
ks.setCertificateEntry(userAlias, cert);
out = new FileOutputStream(keyStorePath);
ks.store(out, caPasswd.toCharArray());
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
public void listX509CertificateInfo(String certFile) {
try {
CertificateFactory cf = CertificateFactory.getInstance("X509");
X509Certificate x509Cert = (X509Certificate) cf.generateCertificate(new FileInputStream(certFile));
System.out.println("\nIssuerDN:" + x509Cert.getIssuerDN());
System.out.println("Signature alg:" + x509Cert.getSigAlgName());
System.out.println("Version:" + x509Cert.getVersion());
System.out.println("Serial Number:" + x509Cert.getSerialNumber());
System.out.println("Subject DN:" + x509Cert.getSubjectDN());
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean Verify(String certPath) {
Certificate cert;
PublicKey caPublicKey;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
FileInputStream in = new FileInputStream(certPath);
cert = cf.generateCertificate(in);
in.close();
X509Certificate t = (X509Certificate) cert;
Date timeNow = new Date();
t.checkValidity(timeNow);
in = new FileInputStream(keyStorePath);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(in, keyStorePasswd.toCharArray());
in.close();
caPublicKey = ks.getCertificate(caName).getPublicKey();
System.out.println("\nCA public key:\n" + caPublicKey);
try {
cert.verify(caPublicKey);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("no pass.\n");
e.printStackTrace();
}
System.out.println("\npass.\n");
} catch (CertificateExpiredException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (CertificateNotYetValidException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (CertificateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (KeyStoreException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return true;
}
public static void main(String args[]) {
String userCertPath = "/home/loong/loong.crt";
CertificateChainDemo ccd = new CertificateChainDemo();
ccd.generateX509Certificate(userCertPath);
ccd.listX509CertificateInfo(userCertPath);
ccd.Verify(userCertPath);
}
}
另附RSAKeyPairGenDemo原始碼如下:
public class RSAKeyPairGenDemo {
public final static int PUBLIC_KEY = 0;
public final static int PRIVATE_KEY = 1;
public static KeyPair getRSAKeyPair(int keySize) {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
keyGen.initialize(keySize, random);
KeyPair pair = keyGen.generateKeyPair();
return pair;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean SaveKeyFile(KeyPair keyPair, String keyFile,
int keyType) {
boolean succ = true;
// File fKey = new File(keyFile);
FileOutputStream os = null;
try {
if (keyType != 1 && keyType != 0) {
throw new Exception("Invalid keyType!");
}
os = new FileOutputStream(keyFile);
Key key = (keyType == PUBLIC_KEY ? (Key) keyPair.getPublic()
: (Key) keyPair.getPrivate());
os.write(key.getEncoded());
// ObjectOutputStream objOs = new ObjectOutputStream(os);
// objOs.writeObject((keyType == PUBLIC_KEY ? (Key) keyPair
// .getPublic() : (Key) keyPair.getPrivate()));
// objOs.close();
} catch (Exception e) {
e.printStackTrace();
succ = false;
}
return succ;
}
public static Key LoadKeyObjFromFile(boolean ispk, String keyFile) {
Key key = null;
FileInputStream is = null;
ObjectInputStream objIs = null;
try {
is = new FileInputStream(keyFile);
byte[] buf = new byte[is.available()];
KeyFactory kf = KeyFactory.getInstance("RSA");
is.read(buf);
EncodedKeySpec ks;
if (ispk) {
ks = new PKCS8EncodedKeySpec(buf);
} else {
ks = new X509EncodedKeySpec(buf);
}
key = (!ispk ? (Key) kf.generatePublic(ks) : (Key) kf
.generatePrivate(ks));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException iex) {
iex.printStackTrace();
}
}
return key;
}
}