欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

純Java實(shí)現(xiàn)數(shù)字證書(shū)生成簽名的簡(jiǎn)單實(shí)例

 更新時(shí)間:2016年08月31日 09:55:37   投稿:jingxian  
下面小編就為大家?guī)?lái)一篇純Java實(shí)現(xiàn)數(shù)字證書(shū)生成簽名的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

package com.ylsoft.cert;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Vector;

import sun.misc.BASE64Encoder;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
import sun.security.x509.CertAndKeyGen;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateExtensions;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateValidity;
import sun.security.x509.CertificateVersion;
import sun.security.x509.CertificateX509Key;
import sun.security.x509.ExtendedKeyUsageExtension;
import sun.security.x509.Extension;
import sun.security.x509.KeyIdentifier;
import sun.security.x509.KeyUsageExtension;
import sun.security.x509.SubjectKeyIdentifierExtension;
import sun.security.x509.X500Name;
import sun.security.x509.X500Signer;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;

/**
 * 首先生成CA的根證書(shū),然后有CA的根證書(shū)簽署生成ScriptX的證書(shū)
 * 
 * @author Administrator
 * 
 */
public class GenX509Cert {
	/** 提供強(qiáng)加密隨機(jī)數(shù)生成器 (RNG)* */
	private SecureRandom sr;

	public GenX509Cert() throws NoSuchAlgorithmException,
			NoSuchProviderException {
		// 返回實(shí)現(xiàn)指定隨機(jī)數(shù)生成器 (RNG) 算法的 SecureRandom 對(duì)象。
		sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
	}

	public void createCert(X509Certificate certificate, PrivateKey rootPrivKey,
			KeyPair kp) throws CertificateException, IOException,
			InvalidKeyException, NoSuchAlgorithmException,
			NoSuchProviderException, SignatureException {

		// X.509 v1 證書(shū)的抽象類(lèi)。此類(lèi)提供了一種訪問(wèn) X.509 v1 證書(shū)所有屬性的標(biāo)準(zhǔn)方式。
		byte certbytes[] = certificate.getEncoded();

		// The X509CertImpl class represents an X.509 certificate.
		X509CertImpl x509certimpl = new X509CertImpl(certbytes);

		// The X509CertInfo class represents X.509 certificate information.
		X509CertInfo x509certinfo = (X509CertInfo) x509certimpl
				.get("x509.info");

		// This class defines the X509Key attribute for the Certificate.
		x509certinfo.set("key", new CertificateX509Key(kp.getPublic()));

		// This class defines the Extensions attribute for the Certificate
		CertificateExtensions certificateextensions = new CertificateExtensions();

		certificateextensions.set("SubjectKeyIdentifier",
				new SubjectKeyIdentifierExtension((new KeyIdentifier(kp
						.getPublic())).getIdentifier()));

		x509certinfo.set("extensions", certificateextensions);

		// 設(shè)置issuer域
		X500Name issuer = new X500Name(
				"CN=RootCA,OU=hackwp,O=wp,L=BJ,S=BJ,C=CN");
		x509certinfo.set("issuer.dname", issuer);

		// Constructs a name from a conventionally formatted string, such as
		// "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US". (RFC 1779 or RFC
		// 2253 style).
		X500Name subject = new X500Name(
				"CN=scriptx, OU=wps, O=wps, L=BJ, ST=BJ, C=CN");

		x509certinfo.set("subject.dname", subject);

		// 此 Signature 類(lèi)用來(lái)為應(yīng)用程序提供數(shù)字簽名算法功能。返回實(shí)現(xiàn)指定簽名算法的 Signature 對(duì)象。
		Signature signature = Signature.getInstance("MD5WithRSA");

		// 初始化這個(gè)用于簽名的對(duì)象。如果使用其他參數(shù)再次調(diào)用此方法,此調(diào)用的結(jié)果將無(wú)效。
		signature.initSign(kp.getPrivate());

		// This class provides a binding between a Signature object and an
		// authenticated X.500 name (from an X.509 certificate chain), which is
		// needed in many public key signing applications.
		X500Signer signer = new X500Signer(signature, issuer);

		// This class identifies algorithms, such as cryptographic transforms,
		// each of which may be associated with parameters.
		AlgorithmId algorithmid = signer.getAlgorithmId();

		// This class defines the AlgorithmId for the Certificate.
		x509certinfo
				.set("algorithmID", new CertificateAlgorithmId(algorithmid));

		// 開(kāi)始時(shí)間
		Date bdate = new Date();

		// 結(jié)束時(shí)間
		Date edate = new Date();

		// 天 小時(shí) 分 秒 毫秒
		edate.setTime(bdate.getTime() + 3650 * 24L * 60L * 60L * 1000L);

		// validity為有效時(shí)間長(zhǎng)度 單位為秒,This class defines the interval for which the
		// certificate is valid.證書(shū)的有效時(shí)間
		CertificateValidity certificatevalidity = new CertificateValidity(
				bdate, edate);

		x509certinfo.set("validity", certificatevalidity);

		// This class defines the SerialNumber attribute for the Certificate.
		// 設(shè)置有效期域(包含開(kāi)始時(shí)間和到期時(shí)間)域名等同與x509certinfo.VALIDITY
		x509certinfo.set("serialNumber", new CertificateSerialNumber(
				(int) (new Date().getTime() / 1000L)));

		// 設(shè)置序列號(hào)域,This class defines the version of the X509 Certificate.
		CertificateVersion cv = new CertificateVersion(CertificateVersion.V3);

		x509certinfo.set(X509CertInfo.VERSION, cv);

		// 設(shè)置版本號(hào) 只有v1 ,v2,v3這幾個(gè)合法值
		/**
		 * 以上是證書(shū)的基本信息 如果要添加用戶擴(kuò)展信息 則比較麻煩 首先要確定version必須是v3否則不行 然后按照以下步驟
		 */
		ObjectIdentifier oid = new ObjectIdentifier(new int[] { 2, 5, 29, 15 });

		// 生成擴(kuò)展域的id 是個(gè)int數(shù)組 第1位最大2 第2位最大39 最多可以幾位不明....
		String userData = "Digital Signature, Non-Repudiation, Key Encipherment, Data Encipherment (f0)";

		byte l = (byte) userData.length();// 數(shù)據(jù)總長(zhǎng)17位

		byte f = 0x04;

		byte[] bs = new byte[userData.length() + 2];

		bs[0] = f;

		bs[1] = l;

		for (int i = 2; i < bs.length; i++) {
			bs[i] = (byte) userData.charAt(i - 2);
		}

		Extension ext = new Extension(oid, true, bs);

		// 生成一個(gè)extension對(duì)象 參數(shù)分別為 oid,是否關(guān)鍵擴(kuò)展,byte[]型的內(nèi)容值
		// 其中內(nèi)容的格式比較怪異 第一位是flag 這里取4暫時(shí)沒(méi)出錯(cuò) 估計(jì)用來(lái)說(shuō)明數(shù)據(jù)的用處的 第2位是后面的實(shí)際數(shù)據(jù)的長(zhǎng)度,然后就是數(shù)據(jù)
		// 密鑰用法
		KeyUsageExtension keyUsage = new KeyUsageExtension();

		keyUsage.set(KeyUsageExtension.DIGITAL_SIGNATURE, true);

		keyUsage.set(KeyUsageExtension.NON_REPUDIATION, true);

		keyUsage.set(KeyUsageExtension.KEY_ENCIPHERMENT, true);

		keyUsage.set(KeyUsageExtension.DATA_ENCIPHERMENT, true);

		// 增強(qiáng)密鑰用法
ObjectIdentifier ekeyOid = new ObjectIdentifier(new int[] { 1, 3, 6, 1,
				5, 5, 7, 3, 3 });

Vector<ObjectIdentifier> vkeyOid = new Vector<ObjectIdentifier>();

vkeyOid.add(ekeyOid);

		ExtendedKeyUsageExtension exKeyUsage = new ExtendedKeyUsageExtension(
				vkeyOid);

		CertificateExtensions exts = new CertificateExtensions();

		exts.set("keyUsage", keyUsage);

		exts.set("extendedKeyUsage", exKeyUsage);

		// 如果有多個(gè)extension則都放入CertificateExtensions 類(lèi)中,
		x509certinfo.set(X509CertInfo.EXTENSIONS, exts);
		// 設(shè)置extensions域

		X509CertImpl x509certimpl1 = new X509CertImpl(x509certinfo);

		x509certimpl1.sign(rootPrivKey, "MD5WithRSA");
		// 使用另一個(gè)證書(shū)的私鑰來(lái)簽名此證書(shū) 這里使用 md5散列 用rsa來(lái)加密

		BASE64Encoder base64 = new BASE64Encoder();

		FileOutputStream fos = new FileOutputStream(new File("f:\\ScriptX.crt"));

		base64.encodeBuffer(x509certimpl1.getEncoded(), fos);

		try {
			Certificate[] certChain = { x509certimpl1 };

			savePfx("scriptx", kp.getPrivate(), "123456", certChain,
					"f:\\ScriptX.pfx");

			FileInputStream in = new FileInputStream("F:\\ScriptX.pfx");

			KeyStore inputKeyStore = KeyStore.getInstance("pkcs12");

			inputKeyStore.load(in, "123456".toCharArray());

			Certificate cert = inputKeyStore.getCertificate("scriptx");

			System.out.print(cert.getPublicKey());

			PrivateKey privk = (PrivateKey) inputKeyStore.getKey("scriptx",
					"123456".toCharArray());

			FileOutputStream privKfos = new FileOutputStream(new File(
					"f:\\ScriptX.pvk"));

			privKfos.write(privk.getEncoded());

			System.out.print(privk);
			// base64.encode(key.getEncoded(), privKfos);

			in.close();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// 生成文件
		x509certimpl1.verify(certificate.getPublicKey(), null);

	}

	/**
	 * 保存此根證書(shū)信息KeyStore Personal Information Exchange
	 * 
	 * @param alias
	 * @param privKey
	 * @param pwd
	 * @param certChain
	 * @param filepath
	 * @throws Exception
	 */
	public void savePfx(String alias, PrivateKey privKey, String pwd,
			Certificate[] certChain, String filepath) throws Exception {
		// 此類(lèi)表示密鑰和證書(shū)的存儲(chǔ)設(shè)施。
		// 返回指定類(lèi)型的 keystore 對(duì)象。此方法從首選 Provider 開(kāi)始遍歷已注冊(cè)安全提供者列表。返回一個(gè)封裝 KeyStoreSpi
		// 實(shí)現(xiàn)的新 KeyStore 對(duì)象,該實(shí)現(xiàn)取自第一個(gè)支持指定類(lèi)型的 Provider。
		KeyStore outputKeyStore = KeyStore.getInstance("pkcs12");

		System.out.println("KeyStore類(lèi)型:" + outputKeyStore.getType());

		// 從給定輸入流中加載此 KeyStore。可以給定一個(gè)密碼來(lái)解鎖 keystore(例如,駐留在硬件標(biāo)記設(shè)備上的 keystore)或檢驗(yàn)
		// keystore 數(shù)據(jù)的完整性。如果沒(méi)有指定用于完整性檢驗(yàn)的密碼,則不會(huì)執(zhí)行完整性檢驗(yàn)。如果要?jiǎng)?chuàng)建空
		// keystore,或者不能從流中初始化 keystore,則傳遞 null 作為 stream 的參數(shù)。注意,如果此 keystore
		// 已經(jīng)被加載,那么它將被重新初始化,并再次從給定輸入流中加載。
		outputKeyStore.load(null, pwd.toCharArray());

		// 將給定密鑰(已經(jīng)被保護(hù))分配給給定別名。如果受保護(hù)密鑰的類(lèi)型為
		// java.security.PrivateKey,則它必須附帶證明相應(yīng)公鑰的證書(shū)鏈。如果底層 keystore 實(shí)現(xiàn)的類(lèi)型為
		// jks,則必須根據(jù) PKCS #8 標(biāo)準(zhǔn)中的定義將 key 編碼為
		// EncryptedPrivateKeyInfo。如果給定別名已經(jīng)存在,則與別名關(guān)聯(lián)的 keystore
		// 信息將被給定密鑰(還可能包括證書(shū)鏈)重寫(xiě)。
		outputKeyStore
				.setKeyEntry(alias, privKey, pwd.toCharArray(), certChain);

		// KeyStore.PrivateKeyEntry pke=new
		// KeyStore.PrivateKeyEntry(kp.getPrivate(),certChain);
		// KeyStore.PasswordProtection password=new
		// KeyStore.PasswordProtection("123456".toCharArray());
		// outputKeyStore.setEntry("scriptx", pke, password);

		FileOutputStream out = new FileOutputStream(filepath);

		// 將此 keystore 存儲(chǔ)到給定輸出流,并用給定密碼保護(hù)其完整性。
		outputKeyStore.store(out, pwd.toCharArray());

		out.close();
	}

	public void saveJks(String alias, PrivateKey privKey, String pwd,
			Certificate[] certChain, String filepath) throws Exception {

		KeyStore outputKeyStore = KeyStore.getInstance("jks");

		System.out.println(outputKeyStore.getType());

		outputKeyStore.load(null, pwd.toCharArray());

		outputKeyStore
				.setKeyEntry(alias, privKey, pwd.toCharArray(), certChain);

		// KeyStore.PrivateKeyEntry pke=new
		// KeyStore.PrivateKeyEntry(kp.getPrivate(),certChain);
		// KeyStore.PasswordProtection password=new
		// KeyStore.PasswordProtection("123456".toCharArray());
		// outputKeyStore.setEntry("scriptx", pke, password);

		FileOutputStream out = new FileOutputStream(filepath);

		outputKeyStore.store(out, pwd.toCharArray());

		out.close();
	}

	/**
	 * 頒布根證書(shū),自己作為CA
	 * 
	 * @throws NoSuchAlgorithmException
	 * @throws NoSuchProviderException
	 * @throws InvalidKeyException
	 * @throws IOException
	 * @throws CertificateException
	 * @throws SignatureException
	 * @throws UnrecoverableKeyException
	 */
	public void createRootCA() throws NoSuchAlgorithmException,
			NoSuchProviderException, InvalidKeyException, IOException,
			CertificateException, SignatureException, UnrecoverableKeyException {

		// 參數(shù)分別為公鑰算法、簽名算法 providername(因?yàn)椴恢来_切的 只好使用null 既使用默認(rèn)的provider)
		// Generate a pair of keys, and provide access to them.
		CertAndKeyGen cak = new CertAndKeyGen("RSA", "MD5WithRSA", null);

		// Sets the source of random numbers used when generating keys.
		cak.setRandom(sr);

		// Generates a random public/private key pair, with a given key size.
		cak.generate(1024);

		// Constructs a name from a conventionally formatted string, such as
		// "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US". (RFC 1779 or RFC
		// 2253 style)
		X500Name subject = new X500Name(
				"CN=RootCA,OU=hackwp,O=wp,L=BJ,S=BJ,C=CN");

		// Returns a self-signed X.509v3 certificate for the public key. The
		// certificate is immediately valid. No extensions.
		// Such certificates normally are used to identify a "Certificate
		// Authority" (CA). Accordingly, they will not always be accepted by
		// other parties. However, such certificates are also useful when you
		// are bootstrapping your security infrastructure, or deploying system
		// prototypes.自簽名的根證書(shū)
		X509Certificate certificate = cak.getSelfCertificate(subject,
				new Date(), 3650 * 24L * 60L * 60L);

		X509Certificate[] certs = { certificate };

		try {

			savePfx("RootCA", cak.getPrivateKey(), "123456", certs,
					"f:\\RootCa.pfx");

		} catch (Exception e) {

			e.printStackTrace();

		}

		// 后一個(gè)long型參數(shù)代表從現(xiàn)在開(kāi)始的有效期 單位為秒(如果不想從現(xiàn)在開(kāi)始算 可以在后面改這個(gè)域)
		BASE64Encoder base64 = new BASE64Encoder();

		FileOutputStream fos = new FileOutputStream(new File("f:\\RootCa.crt"));

		// fos.write(certificate.getEncoded());

		// 生成(保存)cert文件 base64加密 當(dāng)然也可以不加密
		base64.encodeBuffer(certificate.getEncoded(), fos);

		fos.close();

	}

	public void signCert() throws NoSuchAlgorithmException,
			CertificateException, IOException, UnrecoverableKeyException,
			InvalidKeyException, NoSuchProviderException, SignatureException {

		try {

			KeyStore ks = KeyStore.getInstance("pkcs12");

			FileInputStream ksfis = new FileInputStream("f:\\RootCa.pfx");

			char[] storePwd = "123456".toCharArray();

			char[] keyPwd = "123456".toCharArray();

			// 從給定輸入流中加載此 KeyStore。
			ks.load(ksfis, storePwd);

			ksfis.close();

			// 返回與給定別名關(guān)聯(lián)的密鑰(私鑰),并用給定密碼來(lái)恢復(fù)它。必須已經(jīng)通過(guò)調(diào)用 setKeyEntry,或者以
			// PrivateKeyEntry
			// 或 SecretKeyEntry 為參數(shù)的 setEntry 關(guān)聯(lián)密鑰與別名。
			PrivateKey privK = (PrivateKey) ks.getKey("RootCA", keyPwd);

			// 返回與給定別名關(guān)聯(lián)的證書(shū)。如果給定的別名標(biāo)識(shí)通過(guò)調(diào)用 setCertificateEntry 創(chuàng)建的條目,或者通過(guò)調(diào)用以
			// TrustedCertificateEntry 為參數(shù)的 setEntry
			// 創(chuàng)建的條目,則返回包含在該條目中的可信證書(shū)。如果給定的別名標(biāo)識(shí)通過(guò)調(diào)用 setKeyEntry 創(chuàng)建的條目,或者通過(guò)調(diào)用以
			// PrivateKeyEntry 為參數(shù)的 setEntry 創(chuàng)建的條目,則返回該條目中證書(shū)鏈的第一個(gè)元素。
			X509Certificate certificate = (X509Certificate) ks
					.getCertificate("RootCA");

			createCert(certificate, privK, genKey());

		} catch (KeyStoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public KeyPair genKey() throws NoSuchAlgorithmException {

		KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");

		kpg.initialize(1024, sr);

		System.out.print(kpg.getAlgorithm());

		KeyPair kp = kpg.generateKeyPair();

		return kp;
	}

	public static void main(String[] args) {

		try {

			GenX509Cert gcert = new GenX509Cert();

			gcert.createRootCA();

			gcert.signCert();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

以上這篇純Java實(shí)現(xiàn)數(shù)字證書(shū)生成簽名的簡(jiǎn)單實(shí)例就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java FTPClient連接池的實(shí)現(xiàn)

    Java FTPClient連接池的實(shí)現(xiàn)

    這篇文章主要介紹了Java FTPClient連接池的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • Java設(shè)計(jì)模式之中介者模式

    Java設(shè)計(jì)模式之中介者模式

    這篇文章介紹了Java設(shè)計(jì)模式之中介者模式,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • Java web velocity分頁(yè)宏示例

    Java web velocity分頁(yè)宏示例

    這篇文章主要介紹了Java web velocity分頁(yè)宏示例,需要的朋友可以參考下
    2014-03-03
  • Java異步判斷線程池所有任務(wù)是否執(zhí)行完成的操作方法

    Java異步判斷線程池所有任務(wù)是否執(zhí)行完成的操作方法

    這篇文章主要介紹了Java異步判斷線程池所有任務(wù)是否執(zhí)行完成的方法,在這個(gè)示例中,我使用了傳統(tǒng)的匿名內(nèi)部類(lèi)來(lái)創(chuàng)建Callable任務(wù)(同時(shí)也提供了Lambda表達(dá)式的注釋),以便與各種Java版本兼容,需要的朋友可以參考下
    2024-07-07
  • java編寫(xiě)屬于自己的線程池

    java編寫(xiě)屬于自己的線程池

    這篇文章主要為大家詳細(xì)介紹了java編寫(xiě)屬于自己的線程池,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 基于IDEA2018卡死不動(dòng)的解決方式(好用)

    基于IDEA2018卡死不動(dòng)的解決方式(好用)

    這篇文章主要介紹了基于IDEA2018卡死不動(dòng)的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Java中前端傳參含有“+”“=”等特殊字符處理方式

    Java中前端傳參含有“+”“=”等特殊字符處理方式

    這篇文章主要介紹了Java中前端傳參含有“+”“=”等特殊字符處理,比如“+”如果不經(jīng)過(guò)處理,傳到Java后臺(tái)之后,就變成空格了,“=”就直接沒(méi)了,本文對(duì)這一問(wèn)題給大家詳細(xì)講解,需要的朋友可以參考下
    2023-10-10
  • 如何在mybatis中向BLOB字段批量插入數(shù)據(jù)

    如何在mybatis中向BLOB字段批量插入數(shù)據(jù)

    這篇文章主要介紹了如何在mybatis中向BLOB字段批量插入數(shù)據(jù)的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-10-10
  • Java中s.charAt(index)用于提取字符串s中的特定字符操作

    Java中s.charAt(index)用于提取字符串s中的特定字符操作

    這篇文章主要介紹了Java中s.charAt(index)用于提取字符串s中的特定字符操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-10-10
  • Spring中@Value使用詳解及SPEL表達(dá)式

    Spring中@Value使用詳解及SPEL表達(dá)式

    這篇文章主要介紹了Spring中@Value使用詳解及SPEL表達(dá)式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09

最新評(píng)論