All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xiaoleilu.hutool.crypto.asymmetric.RSA Maven / Gradle / Ivy

package com.xiaoleilu.hutool.crypto.asymmetric;

import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAKey;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;

import javax.crypto.Cipher;

import com.xiaoleilu.hutool.codec.BCD;
import com.xiaoleilu.hutool.crypto.CryptoException;
import com.xiaoleilu.hutool.crypto.SecureUtil;
import com.xiaoleilu.hutool.util.CharsetUtil;
import com.xiaoleilu.hutool.util.StrUtil;

/**
 * RSA加密算法
 * 
 * @author Looly
 *
 */
public class RSA extends AsymmetricCrypto {

	private static final AsymmetricAlgorithm ALGORITHM_RSA = AsymmetricAlgorithm.RSA;

	// ------------------------------------------------------------------ Static method start
	/**
	 * 生成RSA私钥
	 * 
	 * @param modulus N特征值
	 * @param privateExponent d特征值
	 * @return {@link PrivateKey}
	 */
	public static PrivateKey generatePrivateKey(BigInteger modulus, BigInteger privateExponent) {
		return SecureUtil.generatePrivateKey(ALGORITHM_RSA.getValue(), new RSAPrivateKeySpec(modulus, privateExponent));
	}

	/**
	 * 生成RSA公钥
	 * 
	 * @param modulus N特征值
	 * @param publicExponent e特征值
	 * @return {@link PublicKey}
	 */
	public static PublicKey generatePublicKey(BigInteger modulus, BigInteger publicExponent) {
		return SecureUtil.generatePublicKey(ALGORITHM_RSA.getValue(), new RSAPublicKeySpec(modulus, publicExponent));
	}
	// ------------------------------------------------------------------ Static method end

	// ------------------------------------------------------------------ Constructor start
	/**
	 * 构造,生成新的私钥公钥对
	 */
	public RSA() {
		super(ALGORITHM_RSA);
	}

	/**
	 * 构造
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 * * @param privateKeyBase64 私钥Base64 * @param publicKeyBase64 公钥Base64 */ public RSA(String privateKeyBase64, String publicKeyBase64) { super(ALGORITHM_RSA, privateKeyBase64, publicKeyBase64); } /** * 构造
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 * * @param privateKey 私钥 * @param publicKey 公钥 */ public RSA(byte[] privateKey, byte[] publicKey) { super(ALGORITHM_RSA, privateKey, publicKey); } /** * 构造
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 * * @param modulus N特征值 * @param privateExponent d特征值 * @param publicExponent e特征值 * @since 3.1.1 */ public RSA(BigInteger modulus, BigInteger privateExponent, BigInteger publicExponent) { this(generatePrivateKey(modulus, privateExponent), generatePublicKey(modulus, publicExponent)); } /** * 构造
* 私钥和公钥同时为空时生成一对新的私钥和公钥
* 私钥和公钥可以单独传入一个,如此则只能使用此钥匙来做加密或者解密 * * @param privateKey 私钥 * @param publicKey 公钥 * @since 3.1.1 */ public RSA(PrivateKey privateKey, PublicKey publicKey) { super(ALGORITHM_RSA, privateKey, publicKey); } // ------------------------------------------------------------------ Constructor end /** * 分组加密 * * @param data 数据 * @param keyType 密钥类型 * @return 加密后的密文 * @throws CryptoException 加密异常 */ public String encryptStr(String data, KeyType keyType) { return encryptStr(data, keyType, CharsetUtil.CHARSET_UTF_8); } /** * 分组加密 * * @param data 数据 * @param keyType 密钥类型 * @param charset 加密前编码 * @return 加密后的密文 * @throws CryptoException 加密异常 * @since 3.1.1 */ public String encryptStr(String data, KeyType keyType, Charset charset) { Key key = getKeyByType(keyType); // 加密数据长度 <= 模长-11 int maxBlockSize = ((RSAKey) key).getModulus().bitLength() / 8 - 11; final byte[] dataBytes = StrUtil.bytes(data, charset); final int inputLen = dataBytes.length; lock.lock(); try (ByteArrayOutputStream out = new ByteArrayOutputStream();) { clipher.init(Cipher.ENCRYPT_MODE, key); int offSet = 0; byte[] cache; // 剩余长度 int remainLength = inputLen; // 对数据分段加密 while (remainLength > 0) { cache = clipher.doFinal(dataBytes, offSet, Math.min(remainLength, maxBlockSize)); out.write(cache, 0, cache.length); offSet += maxBlockSize; remainLength = inputLen - offSet; } return BCD.bcdToStr(out.toByteArray()); } catch (Exception e) { throw new CryptoException(e); } finally { lock.unlock(); } } /** * 分组解密 * * @param data 数据 * @param keyType 密钥类型 * @return 解密后的密文 */ public String decryptStr(String data, KeyType keyType) { return decryptStr(data, keyType, CharsetUtil.CHARSET_UTF_8); } /** * 分组解密 * * @param data 数据 * @param keyType 密钥类型 * @param charset 加密前编码 * @return 解密后的密文 * @since 3.1.1 */ public String decryptStr(String data, KeyType keyType, Charset charset) { final Key key = getKeyByType(keyType); // 模长 final int maxBlockSize = ((RSAKey) key).getModulus().bitLength() / 8; byte[] dataBytes = BCD.ascToBcd(StrUtil.bytes(data, charset)); int inputLen = dataBytes.length; lock.lock(); try (ByteArrayOutputStream out = new ByteArrayOutputStream();) { clipher.init(Cipher.DECRYPT_MODE, key); int offSet = 0; byte[] cache; // 剩余长度 int remainLength = inputLen; // 对数据分段解密 while (remainLength > 0) { cache = clipher.doFinal(dataBytes, offSet, Math.min(remainLength, maxBlockSize)); out.write(cache, 0, cache.length); offSet += maxBlockSize; remainLength = inputLen - offSet; } return StrUtil.str(out.toByteArray(), charset); } catch (Exception e) { throw new CryptoException(e); } finally { lock.unlock(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy