非对称的特点是加密和解密时使用的是不同的钥匙。密钥分为公钥和私钥,用公钥加密的数据只能用私钥进行解密,反之亦然。

另外,密钥还可以用于数字签名。数字签名跟上文说的消息摘要是一个道理,通过一定方法对数据内容进行处理得到一个签名,查看这个签名是否与对方传递的签名一致。

在非对称加密中用密钥来指公钥和私钥。

RSA

RAS是最早的非对称签名,是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年7月首次在美国公布,当时他们三人都在麻省理工学院工作实习。RSA就是他们三人姓氏开头字母拼在一起组成的。

对于非对称加密,在Java中可以用KeyPairGenerator工具类来负责生成密钥对:

public class RSAUtil {

    public final static String ALGORITHM = "RSA";

    public static KeyPair getKey() throws Exception{
KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM);
return generator.generateKeyPair();
} public static void main(String[] args) throws Exception{
KeyPair keyPair = getKey();
RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic(); String privateKeyStr = Base64.encode(privateKey.getEncoded());
String publicKeyStr = Base64.encode(publicKey.getEncoded()); System.out.println("私钥:" + privateKeyStr);
System.out.println("公钥:" + publicKeyStr);
} } 

使用公钥加密:

    public static String encryptByPublicKey(String data,String key)throws Exception{
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); Key k = keyFactory.generatePublic(keySpec); Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, k); byte[] bytes = cipher.doFinal(data.getBytes("UTF-8")); return Base64Util.encode(bytes);

加密的时候用X509EncodedKeySpec来获取公钥,不要害怕X509,其实没有别的X508或者X609,就这么一个X509。X.509是一种非常通用的证书格式。所有的证书都符合ITU-T X.509国际标准。

和之前的DES类似,使用私钥解密的代码如下:

    public static String decryptByPrivateKey(String data,String key)throws Exception{

        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); Key k = keyFactory.generatePrivate(keySpec); Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, k); byte[] bytes = cipher.doFinal(Base64Util.decode(data)); return new String(bytes,"UTF-8");

还用X509去读私钥就不行了,会报下面这个错误:

Exception in thread "main" java.security.spec.InvalidKeySpecException: Only RSAPrivate(Crt)KeySpec and PKCS8EncodedKeySpec supported for RSA private keys

意思是只能用RSAPrivate(Crt)KeySpec 或者 PKCS8EncodedKeySpec去读私钥,改成下面这样就好了:

    public static String decryptByPrivateKey(String data,String key)throws Exception{

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM); Key k = keyFactory.generatePrivate(keySpec); Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, k); byte[] bytes = cipher.doFinal(Base64Util.decode(data)); return new String(bytes,"UTF-8");
}

使用私钥加密和公钥解密的方法就不用多说了,只需要在加密和解密时换成另外一个钥匙就行了。

签名和签名验证

/**
* 使用私钥进行签名
* @param data
* @param key
* @return
* @throws Exception
*/
public static String sign(String data,String key)throws Exception{
PrivateKey k = (PrivateKey)getPrivateKey(key);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(k);
signature.update(data.getBytes("UTF-8"));
return Base64.encode(signature.sign());
} /**
* 使用公钥进行签名验证
* @param data
* @param key
* @return
* @throws Exception
*/
public static boolean signVerify(String data,String key,String sign)throws Exception{
PublicKey k = (PublicKey)getPublicKey(key);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(k);
signature.update(data.getBytes("UTF-8"));
return signature.verify(Base64.decode(sign));
}

JDK中有专门用于签名的工具类Signature,可用的签名算法如下:

完整代码重构如下:

public class RSAUtil {

    public final static String ALGORITHM = "RSA";
public final static String SIGNATURE_ALGORITHM = "MD5withRSA"; /**
* 获取公钥密钥对
* @return
* @throws Exception
*/
public static KeyPair getKey() throws Exception{
KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM);
return generator.generateKeyPair();
} private static Key getPublicKey(String key)throws Exception{
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
Key k = keyFactory.generatePublic(keySpec);
return k;
} private static Key getPrivateKey(String key)throws Exception{
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
Key k = keyFactory.generatePrivate(keySpec);
return k;
} /**
* 使用公钥进行加密
* @param data
* @param key
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String data,String key)throws Exception{ Key k = getPublicKey(key); Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, k); byte[] bytes = cipher.doFinal(data.getBytes("UTF-8")); return Base64Util.encode(bytes);
} /**
* 使用私钥进行加密
* @param data
* @param key
* @return
* @throws Exception
*/
public static String encryptByPrivateKey(String data,String key)throws Exception{ Key k = getPrivateKey(key); Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, k); byte[] bytes = cipher.doFinal(data.getBytes("UTF-8")); return Base64Util.encode(bytes);
} /**
* 使用密钥进行解密
* @param data
* @param key
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String data,String key)throws Exception{
Key k = getPrivateKey(key); Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, k); byte[] bytes = cipher.doFinal(Base64Util.decode(data)); return new String(bytes,"UTF-8");
} /**
* 使用公钥进行解密
* @param data
* @param key
* @return
* @throws Exception
*/
public static String decryptByPublicKey(String data,String key)throws Exception{
Key k = getPublicKey(key);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, k); byte[] bytes = cipher.doFinal(Base64Util.decode(data)); return new String(bytes,"UTF-8");
} /**
* 使用私钥进行签名
* @param data
* @param key
* @return
* @throws Exception
*/
public static String sign(String data,String key)throws Exception{
PrivateKey k = (PrivateKey)getPrivateKey(key);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(k);
signature.update(data.getBytes("UTF-8"));
return Base64.encode(signature.sign());
} /**
* 使用公钥进行签名验证
* @param data
* @param key
* @return
* @throws Exception
*/
public static boolean signVerify(String data,String key,String sign)throws Exception{
PublicKey k = (PublicKey)getPublicKey(key);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(k);
signature.update(data.getBytes("UTF-8"));
return signature.verify(Base64.decode(sign));
} public static void main(String[] args) throws Exception{
KeyPair keyPair = getKey();
RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic(); String privateKeyStr = Base64.encode(privateKey.getEncoded());
String publicKeyStr = Base64.encode(publicKey.getEncoded()); System.out.println("私钥:" + privateKeyStr);
System.out.println("公钥:" + publicKeyStr); String data = "Hello,RSA,Hello,RSAHello,RSAHello,RSAHello,RSAHello,RSAHello,RSA";
System.out.println("---------------公钥加密,私钥解密-----------------");
String encryptedData = encryptByPublicKey(data,publicKeyStr);
System.out.println("加密后:" + encryptedData); String decryptedData = decryptByPrivateKey(encryptedData, privateKeyStr);
System.out.println("解密后:" + decryptedData);
System.out.println("---------------私钥加密,公钥解密-----------------"); encryptedData = encryptByPrivateKey(data,privateKeyStr);
System.out.println("加密后:" + encryptedData);
decryptedData = decryptByPublicKey(encryptedData, publicKeyStr);
System.out.println("解密后:" + decryptedData); String sign = sign(data,privateKeyStr);
System.out.println("签名:" + sign);
System.out.println("签名验证:" + signVerify(data,publicKeyStr,sign)); } }

DH(Diffie-Hellman)

非对称加密的算法比较耗时,所以不能用它来传输大数据。通常情况下会是这样:

  1. 因为对称加密算法中没法安全传递密钥,所以用非对称加密算法来传递对称加密的密钥;
  2. 等对称加密的秘钥传递成功之后,正式的数据就用对称加密算法来传递了。

DH算法就是为了实现这个目的而产生的。DH能实现甲乙双方的密钥沟通。

假设客户端要发送数据到服务端,在Java中DH加密的完整步骤:

服务端先生成自己的密钥对:

/**
* 数据处理服务端*/
public class Server { private String publicKey;
private String privateKey;
private SecretKey key; public Server(){
try {
String[] keyPair = DHUtil.getStringKeyPair();
publicKey = keyPair[0];
privateKey = keyPair[1];
} catch (Exception e) {
e.printStackTrace();
} }
...

服务端的私钥自己保持,公布公钥,客户端则需要根据服务端的公钥生成自己的密钥对:

/**
* 数据传输客户端*/
public class Client { private String publicKey;
private String privateKey;private Server server; public Client(Server server){
this.server = server;
String serverPublicKey = server.getPublicKey();//明文获取到公钥
try{
String[] keyPair = DHUtil.getStringKeyPair(serverPublicKey);
publicKey = keyPair[0];
privateKey = keyPair[1];
}catch(Exception e){
e.printStackTrace();
}
}
...

客户端在和服务端通信时,使用的加密算法是对称加密。对称加密的密钥是根据服务端的公钥和客户端的私钥生成的。

public class Client {

    private String publicKey;
private String privateKey;
private SecretKey key; private Server server; public Client(Server server){
this.server = server;
String serverPublicKey = server.getPublicKey();
try{
String[] keyPair = DHUtil.getStringKeyPair(serverPublicKey);
publicKey = keyPair[0];
privateKey = keyPair[1];
key = DHUtil.getAgreementSecretKey(serverPublicKey, privateKey);
}catch(Exception e){
e.printStackTrace();
}
}
...

好了,现在可以往服务端发送数据了,比如有一个登录操作:

public class Client {
...
public boolean login(String user,String pwd){
String data = "user=" + user + "&pwd=" + pwd;
try {
data = DHUtil.encrypt(data, key);
} catch (Exception e) {
e.printStackTrace();
}
String response = server.service(data,publicKey);
System.out.println("Login Response:" + response);
return response.equals("OK");
}
}

可见,公钥是通过明文的形式发送给服务端的。服务端对数据进行处理:

/**
* 数据处理服务端
* @author huqiao
*/
public class Server { ... public String service(String data,String clientPublicKey){try {
key = DHUtil.getAgreementSecretKey(clientPublicKey, privateKey);//根据客户端的publicKey生成本地密钥
String decryptedData = DHUtil.decrypt(data, key);
System.out.println("Data decryped:" + decryptedData);
if(verfiy(decryptedData)){
return "OK";
}else{
return "Error"; }
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
... 

服务器拿到客户端的公钥之后生成本地的密钥,然后对数据进行解密。为了简单起见,这里服务器往客户度返回数据时没有做加密。

非常重要的DHUtil.java完整代码:

public class DHUtil {

    public final static String ALGORITHM = "DH";
public final static String SYMMETRIC_SECRET_ALGORITHM = "AES";//对称加密算法名称 /**
* 产生密钥对
* @return
* @throws Exception
*/
public static KeyPair getKeyPair()throws Exception{
KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM);
generator.initialize(1024);
return generator.generateKeyPair();
} /**
* 获取字符串类型的密钥对
* @return
* @throws Exception
*/
public static String[] getStringKeyPair()throws Exception{
KeyPair keyPair = getKeyPair();
return keyPairToStringArray(keyPair);
} public static String[] getStringKeyPair(String publicKey)throws Exception{
KeyPair keyPair = getKeyPairByPublicKey(publicKey);
return keyPairToStringArray(keyPair);
} private static String[] keyPairToStringArray(KeyPair keyPair){
String[] res = new String[2];
PublicKey pubKey = keyPair.getPublic();
PrivateKey priKey = keyPair.getPrivate(); res[0] = Base64Util.encode(pubKey.getEncoded());
res[1] = Base64Util.encode(priKey.getEncoded()); return res;
} /**
* 由一个公钥产生密钥对
* @param publicKey
* @return
* @throws Exception
*/
public static KeyPair getKeyPairByPublicKey(String publicKey)throws Exception{ PublicKey pKey = getPublicKey(publicKey); KeyPairGenerator generator = KeyPairGenerator.getInstance(pKey.getAlgorithm()); DHParameterSpec dhGenParam = ((DHPublicKey) pKey).getParams();
generator.initialize(dhGenParam); return generator.generateKeyPair();
} private static PublicKey getPublicKey(String key)throws Exception{
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PublicKey k = keyFactory.generatePublic(keySpec);
return k;
} private static PrivateKey getPrivateKey(String key)throws Exception{
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PrivateKey k = keyFactory.generatePrivate(keySpec);
return k;
} /**
* 根据一方公钥和另外一方私钥构建本地密钥
* @param publicKey
* @param privateKey
* @return
* @throws Exception
*/
public static SecretKey getAgreementSecretKey(String publicKey,String privateKey)throws Exception{
PublicKey pubKey = getPublicKey(publicKey);
PrivateKey priKey = getPrivateKey(privateKey); return getAgreementSecretKey(pubKey,priKey); } public static SecretKey getAgreementSecretKey(PublicKey pubKey,PrivateKey priKey)throws Exception{
KeyAgreement argeement = KeyAgreement.getInstance(pubKey.getAlgorithm());
argeement.init(priKey);
argeement.doPhase(pubKey, true); SecretKey secretKey = argeement.generateSecret(SYMMETRIC_SECRET_ALGORITHM);
return secretKey;
} /**
* 加密
* @param data
* @param key
* @return
* @throws Exception
*/
public static String encrypt(String data,SecretKey key)throws Exception{
Cipher cipher = Cipher.getInstance(key.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = cipher.doFinal(data.getBytes("UTF-8"));
return Base64Util.encode(encryptedData);
} /**
* 解密
* @param data
* @param key
* @return
* @throws Exception
*/
public static String decrypt(String data,SecretKey key)throws Exception{
byte[] encryptedData = Base64Util.decode(data);
Cipher cipher = Cipher.getInstance(key.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedData = cipher.doFinal(encryptedData);
return new String(decryptedData,"UTF-8");
}

不要被它的长度吓到,它做的事情其实很简单,就是生成密钥对和加密解密。生成密钥对,加密和解密在之前都见过,这里最重要的方法是使用来自两方的公钥和私钥生成一个本地密钥:

    /**
* 根据一方公钥和另外一方私钥构建本地密钥
* @param publicKey
* @param privateKey
* @return
* @throws Exception
*/
public static SecretKey getAgreementSecretKey(String publicKey,String privateKey)throws Exception{
PublicKey pubKey = getPublicKey(publicKey);
PrivateKey priKey = getPrivateKey(privateKey); return getAgreementSecretKey(pubKey,priKey); } public static SecretKey getAgreementSecretKey(PublicKey pubKey,PrivateKey priKey)throws Exception{
KeyAgreement argeement = KeyAgreement.getInstance(pubKey.getAlgorithm());
argeement.init(priKey);
argeement.doPhase(pubKey, true); SecretKey secretKey = argeement.generateSecret(SYMMETRIC_SECRET_ALGORITHM);
return secretKey;

完整客户端和服务端代码如下:

/**
* 数据传输客户端
* @author huqiao
*/
public class Client { private String publicKey;
private String privateKey;
private SecretKey key; private Server server; public Client(Server server){
this.server = server;
String serverPublicKey = server.getPublicKey();
try{
String[] keyPair = DHUtil.getStringKeyPair(serverPublicKey);
publicKey = keyPair[0];
privateKey = keyPair[1];
key = DHUtil.getAgreementSecretKey(serverPublicKey, privateKey);
}catch(Exception e){
e.printStackTrace();
}
} public boolean login(String user,String pwd){
String data = "user=" + user + "&pwd=" + pwd;
try {
data = DHUtil.encrypt(data, key);
} catch (Exception e) {
e.printStackTrace();
}
String response = server.service(data,publicKey);
System.out.println("Login Response:" + response);
return response.equals("OK");
}
}
/**
* 数据处理服务端
* @author huqiao
*/
public class Server { private String publicKey;
private String privateKey;
private SecretKey key; public Server(){
try {
String[] keyPair = DHUtil.getStringKeyPair();
publicKey = keyPair[0];
privateKey = keyPair[1];
} catch (Exception e) {
e.printStackTrace();
} } public String service(String data,String clientPublicKey){
System.out.println("----------------Data received at Server:----------------\r\n"+ data);
System.out.println("----------------Client PublicKey received at Server:----------------\r\n"+clientPublicKey);
try {
key = DHUtil.getAgreementSecretKey(clientPublicKey, privateKey);
String decryptedData = DHUtil.decrypt(data, key);
System.out.println("Data decryped:" + decryptedData);
if(verfiy(decryptedData)){
return "OK";
}else{
return "Error"; }
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
} private boolean verfiy(String decryptedData) {
//解析用户名和密码,进行验证
return true;
} /**
* 明文拿到服务端公钥
* @return
*/
public String getPublicKey(){
return publicKey;
}
}

测试:

public class DHTest {

    public static void main(String[] args) {
Server server = new Server(); Client client = new Client(server);
boolean loginSuccess = client.login("admin", "123456"); System.out.println("login success:" + loginSuccess);
}
}

测试结果:

----------------Data received at Server:----------------
pVWbVMP57wkLftZN3bXx1mf4631yTMlxJ+hnMm4Dwmg=
----------------Client PublicKey received at Server:----------------
MIIBpzCCARsGCSqGSIb3DQEDATCCAQwCgYEA/X9TgR11EilS30qcLuzk5/YRt1I870QAwx4/gLZR
JmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWkn5/oBHsQIsJPu6nX/rfGG/g7
V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HXKu/yIgMZndFIAccCgYEA9+GghdabPd7LvKtc
NrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotU
fI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7P
SSoCAgIAA4GFAAKBgQC+WT4qNq/Yay1WFA89n5IOy+hJa8JQh4R0uyy5Yfo2ckgQ4cjh/u5GPKev
Ua2B3vQVFEifKSn7tfP5bmYMQ5IZLPJ3JrP2m/QAjQ1T7swG/Kbtfc4eTgq+wpnb2LbDoznKGN28
Mcrbf4HkwZ8QK0M26CySSEQCFliWydd6u/vl0A==
Data decryped:user=admin&pwd=123456
Login Response:OK
login success:true

DSA

DSA的全称为数字签名算法(Digital Signature Algorithm),它与RSA的区别在于它只用于签名,并且它的速度比RSA要快。在安全性上两者差不多。

因为在RSA中已经说到过签名以及验证的过程,DSA和它完全类似:

public class DSAUtil {

    static final String ALGORITHM = "DSA";

    private static KeyPair getKeyPair()throws Exception{
KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM);
generator.initialize(1024);
return generator.genKeyPair();
} /**
* 用私钥签名
* @param data
* @param privateKey
* @return
*/
public static String sign(String data,String privateKey)throws Exception{
PrivateKey priKey = getPrivateKey(privateKey);
Signature sign = Signature.getInstance(ALGORITHM);
sign.initSign(priKey);
sign.update(data.getBytes("UTF-8"));
byte[] signBytes = sign.sign();
return Base64Util.encode(signBytes);
} /**
* 用公钥进行签名验证
* @param data
* @param publicKey
* @param signData
* @return
* @throws Exception
*/
public static boolean verify(String data,String publicKey,String signData)throws Exception{
PublicKey pubKey = getPublicKey(publicKey);
Signature sign = Signature.getInstance(ALGORITHM);
sign.initVerify(pubKey);
sign.update(data.getBytes("UTF-8"));
return sign.verify(Base64Util.decode(signData));
} private static PublicKey getPublicKey(String key)throws Exception{
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PublicKey k = keyFactory.generatePublic(keySpec);
return k;
} private static PrivateKey getPrivateKey(String key)throws Exception{
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64Util.decode(key));
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PrivateKey k = keyFactory.generatePrivate(keySpec);
return k;
} /**
* 获取字符串类型的密钥对
* @return
* @throws Exception
*/
public static String[] getStringKeyPair()throws Exception{
KeyPair keyPair = getKeyPair();
return keyPairToStringArray(keyPair);
} private static String[] keyPairToStringArray(KeyPair keyPair){
String[] res = new String[2];
PublicKey pubKey = keyPair.getPublic();
PrivateKey priKey = keyPair.getPrivate(); res[0] = Base64Util.encode(pubKey.getEncoded());
res[1] = Base64Util.encode(priKey.getEncoded()); return res;
} public static void main(String[] args) throws Exception{
String data = "Hello,DSA";
String[] keyPair = getStringKeyPair();
String pubKey = keyPair[0];
String priKey = keyPair[1];
System.out.println("原文:" + data);
System.out.println("---------Public Key----------");
System.out.println(pubKey);
System.out.println("---------Private Key----------");
System.out.println(priKey);
System.out.println(); String signData = sign(data, priKey);
System.out.println("Sign Data:" + signData);
System.out.println("Verify Result:" + verify(data, pubKey, signData)); }
}

ECC

ECC-Elliptic Curves Cryptography,椭圆曲线密码编码学,是目前已知的公钥体制中,对每比特所提供加密强度最高的一种体制。ECC算法相当耗费资源,如果单纯使用CPU进行加密/解密,效率低下。目前JDK9都没有实现ECC的加密解密,仅仅提供ECC的秘钥生成。

可以自己去实现ECC的Provider。因为Java的安全框架(JCA)提供了密钥生成的扩展机制(JCE)。参考这里如何实现一个Provider:

How to Implement a Provider in the Java Cryptography Architecture

其他相关文章:

参考资料:

http://snowolf.iteye.com/blog/381767

http://snowolf.iteye.com/blog/382422

http://snowolf.iteye.com/blog/382749

Java加密与解密笔记(三) 非对称加密的更多相关文章

  1. Java加密与解密笔记(二) 对称加密

    前面的仅仅是做了编码或者摘要,下面看看真正的加密技术. DES public class DESUtil { static final String ALGORITHM = "DES&quo ...

  2. Java加密与解密笔记(一) Base64和数据摘要算法

    对加密解密下面的内容一定要先理解: 甲乙双方要通信,中间的连接可能被人窃听甚至篡改.解决办法就是把传输的内容进行加密,用密文去传输,这样即使被监听也没办法知道信息的具体内容. 加密时,甲乙双方可以约定 ...

  3. Java加密与解密笔记(四) 高级应用

    术语列表: CA:证书颁发认证机构(Certificate Authority) PEM:隐私增强邮件(Privacy Enhanced Mail),是OpenSSL使用的一种密钥文件. PKI:公钥 ...

  4. java之jvm学习笔记三(Class文件检验器)

    java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...

  5. 使用java实现对称加密解密(AES),非对称加密解密(RSA)

    对称加密:双方采用同样的秘钥进行加密和解密.特点是速度快,但是安全性没有非对称加密高 非对称加密:接收方生成的公有秘钥公布给发送方,发送方使用该公有秘钥加密之后,发送给接收方,然后接收方使用私有秘钥解 ...

  6. PHP中使用OpenSSL生成RSA公钥私钥及进行加密解密示例(非对称加密)

    php服务端与客户端交互.提供开放api时,通常需要对敏感的部分api数据传输进行数据加密,这时候rsa非对称加密就能派上用处了,下面通过一个例子来说明如何用php来实现数据的加密解密 先了解一下关于 ...

  7. 加密解密知识 php非对称加密

    function test1(){ $config = array( "digest_alg" => "sha1", "private_key_ ...

  8. Java Des加解密方法(c#加密Java解密)

    最近我们用Java把一个用.net编写的老系统重新做了翻版,但是登录还是用.net的登录.这样就会遇到一个比较棘手的问题,我们登录用的cookie信息都是.net用des加密的,但我们不得不用Java ...

  9. Java实现 LeetCode 535 TinyURL 的加密与解密(位运算加密)

    535. TinyURL 的加密与解密 TinyURL是一种URL简化服务, 比如:当你输入一个URL https://leetcode.com/problems/design-tinyurl 时,它 ...

随机推荐

  1. Oracle创建表空间、用户、分配权限语句

    --创建表空间 create tablespace 表空间名字 logging datafile 'E:\app\sinohuarui\oradata\orcl\文件名.dbf' size 50m a ...

  2. 项目实战3—Keepalived 实现高可用

    实现基于Keepalived高可用集群网站架构 环境:随着业务的发展,网站的访问量越来越大,网站访问量已经从原来的1000QPS,变为3000QPS,目前业务已经通过集群LVS架构可做到随时拓展,后端 ...

  3. 编程语言 : Java的动态Web解决方案泛谈

    文章概述 最近发现很久前一股脑地学习框架,发觉越发迷糊.知道了框架只是暂时的,重点是基础的技术.该文大篇幅回顾Servlet技术栈和简要的MVC框架. 至于为什么学J2EE,额,大家都用框架,可框架也 ...

  4. 【朝花夕拾】朝花夕拾-Robot Framework实战演练之开篇

    (原创文章,转载请注明出处.) 开博了,简单感慨两句. 前些年一直在做质量体系建设及团队管理的事,忽略了对测试技术热度的保持,这两年有幸重回开发测试第一线,颇感欣喜. 近期随着公司新业务的开展,需要快 ...

  5. jqGrid数据表格

    方式一: <!DOCTYPE html><html><head><meta charset="utf-8" /><title& ...

  6. markdown简述

     前端开发的工具    编辑器:   1. 轻量级的,依靠插件:sublime:atom(github):vs code(miscrosaft)   2. 集成的:DW:webstorm:hbuild ...

  7. EDI数据导入的注意事项&常见异常处理

    EXCEL表格注意事项: •      编码是0开头的,格式必须是文本,否则前面请加字母: •      注意全角半角,中文标点英文标点: •      编号文字类开头和结尾不要有空格,姓名中间也不要 ...

  8. 字节、十六进制字符串相互转换(asc2hex、hex2asc)

    //================================================================== /** 功能: 将16进制数组转换成asc字符数组(短转长) ...

  9. A:分段函数-poj

    A:分段函数 总时间限制:  1000ms 内存限制:  65536kB 描述 编写程序,计算下列分段函数y=f(x)的值. y=-x+2.5; 0 <= x < 5 y=2-1.5(x- ...

  10. Unity20172.0 Android平台打包

    Android SDK及Jdk百度网盘下载链接:https://pan.baidu.com/s/1dFbEmdz 密码:pt7b Unity20172.0 Android平台打包 简介说明: 第一步: ...