赞
踩
ECC全称为“Ellipse Curve Ctyptography”,是一种基于椭圆曲线数学的公开密钥加密算法。说到非对称加密算法,大家一般印象是RSA算法,ECC算法的主要优势是可以使用较小的密钥病提供相当高等级的安全,ECC164位密钥提供的安全级可以与RSA 1024位密钥相当。ECC算法相比RSA、DSA算法有以下优势:
同等安全级别要求下,ECC算法计算量小,处理速度快,虽然同等秘钥长度下,ECC的计算更为复杂,但是ECC算法只要较小长度的秘钥就可以达到RSA、DSA算法长秘钥才能达到的安全等级,所以总体上ECC算法性能上更优;
存储空间小,因为同等级安全要求,ECC的秘钥长度要小很多,所以占用的存储空间小;
带宽要求低,虽然长消息场景ECC算法并没有优势,但是短消息场景,ECC要求的带宽是较低的;
ECC算法不仅可以用于加解密(但ECIES当前还未被NIST认可)、签名验签,还可以与DH结合使用,用于密钥磋商,这个密钥交换算法称为ECDH,交换双方可以在不共享任何秘密的情况下协商出一个共享密钥(交互算法可以直接根据自己的私钥和对方的公钥支持生产共享秘钥);
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- import org.bouncycastle.util.encoders.Base64;
-
- import javax.crypto.Cipher;
- import javax.crypto.KeyAgreement;
- import java.security.*;
- import java.security.spec.ECGenParameterSpec;
- import java.security.spec.PKCS8EncodedKeySpec;
- import java.security.spec.X509EncodedKeySpec;
-
- /**
- * ECC算法工具类
- */
- public class ECCUtil {
- /**
- * 算法名称
- */
- private static final String ALGORITHM = "ECDSA";
-
- /**
- * BouncyCastle provider
- */
- private static final String PROVIDER = "BC";
-
- private static final String ENCRYPT_ALGORITHM = "ECIES";
-
- /**
- * 密钥交换算法
- */
- private static final String SHARE_KEY_ALGORITHM = "ECDH";
-
- /**
- * 签名算法
- */
- private static final String SIGN_PROVIDER = "SHA256withECDSA";
-
- static {
- Security.addProvider(new BouncyCastleProvider());
- }
-
- /**
- * 生产公私钥对
- *
- * @return ECC公私钥
- * @throws Exception
- */
- public static KeyPair generateKeyPair() throws Exception {
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM, PROVIDER);
- // 指定EC曲线类型生成密钥对
- ECGenParameterSpec spec = new ECGenParameterSpec("curve25519");
- keyPairGenerator.initialize(spec, SecureRandom.getInstance("SHA1PRNG"));
- return keyPairGenerator.generateKeyPair();
- }
-
- /**
- * 读取公钥(base64编码)
- * @param keyPair
- * @return
- */
- public static String getPublicKey(KeyPair keyPair) {
- return Base64.toBase64String(keyPair.getPublic().getEncoded());
- }
-
- /**
- * 读取私钥(base64编码)
- * @param keyPair
- * @return
- */
- public static String getPrivateKey(KeyPair keyPair) {
- return Base64.toBase64String(keyPair.getPrivate().getEncoded());
- }
-
- /**
- * 构建公钥对象(输入为base64编码字符串)
- * @param keyStr
- * @return
- * @throws Exception
- */
- public static PublicKey str2PublicKey(String keyStr) throws Exception {
- byte[] publicKey = Base64.decode(keyStr);
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
- KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM, PROVIDER);
- return keyFactory.generatePublic(keySpec);
- }
-
- /**
- * 构建私钥对象(输入为base64编码字符串)
- * @param keyStr
- * @return
- * @throws Exception
- */
- public static PrivateKey str2PrivateKey(String keyStr) throws Exception {
- byte[] privateKey = Base64.decode(keyStr);
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
- KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM, PROVIDER);
- return keyFactory.generatePrivate(keySpec);
- }
-
- /**
- * 加密数据
- * @param publicKey 公钥
- * @param data 数据
- * @return
- * @throws Exception
- */
- public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {
- Cipher cipher = Cipher.getInstance(ENCRYPT_ALGORITHM, PROVIDER);
- cipher.init(Cipher.ENCRYPT_MODE, publicKey);
- return cipher.doFinal(data);
- }
-
- /**
- * 解密数据
- * @param privateKey 私钥
- * @param data 数据
- * @return
- * @throws Exception
- */
- public static byte[] decrypt(PrivateKey privateKey, byte[] data) throws Exception {
- Cipher cipher = Cipher.getInstance(ENCRYPT_ALGORITHM, PROVIDER);
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- return cipher.doFinal(data);
- }
-
- /**
- * 数据签名
- * @param privateKey 私钥
- * @param data 数据
- * @return
- * @throws Exception
- */
- public static byte[] sign(PrivateKey privateKey, byte[] data) throws Exception {
- Signature signature = Signature.getInstance(SIGN_PROVIDER);
- signature.initSign(privateKey);
- signature.update(data);
- return signature.sign();
- }
-
- /**
- * 数据验签
- * @param publicKey 公钥
- * @param data 数据
- * @param sign 数据签名
- * @return
- * @throws Exception
- */
- public static boolean verify(PublicKey publicKey, byte[] data, byte[] sign) throws Exception {
- Signature signature = Signature.getInstance(SIGN_PROVIDER);
- signature.initVerify(publicKey);
- signature.update(data);
- return signature.verify(sign);
- }
-
- /**
- * 生成共享密钥:用于密钥交换,客户端和服务器端双方各自生成一对公私钥,然后客户端使用自己的私钥和服务器的公钥生成一个共享秘钥,
- * 服务端使用自己的私钥和客户端的公钥生成一个共享秘钥,这两个秘钥结果相同,可用于对称加密
- * @param privateKey
- * @param publicKey
- * @return
- * @throws Exception
- */
- public static byte[] genShareKey(PublicKey publicKey, PrivateKey privateKey) throws Exception {
- KeyAgreement keyAgreement = KeyAgreement.getInstance(SHARE_KEY_ALGORITHM, PROVIDER);
- keyAgreement.init(privateKey);
- keyAgreement.doPhase(publicKey, true);
- return keyAgreement.generateSecret();
- }
- }
当前在比特币中ECC算法用的比较多,但是随着计算能力的增强,安全等级要求越来越高,RSA算法的秘钥长度已经太长,弊端比较大,可以预见ECC算法应用会越来越广,比如:
性能要求不高的单向数据加密传输场景(非对称加密相比对称加密算法AES性能差别巨大),例如用于长期自动登录身份的校验等;
双方预制校验身份,比如物理网场景平台一份公私钥,设备一份公私钥,平台发放设备时把设备id和设备公钥预制到进去,这样设备上线后就可以与平台认证通信等;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。