1. 程式人生 > >java原始碼實現生成,簽發,驗證使用者證書功能

java原始碼實現生成,簽發,驗證使用者證書功能

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;
    }
}