`
沙舟狼客
  • 浏览: 157746 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

加密机制的发展(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

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

 

 

4
0
分享到:
评论
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会话过程不是这样的

相关推荐

    org.bouncycastle.jar

    解决org/bouncycastle/jce/provider/bouncycastlepr错误专用。

    jdk8加密使用的jce_policy-8替换原jar包

    jdk8加密使用的jce_policy-8替换原jar包

    AES192、256位加密解密,jce7,jce8 jdk1.7,jdk1.8

    用于替换jdk里的两个jar,解决无法使用AES192、256位加密解密的问题 jce7,jce8

    bcmail-jdk14-138.jar

    此外,bcmail-jdk14-138.jar也提供了处理S/MIME协议的APIs,可以和JCE/JCA提供者如Bouncy Castle Cryptography APIs一同使用。 在使用该API时,还需要配合JavaMail API和Java激活框架。值得注意的是,如果在程序中...

    JCE 加密、解密算法

    JCE 加密、解密算法

    jce_policy-8.zip 开启JDK8对高强度加密算法支持

    由于默认JDK8是不能使用PBEWITHMD5ANDTRIPLEDES等高强度加密算法的, ...需要把jce_policy-8.zip中的两个jar包拷贝到<JRE_HOME>\lib\security下面, 替换掉两个原有的同名文件,以开启对高强度加密算法支持

    jce(Java加密扩展)

    1、javax.crypto.Cipher 类提供加密和解密的功能,它构成了 Java Cryptography Extension (JCE) —— Java 加密扩展框架的核心。这些都是 Java JDK 原生的 API,不是第三方的。 2、Cipher 的 getInstance(String ...

    基于JCE的文件加密技术实现

    自己写的一个小程序,希望对你有帮助. 用java编写,基于JCE

    JDK8 JCE 支持256位加密

    JDK8 JCE 支持256位加密

    jce 1.8 download

    curl -q -L -C - -b "oraclelicense=accept-securebackup-cookie" -o /tmp/jce_policy-8.zip -O http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip 以上两个你选吧

    jce_policy-8.rar

    https://www.oracle.com/java/technologies/javase-jce8-downloads.html(官方地址点击会跳转到登录页面,可以直接访问http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip进行下载)

    jce加密解密

    (java加密解密)如何实现JCE接口的各种算法 jce加密解密 很好的资料 很详细

    JCE文件jdk6, jdk7

    官网下载地址是...JCE(Java Cryptography Extension)是一组包,它们提供用于加密、密钥生成和协商以及 Message Authentication Code(MAC)算法的框架和实现。

    JCE_Policy安装包

    SpringCloud加密,直接替换/jdk/jre/lib/security目录下的jar即可。

    bcpkix-jdk15on-1.49.rar

    解决java.lang.NoClassDefFoundError: org/bouncycastle/jce/provider/BouncyCastleProvider的架包

    jce8-jce7.zip

    jdk8无政策限制权限文件,用于AES加密算法,AES加密扩展包因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件。 因为某些国家...

    JCE(jce_policy-8).zip

    jce_policy-8,JCE(Java Cryptography Extension)是一组包,它们提供用于加密、密钥生成和协商以及 Message Authentication Code(MAC)算法的框架和实现。 它提供对对称、不对称、块和流密码的加密支持,它还...

    JCE.Zip-DES加密-AES加密--RSA加密学习所需源码

    JCE.Zip-DES加密-AES加密--RSA加密学习所需源码 java cryptography extension source code

    java加密模块jce_policy-6.zip

    因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件。

    前台加密后台解密-非对称RSA加密方式

    项目采用servlet编写,简单明了,前台对数据进行公钥加密,后台用私钥进行解密,项目运行后地址为:http://localhost:8082/rsa/rsaser?worktype=turn 端口号视情况而定

Global site tag (gtag.js) - Google Analytics