Java加密解密之非对称加密

非对称加密算法需要两个密钥来进行加密和解密,这两个秘钥是公开密钥(public key,简称公钥)和私有密钥(private key,简称私钥)。使用公钥加密的,要使用私钥解密。反之,使用私钥加密的,要使用公钥解密。


和对称加密的区别是:
对称加密:加密和解密时使用的是同一个秘钥
非对称加密:加密和解密时使用的是不同的秘钥


非对称加密与对称加密相比,其安全性更好:对称加密的通信双方使用相同的秘钥,如果一方的秘钥遭泄露,那么整个通信就会被破解。而非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,秘钥是自己保存的,不需要像对称加密那样在通信之前要先同步秘钥。
非对称加密的缺点是加密和解密花费时间长、速度慢,只适合对少量数据进行加密。


非对称加密中使用的主要算法有:RSA、DSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等。


下面演示一个Java(1.8.0_144)使用RSA算法的非对称加密

package com.security.cipher;

import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.Cipher;

/**
 * 这里面的API里面有很多是调用getInstance方法,这个方法的参数有algorithm或者transformation
 * 一:algorithm:算法
 * 
 * 二:transformation:有两种格式
 * 1:算法/模式/填充方式。如:DES/CBC/PKCS5Padding
 * 2:算法。                              如:DES
 * 
 * 其中,algorithm、transformation的值,不区分大小写
 * 
 * Java加密解密官方参考文档:
 * https://docs.oracle.com/javase/8/docs/technotes/guides/security/index.html
 * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html
 */
public class CipherTest {
	
	/*
	 * 使用KeyPairGenerator生成密钥对KeyPair
	 * KeyPair对象中有公钥、私钥
	 * 
	 * 其中,KeyPairGenerator.getInstance(algorithm)支持的算法有:RSA、DSA
	 * 全部支持的算法见官方文档
	 * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyPairGenerator
	 *  
	 */
	public static KeyPair newKeyPair(String algorithm) throws NoSuchAlgorithmException {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		return keyPair;
	}
	
	/**
	 * 加密,对字符串进行加密,返回结果为byte数组
	 * 保存的时候,可以把byte数组进行base64编码成字符串,或者把byte数组转换成16进制的字符串
	 * 
	 * 其中,transformation支持的全部算法见官方文档:
	 * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher
	 */
	public static byte[] encrypt(String transformation, Key key, String password) throws Exception {
		Cipher cipher = Cipher.getInstance(transformation);
		//加密模式
		cipher.init(Cipher.ENCRYPT_MODE, key);
		return cipher.doFinal(password.getBytes());
	}
	
	/**
	 * 解密,返回结果为原始字符串
	 * 
	 * 其中,transformation支持的全部算法见官方文档:
	 * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#Cipher
	 */
	public static String decrypt(String transformation, Key key, byte[] data) throws Exception {
		Cipher cipher = Cipher.getInstance(transformation);
		//解密模式
		cipher.init(Cipher.DECRYPT_MODE, key);
		byte[] result = cipher.doFinal(data);
		String password = new String(result);
		return password;
	}
	
	public static void main(String[] args) throws Exception {
		String password = "123456";
		
		//这里指定的算法,必须是非对称加密算法
		String algorithm = "RSA";
		String transformation = algorithm;
		
		//使用非对称加密,需要一对秘钥,这一对秘钥,可以从KeyPair对象中获取
		KeyPair keyPair = newKeyPair(algorithm);
		
		//获取公钥
		PublicKey publicKey = keyPair.getPublic();
		
		//获取私钥
		PrivateKey privateKey = keyPair.getPrivate();
		
		//公钥加密私钥解密
		{
			//公钥加密
			byte[] passData = encrypt(transformation, publicKey, password);
			//私钥解密
			String pass = decrypt(transformation, privateKey, passData);
			
			System.out.println("解密后的密码 : " + pass);
		}
		
		//私钥加密公钥解密
		{
			//私钥加密
			byte[] passData = encrypt(transformation, privateKey, password);
			//公钥解密
			String pass = decrypt(transformation, publicKey, passData);
			
			System.out.println("解密后的密码 : " + pass);
		}
	}
}

可以看出,用法和对称加密差不多。关键是在于要有一个公钥,一个私钥。

上面的示例演示的是使用KeyPairGenerator、KeyPair对象获取公钥、私钥。除了这种方法,还有一个方法,就是使用keytool。下面将演示如何使用keytool获取公钥私钥


keytool -genkeypair -alias testkey -keyalg RSA -keystore test.jks -keypass 112233 -storetype jks -storepass 123456

输入命令之后,根据提示,输入对应的信息


这样,就可以得到一个test.jks的文件,这个文件中,就有公钥,私钥。获取方式如下:

public static KeyPair newKeyPairByKeyStore(String path) throws Exception {
	KeyStore keyStore = KeyStore.getInstance("jks");
	String storePass = "123456";
	
	try(InputStream input = new FileInputStream(path)) {
		keyStore.load(input, storePass.toCharArray());
	}
	
	String keyPass = "112233";
	PrivateKey privateKey = (PrivateKey)keyStore.getKey("testkey", keyPass.toCharArray());
	
	PublicKey publicKey = keyStore.getCertificate("testkey").getPublicKey();
	
	return new KeyPair(publicKey, privateKey);
}

同样的,使用openssl也可以










  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值