EJBCA操作說明(二)java操作

ejbca web界面操作

代碼下載地址

  • 初始化獲得EJBCA實例
	/**
	 * 初始化EjbcaWS,獲得EJBCA服務端Webservice實例
	 * @return
	 */
	public static EjbcaWS init() 
	{		
		EjbcaWS ejbcaWS = null;
		CryptoProviderTools.installBCProvider();
		System.setProperty("javax.net.ssl.keyStore","C:/Users/mango/Desktop/superadmin.p12");
		System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
		Provider tlsProvider = new TLSProvider();
		Security.addProvider(tlsProvider);
		Security.setProperty("ssl.TrustManagerFactory.algorithm", "AcceptAll");
		System.setProperty("javax.net.ssl.keyStorePassword", "e9a7d6bb701cfba8b0f20de5b8e92d1cf9c1f4f0");
		try 
		{
			KeyManagerFactory.getInstance("NewSunX509");
		} 
		catch (NoSuchAlgorithmException e1) 
		{	
			e1.printStackTrace();
		}
		Security.setProperty("ssl.KeyManagerFactory.algorithm", "NewSunX509");
 
		QName qname = new QName("http://ws.protocol.core.ejbca.org/","EjbcaWSService");
		EjbcaWSService service = null;
		try {
			service = new EjbcaWSService(new URL("https://ejbcatest:8443/ejbca/ejbcaws/ejbcaws?wsdl"), qname);
			ejbcaWS = service.getEjbcaWSPort();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		return ejbcaWS;
	}

採用域名的方式訪問EJBCA服務端,則需要在客戶端所在服務器hosts文件中加入服務器域名和IP。

 

  • 註冊和更新終端實體

 

	/**
	 * 
	* @Title: editUser
	* @Description: 添加用戶實例或更新用戶實體
	* @param @param ejbcaWS
	* @param @param userName
	* @param @param passWord
	* @param @param caName
	* @param @throws ApprovalException_Exception
	* @param @throws AuthorizationDeniedException_Exception
	* @param @throws CADoesntExistsException_Exception
	* @param @throws EjbcaException_Exception
	* @param @throws UserDoesntFullfillEndEntityProfile_Exception
	* @param @throws WaitingForApprovalException_Exception
	* @param @throws IllegalQueryException_Exception
	* @param @throws EndEntityProfileNotFoundException_Exception    參數
	* @return void    返回類型
	* @throws
	 */
public static void  editUser(EjbcaWS ejbcaWS, String userName, String passWord, String caName, String certType) throws ApprovalException_Exception, AuthorizationDeniedException_Exception,
CADoesntExistsException_Exception, EjbcaException_Exception, UserDoesntFullfillEndEntityProfile_Exception,
 WaitingForApprovalException_Exception, IllegalQueryException_Exception, EndEntityProfileNotFoundException_Exception {

  // Test to add a user.
       final UserDataVOWS user = new UserDataVOWS();
       user.setUsername(userName);
       user.setPassword(passWord);
       user.setClearPwd(true);
       user.setSubjectDN("CN=" + userName);
       user.setCaName(caName);
       user.setEmail(null);
       user.setSubjectAltName(null);
       user.setStatus(EndEntityConstants.STATUS_NEW);
       user.setTokenType(certType);
       user.setEndEntityProfileName("EMPTY");
       user.setCertificateProfileName("ENDUSER");
       String pattern = "yyyy-MM-dd HH:mm:ssZZ"; // ISO 8601標準時間格式
       user.setStartTime(DateFormatUtils.format(new Date(),pattern));//證書有效起始日期
       user.setEndTime(DateFormatUtils.format(DateUtils.addDays(new Date(), 100), pattern));//結束日期

       ejbcaWS.editUser(user);


   }
  • 查找終端實體
  • 		/**
    		 * 檢查用戶實體是否存在
    		 * @param ejbcaWS
    		 * @param username
    		 * @return
    		 * @throws Exception
    		 */
    		public static boolean isExist(EjbcaWS ejbcaWS, String username) throws Exception {
    	    UserMatch usermatch = new UserMatch();
    	    usermatch.setMatchwith(UserMatch.MATCH_WITH_USERNAME);
    	    usermatch.setMatchtype(UserMatch.MATCH_TYPE_EQUALS);
    	    usermatch.setMatchvalue(username);
    	    try 
    	    {
    	        List<UserDataVOWS> users = ejbcaWS.findUser(usermatch);
    	        if (users != null && users.size() > 0) 
    	        {
    	            return true;
    	        } 
    	        else 
    	        {
    	            return false;
    	        }
    	    } 
    	    catch (Exception e) 
    	    {
    	        throw new Exception("檢查用戶 " + username + " 是否存在時出錯:" + e.getMessage());
    	    }
    	}

     

  • 吊銷並刪除終端實體

     
        /**
         *
         * @Title: revokeUser
         * @Description: 吊銷證書
         * @param @param ejbcaWS
         * @param @param userName
         * @return void    返回類型
         * @throws
         */
    	public static void revokeUser(EjbcaWS ejbcaWS, String userName) throws Exception 
    	{
    	
    	    // Revoke and delete
    		ejbcaWS.revokeUser(userName, RevokedCertInfo.REVOCATION_REASON_KEYCOMPROMISE, true);
    	
    	    UserMatch usermatch = new UserMatch();
    	    usermatch.setMatchwith(UserMatch.MATCH_WITH_USERNAME);
    	    usermatch.setMatchtype(UserMatch.MATCH_TYPE_EQUALS);
    	    usermatch.setMatchvalue(userName);
    	    List<UserDataVOWS> userdatas = ejbcaWS.findUser(usermatch);
            if (userdatas != null && userdatas.size() > 0) 
            {
                System.out.println("revoke failed!");
            } 
            else 
            {
            	
            	System.out.println("revoke successfully!");
            }	
    	}

     

true表示是否刪除用戶。

 

  • 獲取證書
	public static List<Certificate> findCert(EjbcaWS ejbcaWS, String certName) throws AuthorizationDeniedException_Exception, EjbcaException_Exception
	{
		//第一個入參爲實體名還是證書名?, 	End entity
		   List<Certificate> foundcerts = ejbcaWS.findCerts(certName, true);
		   return foundcerts;
	}
	

獲取某個終端實體的所有證書,true表示只查找有效的證書。

	public static List<Certificate> getLastCAChainCert(EjbcaWS ejbcaWS, String caName) throws AuthorizationDeniedException_Exception, EjbcaException_Exception, CADoesntExistsException_Exception
	{
		   //入參爲CA名 
		   List<Certificate> foundcerts = ejbcaWS.getLastCAChain(caName);
		   return foundcerts;
	}

根據證書16進制序列號及頒發者DN獲取證書。

	public static Certificate getCert(EjbcaWS ejbcaWS, String certSNinHex, String issuerDN) throws AuthorizationDeniedException_Exception, EjbcaException_Exception, CADoesntExistsException_Exception
	{
		//第一個入參爲證書序列號,第二個參數爲頒發者DN
		Certificate foundcerts = ejbcaWS.getCertificate(certSNinHex, issuerDN);
		return foundcerts;
	}
	
  • 申請證書

根據已註冊終端實體申請包含公私鑰及證書的pkcs12文件

/**
	 * 
	* @Title: createCert
	* @Description: 根據用戶實體名稱密碼申請pkcs12證書
	* @param @param ejbcaWS
	* @param @param username
	* @param @param password
	* @param @param path
	* @param @throws Exception    參數
	* @return void    返回類型
	* @throws
	 */
	public static void createCert(EjbcaWS ejbcaWS,String username, String password, String path) throws Exception {
	    FileOutputStream fileOutputStream = null;
	    try {
	        // 創建證書文件
	        KeyStore ksenv = ejbcaWS.pkcs12Req(username, password, null, "2048", AlgorithmConstants.KEYALGORITHM_RSA);
	        java.security.KeyStore ks = KeyStoreHelper.getKeyStore(ksenv.getKeystoreData(), "PKCS12", password);
	        fileOutputStream = new FileOutputStream(path + File.separator + username + ".p12");
	        ks.store(fileOutputStream, password.toCharArray());

	        // 創建密碼文件
	        File pwdFile = new File(path + File.separator + username + ".pwd");
	        pwdFile.createNewFile();
	        BufferedWriter out = new BufferedWriter(new FileWriter(pwdFile));
	        out.write(password);
	        out.flush();
	        out.close();
	    } catch (Exception e) {
	        throw new Exception("用戶  " + username + " 證書創建失敗:" + e.getMessage());
	    } finally {
	        if (fileOutputStream != null) {
	            try {
	                fileOutputStream.close();
	            } catch (IOException e) {
	            }
	        }
	    }
	}

根據CSR請求申請pem格式證書

certificateResponse = ejbcaWS.certificateRequest(userDataVOWS, pkcs10AsBase64, CertificateHelper.CERT_REQ_TYPE_PKCS10, null, CertificateHelper.RESPONSETYPE_CERTIFICATE);

userDataVOWS:用戶信息,用戶名必填

pkcs10AsBase64: CSR請求

同一個用戶可以創建多份證書,與web界面申請證書規則不同。

 

  • 吊銷證書
    /**
     * @param  issuerDN 頒發者DN
     * @param  reason 吊銷證書的原因
     * @return List<Certificate>  查詢到的證書列表
     * @throws
     * @Title: revokeUser
     * @Description: 吊銷證書
     */
    public static void revokeCert(final String issuerDN, final String certificateSN, final int reason) throws Exception {
        //第一個入參爲證書頒發者DN,第二個參數爲證書序列號
        ejbcaWS.revokeCert(issuerDN, certificateSN, reason);

    }

 

  • 獲取證書吊銷列表
   /**
     * 
    * @Title: getCRL
    * @Description: 獲取某個CA的證書吊銷列表
    * @param @param ejbcaWS
    * @param @param caName	CA名稱
    * @param @param delta	是否爲增量
    * @param @return
    * @param @throws CADoesntExistsException_Exception
    * @param @throws EjbcaException_Exception
    * @param @throws CRLException    參數
    * @return int    返回類型
    * @throws
     */
    public static Set<? extends X509CRLEntry> getCRL(EjbcaWS ejbcaWS, final String caName, final boolean delta) throws CADoesntExistsException_Exception, EjbcaException_Exception, CRLException {
        final byte[] crlBytes = ejbcaWS.getLatestCRL(caName, delta);
        if(crlBytes == null)
        {
        	return null;
        }
        final X509CRL crl = CertTools.getCRLfromByteArray(crlBytes);
        final Set crls = crl.getRevokedCertificates();
        final BigInteger crlNumber = CrlExtensions.getCrlNumber(crl);
        System.out.println(crl.getIssuerDN());
        System.out.println(crl.getThisUpdate());
        System.out.println(crl.getNextUpdate());
        System.out.println(crlNumber.intValue());
        X509CRLEntry entry = crl.getRevokedCertificate(new BigInteger("8805361580365352127"));
        if (entry != null) {
            String time = new SimpleDateFormat("yyyyMMddHHmmss").format(entry.getRevocationDate());
            System.out.println(entry.getSerialNumber());
            System.out.println(entry.getRevocationReason());
            System.out.println(entry.getCertificateIssuer());
        }

        
        return crls;
    }

注意CA的CRL列表不能實時更新,有滯後性,一般一天更新一次。

  • 證書驗證
  • 驗證證書鏈
 /**
     * 
    * @Title: verifyEffect
    * @Description: 驗證證書鏈
    * @param @param ejbcaWS
    * @param @param foundcerts
    * @param @return    參數
    * @return boolean    返回類型
    * @throws
     */
    public static boolean verifyEffect(EjbcaWS ejbcaWS,List<Certificate> foundcerts){ 
        boolean effectFlag = false;
        try 
        {
        	System.out.println("foundcerts.size:"+foundcerts.size());
        	java.security.cert.Certificate cert = 
        			(java.security.cert.Certificate) CertificateHelper.getCertificate(foundcerts.get(0).getCertificateData());
			System.out.println("client SubjectDN:"+ CertTools.getSubjectDN(cert));
			System.out.println("client IssuerDN:"+ CertTools.getIssuerDN(cert));
			System.out.println("client SerialNumber:"+ CertTools.getSerialNumber(cert));
			for(int i = 1 ;i < foundcerts.size(); i++)
			{
				java.security.cert.Certificate cert2 = 
						(java.security.cert.Certificate)CertificateHelper.getCertificate(foundcerts.get(i).getCertificateData());
				System.out.println("service SubjectDN:"+ CertTools.getSubjectDN(cert2));
				System.out.println("service IssuerDN:"+ CertTools.getIssuerDN(cert2));
				System.out.println("service SerialNumber:"+ CertTools.getSerialNumber(cert2));
				cert.verify(cert2.getPublicKey());
				effectFlag = true;
			}
        }
        catch (Exception e) {
			System.out.println(e.getMessage());
		}
        return effectFlag;
        
    }

 

  • 驗證證書有效性
    /**
     * <p>
     * 驗證證書是否過期或無效
     * </p>
     * 
     * @param date 日期
     * @param certificate 證書
     * @return
     */
    public static boolean verifyCertificate(Date date,java.security.cert.Certificate certificate) {
        boolean isValid = true;
        try {
            X509Certificate x509Certificate = (X509Certificate)certificate;
            x509Certificate.checkValidity(date);
            System.out.println("cert valid");
        } catch (Exception e) {
        	System.out.println(e.getMessage());
            isValid = false;
        }
        return isValid;
    }

 

  • 驗證簽名
    
    /**
     * <p>
     * 驗證簽名
     * </p>
     * 
     * @param data 已加密數據
     * @param sign 數據簽名[BASE64]
     * @param certificatePath 證書存儲路徑
     * @return
     * @throws Exception
     */
    public static boolean verifySign(byte[] data, String sign, java.security.cert.Certificate certificate) 
            throws Exception {
        // 獲得證書
        X509Certificate x509Certificate = (X509Certificate) certificate;
        // 獲得公鑰
        PublicKey publicKey = x509Certificate.getPublicKey();
        // 構建簽名
        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
        signature.initVerify(publicKey);
        signature.update(data);
//        return signature.verify((sign));
        return true;
    }

 

  1. 遺留問題

1.EJBCA提供了JAVA SDK去調用其Webservice接口,初始化時獲取了EJBCA的EjbcaWSService實例,並需要設置證書。如果使用手機客戶端直接訪問EJBCA的話APP是否能獲得該實例,如何配置證書等。EJBCA是否提供了手機APP集成時需要使用的SDK?

2.獲取Ejbca實例客戶端需要配置超級管理員證書,該證書擁有刪除用戶,修改用戶,註冊CA等一系列敏感權限,如果手機直接集成的話會存在危險。目前看可以在管理員界面對該證書的權限進行配置。

3.部署環境時需要修改ejbca-setup.sh腳本中的httpsserver_hostname爲部署所在服務器的主機名稱,這樣在生成EJBCA HTTPS服務端證書時證書Domain Name與服務器域名相同,客戶端纔可以通過域名正常訪問。如果通過IP訪問則還需要修改ejbca-setup.sh腳本。

後面我會把操作的代碼打包放到資源裏面,大家可以下載

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章