java-RSA加密解密,支持分段加解密

java-RSA加密解密,支持分段加解密


RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。
RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
RSA的算法涉及三个参数,n、e1、e2。
n:密钥长度,n是两个大质数p、q的积,它的二进制数位数,就是所谓的密钥长度。
e1:(n,e1)为公钥;
e2:(n,e2)为私钥
e1和e2是一对相关的值,e1可以任意取,但要求e1与(p-1)*(q-1)互质;再选择e2,要求(e2*e1)mod((p-1)*(q-1))=1。
(n,e1),(n,e2)就是密钥对。其中(n,e1)为公钥,(n,e2)为私钥。


一、支持密钥对生成、分段加密的帮助类
package me.grass.secret;

import java.io.ByteArrayOutputStream;

/**
 *
 * @author xxj
 */
public class RsaHelper {
	/**
	 * 生成公钥、私钥对(keysize=1024)
	 * @param keySize
	 * @return
	 */
	public RsaHelper.KeyPairInfo getKeyPair() {
		return getKeyPair(1024);
	}
	/**
	 * 生成公钥、私钥对
	 * @param keySize
	 * @return
	 */
	public RsaHelper.KeyPairInfo getKeyPair(int keySize) {
		try {
			KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
			// 初始化密钥对生成器,密钥大小一般要大于1024位,
//			String aa=String.valueOf(new Random().nextInt(999999999));
//			SecureRandom random = new SecureRandom(aa.getBytes()); //?????
//			keyPairGen.initialize(keySize,random);
			keyPairGen.initialize(keySize);
			// 生成一个密钥对,保存在keyPair中
			KeyPair keyPair = keyPairGen.generateKeyPair();
			// 得到私钥
			RSAPrivateKey oraprivateKey = (RSAPrivateKey) keyPair.getPrivate();
			// 得到公钥
			RSAPublicKey orapublicKey = (RSAPublicKey) keyPair.getPublic();
			
			RsaHelper.KeyPairInfo pairInfo = new RsaHelper.KeyPairInfo(keySize);
			//公钥
			byte[] publicKeybyte = orapublicKey.getEncoded();
			String publicKeyString = Base64.encodeBase64String(publicKeybyte);
			pairInfo.setPublicKey(publicKeyString);
			//私钥
			byte[] privateKeybyte = oraprivateKey.getEncoded();
			String privateKeyString = Base64.encodeBase64String(privateKeybyte);
			pairInfo.setPrivateKey(privateKeyString);
			
			return pairInfo;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 获取公钥对象
	 * @param publicKeyBase64
	 * @return
	 * @throws InvalidKeySpecException
	 * @throws NoSuchAlgorithmException
	 */
	public PublicKey getPublicKey(String publicKeyBase64) 
			throws InvalidKeySpecException,NoSuchAlgorithmException{

		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		X509EncodedKeySpec publicpkcs8KeySpec =
				new X509EncodedKeySpec(Base64.decodeBase64(publicKeyBase64));
		PublicKey publicKey = keyFactory.generatePublic(publicpkcs8KeySpec);
		return publicKey;
	}
	/**
	 * 获取私钥对象
	 * @param privateKeyBase64
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeySpecException
	 */
	public PrivateKey getPrivateKey(String privateKeyBase64)
			throws NoSuchAlgorithmException, InvalidKeySpecException{
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PKCS8EncodedKeySpec privatekcs8KeySpec = 
				new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyBase64));		
		PrivateKey privateKey = keyFactory.generatePrivate(privatekcs8KeySpec);
		return privateKey;
	}
	/**
	 * 使用共钥加密
	 * @param content 待加密内容
	 * @param publicKeyBase64  公钥 base64 编码
	 * @return 经过 base64 编码后的字符串
	 */
	public String encipher(String content,String publicKeyBase64){
		return encipher(content,publicKeyBase64,-1);
	}
	/**
	 * 使用共钥加密(分段加密)
	 * @param content 待加密内容
	 * @param publicKeyBase64  公钥 base64 编码
	 * @param segmentSize分段大小,一般小于 keySize/8(段小于等于0时,将不使用分段加密)
	 * @return 经过 base64 编码后的字符串
	 */
	public String encipher(String content,String publicKeyBase64,int segmentSize){
		try {
			PublicKey publicKey = getPublicKey(publicKeyBase64);
			return encipher(content,publicKey,segmentSize);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 分段加密
	 * @param ciphertext 密文
	 * @param key 加密秘钥
	 * @param segmentSize 分段大小,<=0 不分段
	 * @return
	 */
	public String encipher(String ciphertext,java.security.Key key,int segmentSize){
		try {
			// 用公钥加密
			byte[] srcBytes = ciphertext.getBytes();
			
			// Cipher负责完成加密或解密工作,基于RSA
			Cipher cipher = Cipher.getInstance("RSA");
			// 根据公钥,对Cipher对象进行初始化
			cipher.init(Cipher.ENCRYPT_MODE, key);
			byte[] resultBytes = null;

			if(segmentSize>0)
				resultBytes = cipherDoFinal(cipher,srcBytes,segmentSize); //分段加密
			else
				resultBytes = cipher.doFinal(srcBytes);
			
			String base64Str =  Base64.encodeBase64String(resultBytes);		
			return base64Str;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 分段大小
	 * @param cipher
	 * @param srcBytes
	 * @param segmentSize
	 * @return
	 * @throws IllegalBlockSizeException
	 * @throws BadPaddingException
	 * @throws IOException
	 */
	private byte[] cipherDoFinal(Cipher cipher,byte[] srcBytes,int segmentSize) 
			throws IllegalBlockSizeException, BadPaddingException, IOException{
		if(segmentSize<=0)
			throw new RuntimeException("分段大小必须大于0");
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int inputLen = srcBytes.length;
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段解密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > segmentSize) {
				cache = cipher.doFinal(srcBytes, offSet, segmentSize);
			} else {
				cache = cipher.doFinal(srcBytes, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * segmentSize;
		}
		byte[] data = out.toByteArray();
		out.close();
		return data;
	}
	/**
	 * 使用私钥解密
	 * @param contentBase64 待加密内容,base64 编码
	 * @param privateKeyBase64  私钥 base64 编码
	 * @segmentSize 分段大小
	 * @return
	 */
	public String decipher(String contentBase64,String privateKeyBase64){
		return decipher(contentBase64, privateKeyBase64,-1);
	}
	/**
	 * 使用私钥解密(分段解密)
	 * @param contentBase64 待加密内容,base64 编码
	 * @param privateKeyBase64  私钥 base64 编码
	 * @segmentSize 分段大小
	 * @return
	 */
	public String decipher(String contentBase64,String privateKeyBase64,int segmentSize){		
		try {
			PrivateKey privateKey = getPrivateKey(privateKeyBase64);
			return decipher(contentBase64, privateKey,segmentSize);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 分段解密
	 * @param contentBase64 密文
	 * @param key 解密秘钥
	 * @param segmentSize 分段大小(小于等于0不分段)
	 * @return
	 */
	public String decipher(String contentBase64,java.security.Key key,int segmentSize){
		try {
			// 用私钥解密
			byte[] srcBytes = Base64.decodeBase64(contentBase64);	
			// Cipher负责完成加密或解密工作,基于RSA
			Cipher deCipher = Cipher.getInstance("RSA");
			// 根据公钥,对Cipher对象进行初始化
			deCipher.init(Cipher.DECRYPT_MODE, key);
			byte[] decBytes = null;//deCipher.doFinal(srcBytes);
			if(segmentSize>0)
				decBytes = cipherDoFinal(deCipher,srcBytes,segmentSize); //分段加密
			else
				decBytes = deCipher.doFinal(srcBytes);
			
			String decrytStr=new String(decBytes);
			return decrytStr;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 秘钥对
	 *
	 */
	public class KeyPairInfo{
		public KeyPairInfo(int keySize){
			setKeySize(keySize);
		}
		public KeyPairInfo(String publicKey,String privateKey){
			setPrivateKey(privateKey);
			setPublicKey(publicKey);
		}
		String privateKey;
		String publicKey;
		int keySize=0;
		public String getPrivateKey() {
			return privateKey;
		}
		public void setPrivateKey(String privateKey) {
			this.privateKey = privateKey;
		}
		public String getPublicKey() {
			return publicKey;
		}
		public void setPublicKey(String publicKey) {
			this.publicKey = publicKey;
		}
		public int getKeySize() {
			return keySize;
		}
		public void setKeySize(int keySize) {
			this.keySize = keySize;
		}
	}
	
}



二、测试分段加密;公钥加密私钥解密;私钥机密公钥解密;
package me.grass.secret;

import static org.junit.Assert.assertTrue;

import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;

import org.junit.Test;

import me.grass.coder.Debug;

/** 
*
* @author xxj 
*/
public class RsaHelperTest {
	/**
	 * 获取秘钥对
	 * 
	 */
	@Test
	public void getKeyPairTest() {
		RsaHelper rsa = new RsaHelper();
		RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024);
		assertTrue(info!=null);
		Debug.printFormat("公钥:{0}", info.getPublicKey());
		Debug.printFormat("私钥:{0}", info.getPrivateKey());
	}
	/**
	 * rsa 不分段加密,使用莫值为1024 时y,明文不能超过 117
	 * 
	 */
	@Test
	public void encipherTest() {
		RsaHelper rsa = new RsaHelper();
		RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024); //每次调用的公钥 私钥都一样
		assertTrue(info!=null);
		Debug.printFormat("公钥:{0}", info.getPublicKey());
		Debug.printFormat("私钥:{0}", info.getPrivateKey());
		
		String content="rsa加密、解密测试";
		Debug.printFormat("明文:{0}", content);
		
		String ciphertext = rsa.encipher(content, info.getPublicKey());
		Debug.printFormat("密文:{0}", ciphertext);
		
		String deTxt = rsa.decipher(ciphertext, info.getPrivateKey());
		Debug.printFormat("解密:{0}", deTxt);
		
		assertTrue(content.equals(deTxt));
	}
	/**
	 * rsa 分段机密测试(长内容加密)
	 * 
	 */
	@Test
	public void encipherSegmentTest() {
		int keySize=2048;
		RsaHelper rsa = new RsaHelper();
		RsaHelper.KeyPairInfo info = rsa.getKeyPair(keySize); //每次调用的公钥 私钥都一样
		assertTrue(info!=null);
		Debug.printFormat("公钥:{0}", info.getPublicKey());
		Debug.printFormat("私钥:{0}", info.getPrivateKey());
		
		String content="1.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "2.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "3.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "4.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "5.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "6.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "7.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "8.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "9.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n"
				+ "0.rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;rsa加密、解密测试;\r\n";
		Debug.printFormat("明文:{0}", content);
		
		int enSegmentSize=245;//keysize=1024时,分段不能大于117 ;keysize>=2048时,分段不能大于keySize/8+128;
		String ciphertext = rsa.encipher(content, info.getPublicKey(),enSegmentSize);
		Debug.printFormat("密文:{0}", ciphertext);

		int deSegmentSize=256;//等于keySize/8
		String deTxt = rsa.decipher(ciphertext, info.getPrivateKey(),deSegmentSize);
		Debug.printFormat("解密:{0}", deTxt);
		
		assertTrue(content.equals(deTxt));
	}
	/**
	 * 测试公钥加密、私钥解密
	 * 
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeySpecException 
	 */
	@Test
	public void encipherUsePublic() 
			throws InvalidKeySpecException, NoSuchAlgorithmException{
		RsaHelper rsa = new RsaHelper();
		RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024); //每次调用的公钥 私钥都一样
		assertTrue(info!=null);
		Debug.printFormat("公钥:{0}", info.getPublicKey());
		Debug.printFormat("私钥:{0}", info.getPrivateKey());
		
		String content="rsa加密、解密测试";
		Debug.printFormat("明文:{0}", content);
		
		PublicKey pubKey = rsa.getPublicKey(info.getPublicKey());
		String ciphertext = rsa.encipher(content, pubKey,0);
		Debug.printFormat("密文:{0}", ciphertext);

		PrivateKey privKey = rsa.getPrivateKey(info.getPrivateKey());
		String deTxt = rsa.decipher(ciphertext,privKey,0);
		Debug.printFormat("解密:{0}", deTxt);
		
		assertTrue(content.equals(deTxt));
	}
	/**
	 * 测试公钥加密、私钥解密
	 * 
	 * @throws NoSuchAlgorithmException 
	 * @throws InvalidKeySpecException 
	 */
	@Test
	public void encipherUsePrivateKey() 
			throws InvalidKeySpecException, NoSuchAlgorithmException{
		RsaHelper rsa = new RsaHelper();
		RsaHelper.KeyPairInfo info = rsa.getKeyPair(1024); //每次调用的公钥 私钥都一样
		assertTrue(info!=null);
		Debug.printFormat("公钥:{0}", info.getPublicKey());
		Debug.printFormat("私钥:{0}", info.getPrivateKey());
		
		String content="rsa加密、解密测试";
		Debug.printFormat("明文:{0}", content);

		PrivateKey privKey = rsa.getPrivateKey(info.getPrivateKey());
		String ciphertext = rsa.encipher(content, privKey,0);
		Debug.printFormat("密文:{0}", ciphertext);

		PublicKey pubKey = rsa.getPublicKey(info.getPublicKey());
		String deTxt = rsa.decipher(ciphertext,pubKey,0);
		Debug.printFormat("解密:{0}", deTxt);
		
		assertTrue(content.equals(deTxt));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值