天天看點

加密機制的發展(JCE/JCA)

一、對稱密鑰-------最原始的加密解密

      對稱密鑰最好的了解就是:加密和解密用同一個密鑰,典型的例子就是凱撒密碼,他的基本思想是:通過把字母移動一定的位數來實作加密和解密。例如,如果密匙是把明文字母的位數向後移動三位,那麼明文字母B就變成了密文的E,依次類推,X将變成A,Y變成B,Z變成C,由此可見,位數就是凱撒密碼加密和解密的密鑰。 常見的對稱加密算法有DES、3DES、IDEA、AES,這裡用AES寫個例子

byte[] plain = "password".getBytes();
		System.out.println("原文:"+Arrays.toString(plain));
		
		//生成AES Key
		KeyGenerator generator = KeyGenerator.getInstance("AES");
		SecretKey aesKey = generator.generateKey(); 
		
		//擷取AES的Cipher
		Cipher cipher = Cipher.getInstance("AES");
		//初始化模式  加密
		cipher.init(Cipher.ENCRYPT_MODE,aesKey);
		cipher.update(plain);
		byte[] result1 = cipher.doFinal();
		System.out.println("加密結果:"+Arrays.toString(result1));
		
		//解密
		cipher.init(Cipher.DECRYPT_MODE, aesKey);
		cipher.update(result1);
		byte[] result2 = cipher.doFinal();
		
		System.out.println("解密結果:"+Arrays.toString(result2));
		System.out.println("原文比較:"+Arrays.equals(result2, plain));
           

 結果:

原文:[112, 97, 115, 115, 119, 111, 114, 100]
加密結果:[-31, -16, -80, 28, -127, -14, -128, -22, -57, -117, -86, -44, -119, -125, -80, -11]
解密結果:[112, 97, 115, 115, 119, 111, 114, 100]
原文比較:true
           

 二、非對稱密鑰加密

 又名“公開密鑰加密算法”,對稱密鑰的缺點就是當得到那個key之後就不安全了,非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey);公開密鑰與私有密鑰是一對,如果用公開密鑰對資料進行加密,隻有用對應的私有密鑰才能解密;如果用私有密鑰對資料進行加密,那麼隻有用對應的公開密鑰才能 解密。因為加密和解密使用的是兩個不同的密鑰,是以這種算法叫作非對稱加密算法。 非對稱加密算法實作機密資訊交換的基本過程是:甲方生成一對密鑰并将其中的一把作為公用密鑰向其它方公開;得到該公用密鑰的乙方使用該密鑰對機密資訊進行 加密後再發送給甲方;甲方再用自己儲存的另一把專用密鑰對加密後的資訊進行解密,說簡單了就是publicKey和privateKey是一對,可以根據一定對應的關系得到另一半,比如y=3x+10;可以把x和y當做一個非對稱密鑰;典型的算法有 RSA、Elgamal、背包算法、Rabin、D-H、ECC(橢圓曲線加密算法)

//B給A發送的資訊
		byte[] plain = "password".getBytes();
		System.out.println("原文:"+Arrays.toString(plain));
		
		//A生成一個密鑰對
		KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
		generator.initialize(1024);
		KeyPair keyPair = generator.generateKeyPair();
		//A把公鑰公開
		PublicKey publicKey = keyPair.getPublic();
		//A自己儲存好私鑰
		PrivateKey privateKey = keyPair.getPrivate();
		System.out.println("公鑰:"+publicKey);
		System.out.println("私鑰:"+privateKey);
		
		Cipher cipher = Cipher.getInstance("RSA");
		//B用A的公鑰把資訊加密後發給A
		cipher.init(Cipher.ENCRYPT_MODE,publicKey);
		cipher.update(plain);
		byte[] result1 = cipher.doFinal();
		System.out.println("加密結果:"+Arrays.toString(result1));
		
		//A得到B發過來的資訊後用自己的私鑰進行解密
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		cipher.update(result1);
		byte[] result2 = cipher.doFinal();
		System.out.println("解密結果:"+Arrays.toString(result2));
		
		System.out.println("原文比較:"+Arrays.equals(result2, plain));
           

三、簽名算法的産生

當B給A發資訊“我給你打過去了1000元”,被C截取,C把資訊篡改為“你給我打1000元”發給A,這時A并不知道資訊已經被C修改過,還認為是B發過來的資訊,于是就給B打了了一千元!!!這樣很不安全,于是就有了簽名算法的産生,就是B把自己的資訊進行簽名(相當于蓋個章),這時A就很容易識别資訊沒有修改過

//B給A發送的資訊
		byte[] plain = "password".getBytes();
		System.out.println("原文:"+Arrays.toString(plain));
		
		KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
		generator.initialize(1024);
		
		//A生成一個密鑰對
		KeyPair aKeyPair = generator.generateKeyPair();
		//A把公鑰公開
		PublicKey aPublicKey = aKeyPair.getPublic();
		//A自己儲存好私鑰
		PrivateKey aPrivateKey = aKeyPair.getPrivate();
		System.out.println("A的公鑰:"+aPublicKey);
		System.out.println("A的私鑰:"+aPrivateKey);
		
		
		
		//B生成的一個密鑰對
		KeyPair bKeyPair = generator.generateKeyPair();
		//B的公鑰
		PublicKey bPublicKey = bKeyPair.getPublic();
		//B的私鑰
		PrivateKey bPrivateKey = bKeyPair.getPrivate();
		System.out.println("B的公鑰:"+aPublicKey);
		System.out.println("B的私鑰:"+aPrivateKey);
		
		//第一步B操作
		//加密
		Cipher cipher = Cipher.getInstance("RSA");
		//B用A的公鑰把資訊加密
		cipher.init(Cipher.ENCRYPT_MODE,aPublicKey);
		cipher.update(plain);
		byte[] result1 = cipher.doFinal();
		System.out.println("加密結果:"+Arrays.toString(result1));
		
		//把原文做一個資訊摘要
		MessageDigest digest = MessageDigest.getInstance("SHA1");
		digest.update(plain);
		byte[] hash = digest.digest();
		
		//簽名
		Signature signature = Signature.getInstance("SHA1withRSA");
		//B用自己的私鑰對資訊簽名
		signature.initSign(bPrivateKey);
		signature.update(hash);
		byte[] signByte = signature.sign();
		
		
		//B把簽名結果signByte和加密結果result1一起發送給A
		
		
		//第二步A操作
		//A得到B發過來的資訊後用自己的私鑰進行解密
		cipher.init(Cipher.DECRYPT_MODE, aPrivateKey);
		cipher.update(result1);
		byte[] result2 = cipher.doFinal();
		System.out.println("解密結果:"+Arrays.toString(result2));
		System.out.println("原文比較:"+Arrays.equals(result2, plain));
		
		//把解密的結果進行資訊摘要
		digest.reset();
		digest.update(result2);
		byte[] hash2 = digest.digest();
		
		//比較兩次摘要的結果是否一緻
		signature.initVerify(bPublicKey);
		signature.update(hash2);
		boolean b = signature.verify(signByte);
		System.out.println("驗證簽名結果:"+b);
           

 輸出結果:

原文:[112, 97, 115, 115, 119, 111, 114, 100]
A的公鑰:Sun RSA public key, 1024 bits
  modulus: 102539187515284730067999644651029605499155012515018193956264041032712042245940835316344273183723893202553260620259419073173666324899506874839042020529427319710557325844173671303708388890745691502555168128969439923835578562447745704520780863763243855014463806372707187192860875656087947756935417785902707236111
  public exponent: 65537
A的私鑰:Sun RSA private CRT key, 1024 bits
  modulus:          102539187515284730067999644651029605499155012515018193956264041032712042245940835316344273183723893202553260620259419073173666324899506874839042020529427319710557325844173671303708388890745691502555168128969439923835578562447745704520780863763243855014463806372707187192860875656087947756935417785902707236111
  public exponent:  65537
  private exponent: 60911441005196298675210860520152487475587893742804420539715204868158635834364140252080487347842514705717396115283266611802859509813734259187310143906970630220845991871368219715775743370250594182491008406793730989043642353446311784524222989887596013598331427135510011783066371889013758659686178307766978183449
  prime p:          10952081096215932838370494255560322806855249435195895093365419505271086940019997647808658906999895561701787208823891331735140003545850379556296491139129413
  prime q:          9362529971651978753471787637908879302644842060847691470500031927265884682918029490403020820378706946420421723488722740493564033473307756625205829732314947
  prime exponent p: 2815686015382795251441238654682635442157927548310353486246150315765331703501791970458337945344480832493300161458012192325028211845889086243557678551096197
  prime exponent q: 7759084034214778247971576391622212819698022595645523396512935197912507358947265448712319297758956167980413584201946964377785729435826543564472042208999827
  crt coefficient:  4074873801299390551066760636369955957669465077600980966897569652009774826505084817566977483734221289258517186275849939327186461536804759994864093579045356
B的公鑰:Sun RSA public key, 1024 bits
  modulus: 102539187515284730067999644651029605499155012515018193956264041032712042245940835316344273183723893202553260620259419073173666324899506874839042020529427319710557325844173671303708388890745691502555168128969439923835578562447745704520780863763243855014463806372707187192860875656087947756935417785902707236111
  public exponent: 65537
B的私鑰:Sun RSA private CRT key, 1024 bits
  modulus:          102539187515284730067999644651029605499155012515018193956264041032712042245940835316344273183723893202553260620259419073173666324899506874839042020529427319710557325844173671303708388890745691502555168128969439923835578562447745704520780863763243855014463806372707187192860875656087947756935417785902707236111
  public exponent:  65537
  private exponent: 60911441005196298675210860520152487475587893742804420539715204868158635834364140252080487347842514705717396115283266611802859509813734259187310143906970630220845991871368219715775743370250594182491008406793730989043642353446311784524222989887596013598331427135510011783066371889013758659686178307766978183449
  prime p:          10952081096215932838370494255560322806855249435195895093365419505271086940019997647808658906999895561701787208823891331735140003545850379556296491139129413
  prime q:          9362529971651978753471787637908879302644842060847691470500031927265884682918029490403020820378706946420421723488722740493564033473307756625205829732314947
  prime exponent p: 2815686015382795251441238654682635442157927548310353486246150315765331703501791970458337945344480832493300161458012192325028211845889086243557678551096197
  prime exponent q: 7759084034214778247971576391622212819698022595645523396512935197912507358947265448712319297758956167980413584201946964377785729435826543564472042208999827
  crt coefficient:  4074873801299390551066760636369955957669465077600980966897569652009774826505084817566977483734221289258517186275849939327186461536804759994864093579045356
加密結果:[112, 15, 49, -69, -36, -19, -88, -105, 21, -64, -43, 114, 47, 127, -63, 114, 35, 110, 25, 18, 17, 52, 69, -104, 109, 38, 12, -99, 37, 69, 63, 28, -123, -71, 82, -63, 30, -46, -82, 80, 78, 2, 94, -29, -23, -69, 94, -125, 109, 125, -68, -14, -114, -112, 7, 113, 71, 121, -11, -27, -105, 79, -99, 26, 56, 87, -8, 52, 73, -18, -59, -54, 85, 57, 6, 26, -74, 72, -14, 61, 4, 49, -115, 91, 43, -81, -105, 7, 126, -99, -65, 73, 66, 15, 43, -23, 113, 66, -56, -15, 73, 13, 46, -61, -125, -21, 16, -72, 38, -46, 33, 51, 72, 122, 12, -63, 86, -41, 112, -48, 28, 21, 29, 30, 19, -8, 124, 78]
解密結果:[112, 97, 115, 115, 119, 111, 114, 100]
原文比較:true
驗證簽名結果:true
           

 四、資訊摘要

在三中并不是對原文進行簽名而是對原文的哈希值進行簽名,為什麼呢?

1、無論輸入的消息有多長,計算出來的消息摘要的長度總是固定的。例如應用MD5算法摘要的消息有128個比特位,用SHA-1算法摘要的消息最終有160比特位的輸出,SHA-1的變體可以産生192比特位和256比特位的消息摘要。一般認為,摘要的最終輸出越長,該摘要算法就越安全。這樣就避免了原文過長簽名的效率問題

2、消息摘要看起來是“随機的”。這些比特看上去是胡亂的雜湊在一起的。可以用大量的輸入來檢驗其輸出是否相同,一般,不同的輸入會有不同的輸出,而且輸出的摘要消息可以通過随機性檢驗。但是,一個摘要并不是真正随機的,因為用相同的算法對相同的消息求兩次摘要,其結果必然相同;而若是真正随機的,則無論如何都是無法重制的。是以消息摘要是“僞随機的”。

3、一般地,隻要輸入的消息不同,對其進行摘要以後産生的摘要消息也必不相同;但相同的輸入必會産生相同的輸出。這正是好的消息摘要算法所具有的性質:輸入改變了,輸出也就改變了;兩條相似的消息的摘要确不相近,甚至會大相徑庭

4、消息摘要函數是無陷門的單向函數,即隻能進行正向的資訊摘要,而無法從摘要中恢複出任何的消息,甚至根本就找不到任何與原資訊相關的資訊。當然,可以采用 強力攻擊的方法,即嘗試每一個可能的資訊,計算其摘要,看看是否與已有的摘要相同,如果這樣做,最終肯定會恢複出摘要的消息。但實際上,要得到的資訊可能 是無窮 個消息之一,是以這種強力攻擊幾乎是無效的。

5、好的摘要算法,沒有人能從中找到“碰撞”,雖然“碰撞”是肯定存在的。即對于給定的一個摘要,不可能找到一條資訊使其摘要正好是給定的。或者說,無法找到兩條消息,是它們的摘要相同

常見的資訊摘要算法SHA1、MD5(已破解、慎用)

byte[] plain = "password".getBytes();
		MessageDigest digest = MessageDigest.getInstance("MD5");
		digest.update(plain);
		byte[] result1 = digest.digest();
		
		plain = "possword".getBytes();
		digest.reset();
		digest.update(plain);
		byte[] result2 = digest.digest();
		
		System.out.println(Arrays.toString(result1));
		System.out.println(Arrays.toString(result2));
           

 輸出結果:

[95, 77, -52, 59, 90, -89, 101, -42, 29, -125, 39, -34, -72, -126, -49, -103]
[112, 68, -103, 81, 72, -7, 93, 85, 65, -122, 71, -65, -74, 95, -89, -93]
           

 五、一種更為安全的加密方式

在三中A的密鑰對進行了加密和解密,B的密鑰對進行了簽名和驗證簽名,這樣會造成一種情況,當A的密鑰對被C截取,C就可以得到B的發送過來的資訊,這時就需要在B在給A發資訊時再産生一個密鑰對,用A的公鑰對這個會話密鑰進行加密,當A得到時在用A的私鑰解密,但是這時簽名隻是用B的,二A的密鑰對隻負責解密開會話密鑰即可

// B給A發送的資訊
		byte[] plain = "password".getBytes();
		System.out.println("原文:" + Arrays.toString(plain));

		KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
		generator.initialize(1024);

		// A生成一個密鑰對
		KeyPair aKeyPair = generator.generateKeyPair();
		// A把公鑰公開
		PublicKey aPublicKey = aKeyPair.getPublic();
		// A自己儲存好私鑰
		PrivateKey aPrivateKey = aKeyPair.getPrivate();
		System.out.println("A的公鑰:" + aPublicKey);
		System.out.println("A的私鑰:" + aPrivateKey);

		// B産生的會話密鑰(對稱的)
		KeyGenerator generator2 = KeyGenerator.getInstance("AES");
		SecretKey secretKey = generator2.generateKey();
		System.out.println("B的會話密鑰:"+Arrays.toString(secretKey.getEncoded()));
		
		// B生成的一個密鑰對
		KeyPair bKeyPair = generator.generateKeyPair();
		// B的公鑰
		PublicKey bPublicKey = bKeyPair.getPublic();
		// B的私鑰
		PrivateKey bPrivateKey = bKeyPair.getPrivate();
		System.out.println("B的公鑰:" + aPublicKey);
		System.out.println("B的私鑰:" + aPrivateKey);

		// 第一步B操作
		// 用B的會話密鑰加密資訊
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, secretKey);
		cipher.update(plain);
		byte[] result1 = cipher.doFinal();
		System.out.println("加密結果:" + Arrays.toString(result1));

		// 用A的公鑰對B的會話密鑰secretKey進行加密
		Cipher rsaCipher = Cipher.getInstance("RSA");
		rsaCipher.init(Cipher.ENCRYPT_MODE, aPublicKey);
		rsaCipher.update(secretKey.getEncoded());
		byte[] sessionKeyEnc = rsaCipher.doFinal();
		System.out.println("加密B會話密鑰:" + Arrays.toString(sessionKeyEnc));

		// 把原文做一個資訊摘要
		MessageDigest digest = MessageDigest.getInstance("SHA1");
		digest.update(plain);
		byte[] hash = digest.digest();

		// 簽名
		Signature signature = Signature.getInstance("SHA1withRSA");
		// B用自己的私鑰對資訊簽名
		signature.initSign(bPrivateKey);
		signature.update(hash);
		byte[] signByte = signature.sign();

		// B把簽名結果signByte和加密結果result1一起發送給A

		// 第二步A操作
		// A得到B發過來的會話密鑰的加密結果用自己的私鑰進行解密,加密會話密鑰
		rsaCipher.init(Cipher.DECRYPT_MODE, aPrivateKey);
		rsaCipher.update(sessionKeyEnc);
		byte[] sessionKeyDec = rsaCipher.doFinal();

		SecretKey secretKey2 = new AESKey(secretKey.getAlgorithm(),
				secretKey.getFormat(), sessionKeyDec);
		System.out.println("解密B會話密鑰:"+Arrays.toString(secretKey2.getEncoded()));
		// 用會話密鑰解密加密資訊
		cipher.init(Cipher.DECRYPT_MODE, secretKey2);
		cipher.update(result1);
		byte[] result2 = cipher.doFinal();

		System.out.println("解密結果:" + Arrays.toString(result2));
		System.out.println("原文比較:" + Arrays.equals(result2, plain));

		// 把解密的結果進行資訊摘要
		digest.reset();
		digest.update(result2);
		byte[] hash2 = digest.digest();

		// 比較兩次摘要的結果是否一緻
		signature.initVerify(bPublicKey);
		signature.update(hash2);
		boolean b = signature.verify(signByte);
		System.out.println("驗證簽名結果:" + b);
           

 附AESKey的實作

class AESKey implements SecretKey {

	private String alg;
	private String format;
	private byte[] encode;

	public AESKey(String alg, String format, byte[] encode) {
		this.alg = alg;
		this.format = format;
		this.encode = encode;
	}

	@Override
	public String getAlgorithm() {
		return alg;
	}

	@Override
	public String getFormat() {
		return format;
	}

	@Override
	public byte[] getEncoded() {
		return encode;
	}

}
           

輸出結果:

原文:[112, 97, 115, 115, 119, 111, 114, 100]
A的公鑰:Sun RSA public key, 1024 bits
  modulus: 91418327984526516476749547644261586889316522330588032287624662687056483794446619299917106424382328807604185610341520333805651808184020229732304326816785271283309582321041169498456578545227365985190079275013558202192417643073047723942028309192889848604991039624232965615569082893809043335310769221406950339451
  public exponent: 65537
A的私鑰:Sun RSA private CRT key, 1024 bits
  modulus:          91418327984526516476749547644261586889316522330588032287624662687056483794446619299917106424382328807604185610341520333805651808184020229732304326816785271283309582321041169498456578545227365985190079275013558202192417643073047723942028309192889848604991039624232965615569082893809043335310769221406950339451
  public exponent:  65537
  private exponent: 7289808536355578911263761478079726766308621781583732193037924946252608210778308931769333325813236039924614706191079623181841346866192985955735270334994273822168635554800311834689396926056907915364013116653956729820217943675826705803145502968360556473671192256873645980914820857616540140359605487380347500065
  prime p:          12811208585041226420003104891009334655869873900957079721177285397537909001175110616098948196872226637578122241767087202556901912670110934326807694215062339
  prime q:          7135808255535660896317005149774126239765294875672287001548016927610965298975501762989418545676413755503802272840960204525504790519573640226411713915125609
  prime exponent p: 12100441317463981516160523000112437623525658244093324256841099583334514931744518703131681223348455087854545445895058744304359145157583303260199934077033947
  prime exponent q: 3332555400417778858561950907413166330782556117303228531308728719706254709641014731522912758098753312094006075420651982542870822946314149357001134134919961
  crt coefficient:  4165767192593562897090598706799474220098321601896273854027284136853238852079123306614545261899611295589143417080338467864171030026514316189741786135891848
B的會話密鑰:[-95, -12, -94, -23, 115, 101, -29, -48, 111, -63, -39, 29, -25, 17, 50, 76]
B的公鑰:Sun RSA public key, 1024 bits
  modulus: 91418327984526516476749547644261586889316522330588032287624662687056483794446619299917106424382328807604185610341520333805651808184020229732304326816785271283309582321041169498456578545227365985190079275013558202192417643073047723942028309192889848604991039624232965615569082893809043335310769221406950339451
  public exponent: 65537
B的私鑰:Sun RSA private CRT key, 1024 bits
  modulus:          91418327984526516476749547644261586889316522330588032287624662687056483794446619299917106424382328807604185610341520333805651808184020229732304326816785271283309582321041169498456578545227365985190079275013558202192417643073047723942028309192889848604991039624232965615569082893809043335310769221406950339451
  public exponent:  65537
  private exponent: 7289808536355578911263761478079726766308621781583732193037924946252608210778308931769333325813236039924614706191079623181841346866192985955735270334994273822168635554800311834689396926056907915364013116653956729820217943675826705803145502968360556473671192256873645980914820857616540140359605487380347500065
  prime p:          12811208585041226420003104891009334655869873900957079721177285397537909001175110616098948196872226637578122241767087202556901912670110934326807694215062339
  prime q:          7135808255535660896317005149774126239765294875672287001548016927610965298975501762989418545676413755503802272840960204525504790519573640226411713915125609
  prime exponent p: 12100441317463981516160523000112437623525658244093324256841099583334514931744518703131681223348455087854545445895058744304359145157583303260199934077033947
  prime exponent q: 3332555400417778858561950907413166330782556117303228531308728719706254709641014731522912758098753312094006075420651982542870822946314149357001134134919961
  crt coefficient:  4165767192593562897090598706799474220098321601896273854027284136853238852079123306614545261899611295589143417080338467864171030026514316189741786135891848
加密結果:[-109, 14, -118, 18, 40, 66, 3, 94, 41, 110, 0, -47, 78, -91, 122, 111]
加密B會話密鑰:[125, 88, -125, 31, -106, 119, -82, -119, -79, 23, -113, 84, 28, -33, 86, -48, 80, 10, 45, 4, 98, -55, 81, 112, -58, -126, -117, 21, -9, 88, 24, -121, -36, -124, 44, 7, -112, 107, -49, -56, -82, 56, 2, -15, -49, -32, -53, 99, 104, 21, -46, -86, -101, -79, -121, 102, -100, 64, -28, -85, -9, -87, 12, -80, -123, -59, 24, -118, 114, -64, 110, -47, -25, -97, 1, 26, -45, 34, -119, -30, 85, 34, 117, 105, -83, -97, 107, -24, 37, 110, -43, 92, -34, 108, 79, -17, 64, -64, 76, 90, 95, -77, 39, -31, 16, -102, -83, 3, -125, -110, 104, 59, -69, 119, -128, 44, 96, -50, 34, 109, -26, -36, 126, -120, 127, -106, -126, 50]
解密B會話密鑰:[-95, -12, -94, -23, 115, 101, -29, -48, 111, -63, -39, 29, -25, 17, 50, 76]
解密結果:[112, 97, 115, 115, 119, 111, 114, 100]
原文比較:true
驗證簽名結果:true
           

六、這樣就安全了嗎?----------數字證書的産生

當B擷取A的公鑰時,B怎麼确定這就是A的公鑰?唯一的方法就是B不僅拿到A的公鑰、還要拿到A的個人資訊,相等于身份證,這時X509Certificate就産生了,對于X509證書的組裝現在比較好的實作非bouncycastle莫屬了

1、數字證書的組裝

public static X509Certificate getCertificate(PublicKey publicKey,
			X500Name subject) throws Exception {
		
		//公鑰算法OID
		String sAlg = null;
		//TODO 僅對RSA
		sAlg = X509Util.getAlgorithmOID("SHA1with"+publicKey.getAlgorithm()).toString();
		byte[] publicKeyEncode = publicKey.getEncoded();
		
		//組裝公鑰資訊
		SubjectPublicKeyInfo publicKeyInfo;
		if (sAlg.equals("1.2.156.197.1.301")) {
			publicKeyInfo = new SubjectPublicKeyInfo(new AlgorithmIdentifier(
					sAlg), publicKeyEncode);
		} else {
			publicKeyInfo = new SubjectPublicKeyInfo(
					ASN1Sequence.getInstance(publicKeyEncode));
		}
		
		//頒發者
		X500Name issuer;
		issuer = subject;
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		//證書序列号
		BigInteger serial = new BigInteger(md.digest(publicKeyEncode));
		//證書生效日期
		Date notBefore = new Date();
		long year = 365 * 24 * 60 * 60 * 1000;
		//證書結束日期
		Date notAfter = new Date(notBefore.getTime() + 10 * year);
		//組裝證書
		X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(
				issuer, serial, notBefore, notAfter, subject, publicKeyInfo);
		
		//證書簽名
		ContentSigner signer = new ContentSigner() {

			//TODO 簽名為空
			public byte[] getSignature() {
				return new byte[0];
			}

			public OutputStream getOutputStream() {
				return new ByteArrayOutputStream();
			}

			public AlgorithmIdentifier getAlgorithmIdentifier() {
				return new AlgorithmIdentifier(X509Util.getAlgorithmOID(
						"SHA1withRSA").toString());
			}
		};
		X509CertificateHolder certHolder = certBuilder.build(signer);
		byte[] certBuf = null;
		try {
			certBuf = certHolder.getEncoded();
		} catch (IOException e) {
			e.printStackTrace();
		}
		CertificateFactory cf = CertificateFactory.getInstance("X509");
		return (X509Certificate) cf
				.generateCertificate(new ByteArrayInputStream(certBuf));
	}
           

2、用數字證書代替公鑰,不僅驗證公鑰,也要驗證證書的有效性

KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
		generator.initialize(1024);

		// A生成一個密鑰對
		KeyPair aKeyPair = generator.generateKeyPair();
		// A把公鑰公開
		PublicKey aPublicKey = aKeyPair.getPublic();
		// A自己儲存好私鑰
		PrivateKey aPrivateKey = aKeyPair.getPrivate();
		System.out.println("A的公鑰:" + aPublicKey);
		System.out.println("A的私鑰:" + aPrivateKey);
		
		X500Name subject = new X500Name("o=ChinaZF,ou=特工,cn=007");
		
		X509Certificate certificate = getCertificate(aPublicKey, subject);
		System.out.println(certificate);
		
		//沒有簽名,簽名是無效的。
		//certificate.verify(aPublicKey);
           

 輸出結果:

A的公鑰:Sun RSA public key, 1024 bits
  modulus: 121375921797136310584113277075626417702106134650309911734631920262170928928191143305688909496584272517313783965325179965007347203684990245350583963403130438989877867943122025651419267585781869015209835513328257718652754130646803812568871376045617234858685855024104612111317545237059745480540648495825269928597
  public exponent: 65537
A的私鑰:Sun RSA private CRT key, 1024 bits
  modulus:          121375921797136310584113277075626417702106134650309911734631920262170928928191143305688909496584272517313783965325179965007347203684990245350583963403130438989877867943122025651419267585781869015209835513328257718652754130646803812568871376045617234858685855024104612111317545237059745480540648495825269928597
  public exponent:  65537
  private exponent: 93254829947223776597065105827075041740606835803394341907226773898120035770956995878226859024390922289154232937211327750400765273771309547646946828650042355995573887546324363837040512754119171427890650604483145044299112375628241658963865665079757096855204500705764805660706159297347368063382327902394539344193
  prime p:          11158242331654507984390217603269741420760310208724980668108807848920513940485092997460488756039704124521900603405927494488714645375960645043236583812293637
  prime q:          10877691861271763807257505279108273122815111142116808418621656894013946974232416694440801989770282169671002997798867760467165866508205378344644397636512081
  prime exponent p: 8325308353040910194557469221427343576793836284636680115189656014106768553059189120494117509083867926222925915213437335024629884333944544628594266982827017
  prime exponent q: 2552075774889217393234224959512470933005861557916719505694899009755686843703520745437260957851410022443220502832833219173034199969943175571467297222317313
  crt coefficient:  7894234470957278080153194562540672330990888843195530292196598522531445521952494004124571924854822356789631822756291673583770445705652331919704012044777045
[
[
  Version: V3
  Subject: CN=007, OU=特工, O=ChinaZF
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 1024 bits
  modulus: 121375921797136310584113277075626417702106134650309911734631920262170928928191143305688909496584272517313783965325179965007347203684990245350583963403130438989877867943122025651419267585781869015209835513328257718652754130646803812568871376045617234858685855024104612111317545237059745480540648495825269928597
  public exponent: 65537
  Validity: [From: Fri Dec 23 17:44:24 CST 2011,
               To: Mon Jun 11 00:29:13 CST 2012]
  Issuer: CN=007, OU=特工, O=ChinaZF
  SerialNumber: [    37ce978c 070962d7 6d10a4bf df2ea726]

]
  Algorithm: [SHA1withRSA]
  Signature:

]
           

這裡面的證書可以base64的格式儲存到檔案中,在windows下用cer格式,就可以看到!

3、後面的和三一樣

七、我也可頒發證書,是每個人都可以?-----CA的必要性

假設六中我的簽名是有效的,驗證簽名肯定可以通過,但是每個人都以頒發證書,這不亂套了,怎麼辦?想你的身份證是誰頒發的?對,CA需要國家的認證,需要國家的信任你,是以CA中心就産生了。。。。

八、以後有空在寫

1、加解密算法都是規定好的,可不可一自己寫

2、估計都聽過加密機,JCE可以實作連接配接加密機嗎?可以連接配接智能卡嗎?

3、證書的有效性,CRL

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

<script type="text/javascript"> var cpro_id = "u1405021"; </script> <script type="text/javascript" src="http://cpro.baidustatic.com/cpro/ui/c.js"></script> 4

頂 0

踩 分享到:

加密機制的發展(JCE/JCA)
加密機制的發展(JCE/JCA)

碼奴 ,程式員 | 開發一個JCE的Provider

  • 2011-12-23 17:56
  • 浏覽 3006
  • 評論(4)
  • 分類:程式設計語言
  • 相關推薦
參考知識庫
加密機制的發展(JCE/JCA)
語音識别與合成知識庫 236  關注 | 222  收錄
加密機制的發展(JCE/JCA)
計算機視覺知識庫 641  關注 | 191  收錄
加密機制的發展(JCE/JCA)
自然語言了解和處理知識庫 241  關注 | 87  收錄
加密機制的發展(JCE/JCA)
知識工程知識庫 72  關注 | 58  收錄
評論

4 樓 沙舟狼客 2012-10-05   ggd543 寫道 第五部分 有點多此一舉,SSH會話過程不是這樣的

這裡隻是原理部分 3 樓 沙舟狼客 2012-10-05   ggd543 寫道 第六部分能否提供 X509CertificateHolder , X509v3CertificateBuilder,ContentSigner,ASN1Sequence,SubjectPublicKeyInfo,X509Util的實作?

這個你可以看一下bouncycastle 2 樓 ggd543 2012-10-04   第六部分能否提供 X509CertificateHolder , X509v3CertificateBuilder,ContentSigner,ASN1Sequence,SubjectPublicKeyInfo,X509Util的實作? 1 樓 ggd543 2012-10-04   第五部分 有點多此一舉,SSH會話過程不是這樣的

發表評論
加密機制的發展(JCE/JCA)

您還沒有登入,請您登入後再發表評論

<script type="text/javascript"> dp.SyntaxHighlighter.HighlightAll('code', true, true); $$('#main .blog_content pre[name=code]').each(function(pre, index){ // blog content var post_id = 1323331; var location = window.location; source_url = location.protocol + "//" + location.host + location.pathname + location.search; pre.writeAttribute('codeable_id', post_id); pre.writeAttribute('codeable_type', "Blog"); pre.writeAttribute('source_url', source_url); pre.writeAttribute('pre_index', index); pre.writeAttribute('title', '加密機制的發展(JCE/JCA)'); }); fix_image_size($$('div.blog_content img'), 700); function processComment() { $$('#main .blog_comment > div').each(function(comment){// comment var post_id = comment.id.substr(2); $$("#"+comment.id+" pre[name=code]").each(function(pre, index){ var location = window.location; source_url = location.protocol + "//" + location.host + location.pathname + location.search; source_url += "#" + comment.id; pre.writeAttribute('codeable_id', post_id); pre.writeAttribute('codeable_type', "BlogComment"); pre.writeAttribute('source_url', source_url); pre.writeAttribute('pre_index', index); pre.writeAttribute('title', '加密機制的發展(JCE/JCA)'); }); }); } function quote_comment(id) { new Ajax.Request('/editor/quote', { parameters: {'id':id, 'type':'BlogComment'}, onSuccess:function(response){editor.bbcode_editor.textarea.insertAfterSelection(response.responseText); Element.scrollTo(editor.bbcode_editor.textarea.element);} }); } code_favorites_init(); processComment(); new WeiboShare({share_buttons: $('share_weibo'), img_scope: $('blog_content')}); </script>

加密機制的發展(JCE/JCA)

沙舟狼客

  • 浏覽: 104632 次
  • 性别:
    加密機制的發展(JCE/JCA)
  • 來自: 北京
  • 加密機制的發展(JCE/JCA)
最近訪客 更多訪客>>
加密機制的發展(JCE/JCA)

shushali

加密機制的發展(JCE/JCA)

rongbinke

加密機制的發展(JCE/JCA)

you_meng

加密機制的發展(JCE/JCA)

靜水流深9318

文章分類
  • 全部部落格 (80)
  • web設計(html+css) (4)
  • JavaScript (9)
  • java基礎 (25)
  • 資料庫 (4)
  • hibernate (1)
  • jsp+servlet (1)
  • struts (0)
  • spring (11)
  • 軟體常識 (11)
  • 扯淡問題 (4)
  • Groovy/Grails (15)
  • linux (2)
  • PKI行業 (5)
  • C/C++ (3)
社群版塊
  • 我的資訊 (1)
  • 我的論壇 (57)
  • 我的問答 (9)
存檔分類
  • 2017-03 (1)
  • 2013-11 (2)
  • 2012-06 (1)
  • 更多存檔...
最新評論
  • 沙舟狼客: 為了友善使用可以配置到環境變量裡面MINGW_HOME=C:\ ...

    windows下用mingw32+sdl進行簡單2d遊戲開發(c語言)

  • 沙舟狼客: 如果安裝autotools時不用gcccc相當于gcc的連結n ...

    windows下用mingw32+sdl進行簡單2d遊戲開發(c語言)

  • lirihong: java中文亂碼完全解決方案 ??  高度很高,深度、全面度全 ...

    java中文亂碼完全解決方案

  • 沙舟狼客: 非常适合想寫windows遊戲的菜鳥

    windows下用mingw32+sdl進行簡單2d遊戲開發(c語言)

  • xixilive: 噢喔~~語義全無

    京東導航的jquery實作

聲明:ITeye文章版權屬于作者,受法律保護。沒有作者書面許可不得轉載。若作者同意轉載,必須以超連結形式标明文章原始出處和作者。

© 2003-2017 ITeye.com. All rights reserved. [ 京ICP證110151号 京公網安備110105010620 ]

上一篇: ASN.1概述
下一篇: CA與私鑰