Java加密技术(七)——非对称加密算法最高级ECC

ECC

ECC-Elliptic Curves Cryptography,椭圆曲线密码编码学,是目前已知的公钥体制中,对每比特所提供加密强度最高的一种体制。在软件注册保护方面起到很大的作用,一般的序列号通常由该算法产生。

当我开始整理《Java加密技术(二)》的时候,我就已经在开始研究ECC了,但是关于Java实现ECC算法的资料实在是太少了,无论是国内还是国外的资料,无论是官方还是非官方的解释,最终只有一种答案——ECC算法在jdk1.5后加入支持,目前仅仅只能完成密钥的生成与解析。
如果想要获得ECC算法实现,需要调用硬件完成加密/解密(ECC算法相当耗费资源,如果单纯使用CPU进行加密/解密,效率低下),涉及到Java Card领域,PKCS#11。
其实,PKCS#11配置很简单,但缺乏硬件设备,无法尝试!

尽管如此,我照旧提供相应的Java实现代码,以供大家参考。

通过java代码实现如下:
Coder类见 Java加密技术(一)

Java代码
 

  1. import java.math.BigInteger;
  2. import java.security.Key;
  3. import java.security.KeyFactory;
  4. import java.security.interfaces.ECPrivateKey;
  5. import java.security.interfaces.ECPublicKey;
  6. import java.security.spec.ECFieldF2m;
  7. import java.security.spec.ECParameterSpec;
  8. import java.security.spec.ECPoint;
  9. import java.security.spec.ECPrivateKeySpec;
  10. import java.security.spec.ECPublicKeySpec;
  11. import java.security.spec.EllipticCurve;
  12. import java.security.spec.PKCS8EncodedKeySpec;
  13. import java.security.spec.X509EncodedKeySpec;
  14. import java.util.HashMap;
  15. import java.util.Map;
  16. import javax.crypto.Cipher;
  17. import javax.crypto.NullCipher;
  18. import sun.security.ec.ECKeyFactory;
  19. import sun.security.ec.ECPrivateKeyImpl;
  20. import sun.security.ec.ECPublicKeyImpl;
  21. /**
  22. * ECC安全编码组件
  23. *
  24. * @author 梁栋
  25. * @version 1.0
  26. * @since 1.0
  27. */
  28. public abstract class ECCCoder extends Coder {
  29. public static final String ALGORITHM = "EC";
  30. private static final String PUBLIC_KEY = "ECCPublicKey";
  31. private static final String PRIVATE_KEY = "ECCPrivateKey";
  32. /**
  33. * 解密<br>
  34. * 用私钥解密
  35. *
  36. * @param data
  37. * @param key
  38. * @return
  39. * @throws Exception
  40. */
  41. public static byte[] decrypt(byte[] data, String key) throws Exception {
  42. // 对密钥解密
  43. byte[] keyBytes = decryptBASE64(key);
  44. // 取得私钥
  45. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  46. KeyFactory keyFactory = ECKeyFactory.INSTANCE;
  47. ECPrivateKey priKey = (ECPrivateKey) keyFactory
  48. .generatePrivate(pkcs8KeySpec);
  49. ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(priKey.getS(),
  50. priKey.getParams());
  51. // 对数据解密
  52. // TODO Chipher不支持EC算法 未能实现
  53. Cipher cipher = new NullCipher();
  54. // Cipher.getInstance(ALGORITHM, keyFactory.getProvider());
  55. cipher.init(Cipher.DECRYPT_MODE, priKey, ecPrivateKeySpec.getParams());
  56. return cipher.doFinal(data);
  57. }
  58. /**
  59. * 加密<br>
  60. * 用公钥加密
  61. *
  62. * @param data
  63. * @param privateKey
  64. * @return
  65. * @throws Exception
  66. */
  67. public static byte[] encrypt(byte[] data, String privateKey)
  68. throws Exception {
  69. // 对公钥解密
  70. byte[] keyBytes = decryptBASE64(privateKey);
  71. // 取得公钥
  72. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  73. KeyFactory keyFactory = ECKeyFactory.INSTANCE;
  74. ECPublicKey pubKey = (ECPublicKey) keyFactory
  75. .generatePublic(x509KeySpec);
  76. ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(pubKey.getW(),
  77. pubKey.getParams());
  78. // 对数据加密
  79. // TODO Chipher不支持EC算法 未能实现
  80. Cipher cipher = new NullCipher();
  81. // Cipher.getInstance(ALGORITHM, keyFactory.getProvider());
  82. cipher.init(Cipher.ENCRYPT_MODE, pubKey, ecPublicKeySpec.getParams());
  83. return cipher.doFinal(data);
  84. }
  85. /**
  86. * 取得私钥
  87. *
  88. * @param keyMap
  89. * @return
  90. * @throws Exception
  91. */
  92. public static String getPrivateKey(Map<String, Object> keyMap)
  93. throws Exception {
  94. Key key = (Key) keyMap.get(PRIVATE_KEY);
  95. return encryptBASE64(key.getEncoded());
  96. }
  97. /**
  98. * 取得公钥
  99. *
  100. * @param keyMap
  101. * @return
  102. * @throws Exception
  103. */
  104. public static String getPublicKey(Map<String, Object> keyMap)
  105. throws Exception {
  106. Key key = (Key) keyMap.get(PUBLIC_KEY);
  107. return encryptBASE64(key.getEncoded());
  108. }
  109. /**
  110. * 初始化密钥
  111. *
  112. * @return
  113. * @throws Exception
  114. */
  115. public static Map<String, Object> initKey() throws Exception {
  116. BigInteger x1 = new BigInteger(
  117. "2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8", 16);
  118. BigInteger x2 = new BigInteger(
  119. "289070fb05d38ff58321f2e800536d538ccdaa3d9", 16);
  120. ECPoint g = new ECPoint(x1, x2);
  121. // the order of generator
  122. BigInteger n = new BigInteger(
  123. "5846006549323611672814741753598448348329118574063", 10);
  124. // the cofactor
  125. int h = 2;
  126. int m = 163;
  127. int[] ks = { 7, 6, 3 };
  128. ECFieldF2m ecField = new ECFieldF2m(m, ks);
  129. // y^2+xy=x^3+x^2+1
  130. BigInteger a = new BigInteger("1", 2);
  131. BigInteger b = new BigInteger("1", 2);
  132. EllipticCurve ellipticCurve = new EllipticCurve(ecField, a, b);
  133. ECParameterSpec ecParameterSpec = new ECParameterSpec(ellipticCurve, g,
  134. n, h);
  135. // 公钥
  136. ECPublicKey publicKey = new ECPublicKeyImpl(g, ecParameterSpec);
  137. BigInteger s = new BigInteger(
  138. "1234006549323611672814741753598448348329118574063", 10);
  139. // 私钥
  140. ECPrivateKey privateKey = new ECPrivateKeyImpl(s, ecParameterSpec);
  141. Map<String, Object> keyMap = new HashMap<String, Object>(2);
  142. keyMap.put(PUBLIC_KEY, publicKey);
  143. keyMap.put(PRIVATE_KEY, privateKey);
  144. return keyMap;
  145. }
  146. }
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECFieldF2m;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.NullCipher;

import sun.security.ec.ECKeyFactory;
import sun.security.ec.ECPrivateKeyImpl;
import sun.security.ec.ECPublicKeyImpl;

/**
 * ECC安全编码组件
 *
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class ECCCoder extends Coder {

	public static final String ALGORITHM = "EC";
	private static final String PUBLIC_KEY = "ECCPublicKey";
	private static final String PRIVATE_KEY = "ECCPrivateKey";

	/**
	 * 解密<br>
	 * 用私钥解密
	 *
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, String key) throws Exception {
		// 对密钥解密
		byte[] keyBytes = decryptBASE64(key);

		// 取得私钥
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = ECKeyFactory.INSTANCE;

		ECPrivateKey priKey = (ECPrivateKey) keyFactory
				.generatePrivate(pkcs8KeySpec);

		ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(priKey.getS(),
				priKey.getParams());

		// 对数据解密
		// TODO Chipher不支持EC算法 未能实现
		Cipher cipher = new NullCipher();
		// Cipher.getInstance(ALGORITHM, keyFactory.getProvider());
		cipher.init(Cipher.DECRYPT_MODE, priKey, ecPrivateKeySpec.getParams());

		return cipher.doFinal(data);
	}

	/**
	 * 加密<br>
	 * 用公钥加密
	 *
	 * @param data
	 * @param privateKey
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, String privateKey)
			throws Exception {
		// 对公钥解密
		byte[] keyBytes = decryptBASE64(privateKey);

		// 取得公钥
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = ECKeyFactory.INSTANCE;

		ECPublicKey pubKey = (ECPublicKey) keyFactory
				.generatePublic(x509KeySpec);

		ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(pubKey.getW(),
				pubKey.getParams());

		// 对数据加密
		// TODO Chipher不支持EC算法 未能实现
		Cipher cipher = new NullCipher();
		// Cipher.getInstance(ALGORITHM, keyFactory.getProvider());
		cipher.init(Cipher.ENCRYPT_MODE, pubKey, ecPublicKeySpec.getParams());

		return cipher.doFinal(data);
	}

	/**
	 * 取得私钥
	 *
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPrivateKey(Map<String, Object> keyMap)
			throws Exception {
		Key key = (Key) keyMap.get(PRIVATE_KEY);

		return encryptBASE64(key.getEncoded());
	}

	/**
	 * 取得公钥
	 *
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPublicKey(Map<String, Object> keyMap)
			throws Exception {
		Key key = (Key) keyMap.get(PUBLIC_KEY);

		return encryptBASE64(key.getEncoded());
	}

	/**
	 * 初始化密钥
	 *
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> initKey() throws Exception {
		BigInteger x1 = new BigInteger(
				"2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8", 16);
		BigInteger x2 = new BigInteger(
				"289070fb05d38ff58321f2e800536d538ccdaa3d9", 16);

		ECPoint g = new ECPoint(x1, x2);

		// the order of generator
		BigInteger n = new BigInteger(
				"5846006549323611672814741753598448348329118574063", 10);
		// the cofactor
		int h = 2;
		int m = 163;
		int[] ks = { 7, 6, 3 };
		ECFieldF2m ecField = new ECFieldF2m(m, ks);
		// y^2+xy=x^3+x^2+1
		BigInteger a = new BigInteger("1", 2);
		BigInteger b = new BigInteger("1", 2);

		EllipticCurve ellipticCurve = new EllipticCurve(ecField, a, b);

		ECParameterSpec ecParameterSpec = new ECParameterSpec(ellipticCurve, g,
				n, h);
		// 公钥
		ECPublicKey publicKey = new ECPublicKeyImpl(g, ecParameterSpec);

		BigInteger s = new BigInteger(
				"1234006549323611672814741753598448348329118574063", 10);
		// 私钥
		ECPrivateKey privateKey = new ECPrivateKeyImpl(s, ecParameterSpec);

		Map<String, Object> keyMap = new HashMap<String, Object>(2);

		keyMap.put(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);

		return keyMap;
	}

}

请注意上述代码中的
TODO内容,再次提醒注意,Chipher不支持EC算法 ,以上代码仅供参考。Chipher、Signature、KeyPairGenerator、KeyAgreement、SecretKey均不支持EC算法。为了确保程序能够正常执行,我们使用了NullCipher类,验证程序。

照旧提供一个测试类:

Java代码
 

  1. import static org.junit.Assert.*;
  2. import java.math.BigInteger;
  3. import java.security.spec.ECFieldF2m;
  4. import java.security.spec.ECParameterSpec;
  5. import java.security.spec.ECPoint;
  6. import java.security.spec.ECPrivateKeySpec;
  7. import java.security.spec.ECPublicKeySpec;
  8. import java.security.spec.EllipticCurve;
  9. import java.util.Map;
  10. import org.junit.Test;
  11. /**
  12. *
  13. * @author 梁栋
  14. * @version 1.0
  15. * @since 1.0
  16. */
  17. public class ECCCoderTest {
  18. @Test
  19. public void test() throws Exception {
  20. String inputStr = "abc";
  21. byte[] data = inputStr.getBytes();
  22. Map<String, Object> keyMap = ECCCoder.initKey();
  23. String publicKey = ECCCoder.getPublicKey(keyMap);
  24. String privateKey = ECCCoder.getPrivateKey(keyMap);
  25. System.err.println("公钥: \n" + publicKey);
  26. System.err.println("私钥: \n" + privateKey);
  27. byte[] encodedData = ECCCoder.encrypt(data, publicKey);
  28. byte[] decodedData = ECCCoder.decrypt(encodedData, privateKey);
  29. String outputStr = new String(decodedData);
  30. System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
  31. assertEquals(inputStr, outputStr);
  32. }
  33. }
import static org.junit.Assert.*;

import java.math.BigInteger;
import java.security.spec.ECFieldF2m;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import java.util.Map;

import org.junit.Test;

/**
 *
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class ECCCoderTest {

	@Test
	public void test() throws Exception {
		String inputStr = "abc";
		byte[] data = inputStr.getBytes();

		Map<String, Object> keyMap = ECCCoder.initKey();

		String publicKey = ECCCoder.getPublicKey(keyMap);
		String privateKey = ECCCoder.getPrivateKey(keyMap);
		System.err.println("公钥: \n" + publicKey);
		System.err.println("私钥: \n" + privateKey);

		byte[] encodedData = ECCCoder.encrypt(data, publicKey);

		byte[] decodedData = ECCCoder.decrypt(encodedData, privateKey);

		String outputStr = new String(decodedData);
		System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
		assertEquals(inputStr, outputStr);
	}
}

控制台输出:

Console代码
 

  1. 公钥:
  2. MEAwEAYHKoZIzj0CAQYFK4EEAAEDLAAEAv4TwFN7vBGsqgfXk95ObV5clO7oAokHD7BdOP9YMh8u
  3. gAU21TjM2qPZ
  4. 私钥:
  5. MDICAQAwEAYHKoZIzj0CAQYFK4EEAAEEGzAZAgEBBBTYJsR3BN7TFw7JHcAHFkwNmfil7w==
  6. 加密前: abc
  7. 解密后: abc
时间: 2024-08-26 21:05:05

Java加密技术(七)——非对称加密算法最高级ECC的相关文章

Java加密技术(一)——BASE64与单向加密算法MD5&amp;SHA&amp;MAC

http://snowolf.iteye.com/blog/379860 加密解密,曾经是我一个毕业设计的重要组件.在工作了多年以后回想当时那个加密.解密算法,实在是太单纯了.     言归正传,这里我们主要描述Java已经实现的一些加密解密算法,最后介绍数字证书.     如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorithm,安全散列算法) H

Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC

加密解密,曾经是我一个毕业设计的重要组件.在工作了多年以后回想当时那个加密.解密算法,实在是太单纯了. 言归正传,这里我们主要描述Java已经实现的一些加密解密算法,最后介绍数字证书. 如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorithm,安全散列算法) HMAC(Hash Message Authentication Code,散列消息鉴别码)

Java加密技术(二)——对称加密算法DES&AES

接下来我们介绍对称加密算法,最常用的莫过于DES数据加密算法. DES DES-Data Encryption Standard,即数据加密算法.是IBM公司于1975年研究成功并公开发表的.DES算法的入口参数有三个:Key.Data.Mode.其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密. DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位. 通过java

【安全加密技术】非对称加密

转载请注明出处:http://blog.csdn.net/sk719887916/article/details/46810595 看过上篇网络互联基系列基础的朋友,对安全产生的原因以及策略度有所了解,当然作为开发者来讲,网络传输中的安全问题我们不必过多的关心,我们关心的是发送方加密和接收方对数据的解密过程,也就是网络安全中的一面边缘学科,密码学中的一种数据加密技术,目前业界的加密方式主要有对称加密和非堆成加密,那就先来了解下有非对称加密以及所关联的相关名字. 非对称加密 非对称加密算法是一种密

Java加密技术(十)——单向认证

在 Java 加密技术(九)中,我们使用自签名证书完成了认证.接下来,我们使用第三方CA签名机构完成证书签名. 这里我们使用 thawte提供的测试用21天免费ca证书. 1.要在该网站上注明你的域名,这里使用 www.zlex.org作为测试用域名(请勿使用该域名作为你的域名地址,该域名受法律保护!请使用其他非注册域名!). 2.如果域名有效,你会收到邮件要求你访问 https://www.thawte.com/cgi/server/try.exe获得ca证书. 3.复述密钥库的创建. She

Java 加密解密之对称加密算法AES

Java 加密解密之对称加密算法AES 密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准.2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一.该算法

Java加密技术(八)——数字证书

本篇的主要内容为Java证书体系的实现. 请大家在阅读本篇内容时先阅读 Java加密技术(四),预先了解RSA加密算法. 在构建Java代码实现前,我们需要完成证书的制作. 1.生成keyStroe文件 在命令行下执行以下命令: Shell代码   keytool -genkey -validity 36000 -alias www.zlex.org -keyalg RSA -keystore d:\zlex.keystore keytool -genkey -validity 36000 -a

Java加密技术(十二)——*.PFX(*.p12)&个人信息交换文件

今天来点实际工作中的硬通货! 与计费系统打交道,少不了用到加密/解密实现.为了安全起见,通过非对称加密交换对称加密密钥更是不可或缺.那么需要通过什么载体传递非对称算法公钥/私钥信息?数字证书是公钥的载体,而密钥库可以包含公钥.私钥信息. JKS和 PKCS#12都是比较常用的两种密钥库格式/标准.对于前者,搞Java开发,尤其是接触过HTTPS平台的朋友,并不陌生. JKS文件(通常为*.jks或*.keystore,扩展名无关)可以通过Java原生工具--KeyTool生成:而后者 PKCS#

Java加密技术(四)非对称加密算法RSA

RSA  这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作,也很流行.算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman. 这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥.相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了.RSA同时有两把钥匙,公钥与私钥.同时支持数字签名.数字签名的意义在于,对传输过来的数据进行校验.确保数据在传输工程中不被修改. 流程分析: 甲方构建