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

net.guerlab.cloud.rsa.RsaUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2018-2024 guerlab.net and other contributors.
 *
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.gnu.org/licenses/lgpl-3.0.html
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.guerlab.cloud.rsa;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;

import jakarta.annotation.Nullable;

/**
 * RSA工具类.
 *
 * @author guer
 */
public final class RsaUtils {

	/**
	 * 加密算法 RSA.
	 */
	public static final String KEY_ALGORITHM = "RSA";

	/**
	 * 变化类型.
	 */
	public static final String TRANSFORMATION = "RSA/ECB/PKCS1PADDING";

	/**
	 * 默认密钥长度.
	 */
	public static final int DEFAULT_KEY_SIZE = 2048;

	/**
	 * 公钥前缀.
	 */
	public static final String PUBLIC_KEY_FILE_PREFIX = "-----BEGIN CERTIFICATE-----";

	/**
	 * 公钥后缀.
	 */
	public static final String PUBLIC_KEY_FILE_SUFFIX = "-----END CERTIFICATE-----";

	/**
	 * 私钥前缀.
	 */
	public static final String PRIVATE_KEY_FILE_PREFIX = "-----BEGIN PRIVATE KEY-----";

	/**
	 * 私钥后缀.
	 */
	public static final String PRIVATE_KEY_FILE_SUFFIX = "-----END PRIVATE KEY-----";

	/**
	 * 单行文本长度.
	 */
	public static final int LINE_LENGTH = 64;

	/**
	 * 换行.
	 */
	public static final String LINE_FEED = "\r\n";

	/**
	 * RSA 最大加密明文长度.
	 */
	private static final int MAX_ENCRYPT_BLOCK = 245;

	/**
	 * RSA 最大解密秘文长度.
	 */
	private static final int MAX_DECRYPT_BLOCK = 256;

	private RsaUtils() {

	}

	/**
	 * 创建公/私钥对.
	 *
	 * @param keySize key长度
	 * @return 公/私钥对
	 */
	public static KeyPair createKeyPair(int keySize) {
		try {
			KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
			keyPairGen.initialize(keySize, new SecureRandom());
			return keyPairGen.generateKeyPair();
		}
		catch (Exception e) {
			throw new RsaException(e.getLocalizedMessage(), e);
		}
	}

	/**
	 * 创建公/私钥对.
	 *
	 * @return 公/私钥对
	 */
	public static KeyPair createKeyPair() {
		return createKeyPair(DEFAULT_KEY_SIZE);
	}

	/**
	 * 构造RSA公/私钥对.
	 *
	 * @param keyPair 公/私钥对
	 * @return RSA公/私钥对
	 */
	public static RsaKeys buildKeys(KeyPair keyPair) {
		Base64.Encoder encoder = Base64.getEncoder();
		RsaKeys rsaKeys = new RsaKeys();
		rsaKeys.setPublicKey(encoder.encodeToString(keyPair.getPublic().getEncoded()));
		rsaKeys.setPrivateKey(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
		return rsaKeys;
	}

	/**
	 * 构造RSA公/私钥对.
	 *
	 * @return RSA公/私钥对
	 */
	public static RsaKeys buildKeys() {
		return buildKeys(createKeyPair());
	}

	/**
	 * 解析公钥.
	 *
	 * @param bytes 公钥byte数组
	 * @return 公钥
	 */
	public static PublicKey parsePublicKey(byte[] bytes) {
		try {
			X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
			KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
			return factory.generatePublic(spec);
		}
		catch (Exception e) {
			throw new RsaException(e.getLocalizedMessage(), e);
		}
	}

	/**
	 * 解析公钥.
	 *
	 * @param keyString 公钥字符串
	 * @return 公钥
	 */
	public static PublicKey parsePublicKey(String keyString) {
		return parsePublicKey(Base64.getDecoder().decode(cleanFormat(keyString)));
	}

	/**
	 * 解析私钥.
	 *
	 * @param bytes 私钥byte数组
	 * @return 私钥
	 */
	public static PrivateKey parsePrivateKey(byte[] bytes) {
		try {
			PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
			KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
			return factory.generatePrivate(spec);
		}
		catch (Exception e) {
			throw new RsaException(e.getLocalizedMessage(), e);
		}
	}

	/**
	 * 解析私钥.
	 *
	 * @param keyString 私钥字符串
	 * @return 私钥
	 */
	public static PrivateKey parsePrivateKey(String keyString) {
		return parsePrivateKey(Base64.getDecoder().decode(cleanFormat(keyString)));
	}

	/**
	 * 清理密钥字符串格式.
	 *
	 * @param keyString 原始字符串
	 * @return 清理后的字符串内容
	 */
	public static String cleanFormat(String keyString) {
		keyString = keyString.replace(PUBLIC_KEY_FILE_PREFIX, "");
		keyString = keyString.replace(PUBLIC_KEY_FILE_SUFFIX, "");
		keyString = keyString.replace(PRIVATE_KEY_FILE_PREFIX, "");
		keyString = keyString.replace(PRIVATE_KEY_FILE_SUFFIX, "");
		keyString = keyString.replace(LINE_FEED, "");
		keyString = keyString.replace("\n", "");
		return keyString;
	}

	/**
	 * 格式化公钥字符串.
	 *
	 * @param keyString 原始字符串
	 * @return 格式化后的公钥字符串
	 */
	public static String formatPublicKey(String keyString) {
		if (keyString.startsWith(PUBLIC_KEY_FILE_PREFIX) && keyString.endsWith(PUBLIC_KEY_FILE_SUFFIX)) {
			return keyString;
		}
		return PUBLIC_KEY_FILE_PREFIX + LINE_FEED + formatKey(keyString) + LINE_FEED + PUBLIC_KEY_FILE_SUFFIX;
	}

	/**
	 * 格式化私钥字符串.
	 *
	 * @param keyString 原始字符串
	 * @return 格式化后的私钥字符串
	 */
	public static String formatPrivateKey(String keyString) {
		if (keyString.startsWith(PRIVATE_KEY_FILE_PREFIX) && keyString.endsWith(PRIVATE_KEY_FILE_SUFFIX)) {
			return keyString;
		}
		return PRIVATE_KEY_FILE_PREFIX + LINE_FEED + formatKey(keyString) + LINE_FEED + PRIVATE_KEY_FILE_SUFFIX;
	}

	/**
	 * 格式化key字符串.
	 *
	 * @param keyString 原始字符串
	 * @return 格式化后的key字符串
	 */
	public static String formatKey(String keyString) {
		StringBuilder result = new StringBuilder();
		while (true) {
			if (keyString.length() > LINE_LENGTH) {
				result.append(keyString, 0, LINE_LENGTH);
				result.append(LINE_FEED);
				keyString = keyString.substring(LINE_LENGTH);
			}
			else {
				result.append(keyString);
				break;
			}
		}

		return result.toString();
	}

	/**
	 * 将RSA公/私钥对写入输出流.
	 *
	 * @param rsaKeys      RSA公/私钥对
	 * @param outputStream 输出流
	 * @throws IOException 当IO发生问题的时候抛出IOException
	 */
	public static void writeTo(RsaKeys rsaKeys, OutputStream outputStream) throws IOException {
		String contentBuilder =
				rsaKeys.getPublicKeyFormattedContent() + LINE_FEED + rsaKeys.getPrivateKeyFormattedContent();
		outputStream.write(contentBuilder.getBytes());
	}

	/**
	 * 从流中读取RSA公/私钥对.
	 *
	 * @param inputStream 输入流
	 * @return RSA公/私钥对
	 * @throws IOException 当IO发生问题的时候抛出IOException
	 */
	@Nullable
	public static RsaKeys read(InputStream inputStream) throws IOException {
		byte[] bytes = inputStream.readAllBytes();
		if (bytes == null || bytes.length == 0) {
			return null;
		}
		String content = new String(bytes);

		String publicKey = readPublicKey(content);
		String privateKey = readPrivateKey(content);

		if (publicKey == null || privateKey == null) {
			return null;
		}

		return new RsaKeys(publicKey, privateKey);
	}

	/**
	 * 从内容中读取公钥内容.
	 *
	 * @param content 待读取内容
	 * @return 公钥内容
	 */
	@Nullable
	public static String readPublicKey(String content) {
		return readKey(content, PUBLIC_KEY_FILE_PREFIX, PUBLIC_KEY_FILE_SUFFIX);
	}

	/**
	 * 从内容中读取私钥内容.
	 *
	 * @param content 待读取内容
	 * @return 私钥内容
	 */
	@Nullable
	public static String readPrivateKey(String content) {
		return readKey(content, PRIVATE_KEY_FILE_PREFIX, PRIVATE_KEY_FILE_SUFFIX);
	}

	/**
	 * 从内容中读取内容.
	 *
	 * @param content 待读取内容
	 * @param prefix  前缀
	 * @param suffix  后缀
	 * @return 内容
	 */
	@Nullable
	public static String readKey(String content, String prefix, String suffix) {
		int startIndex = content.indexOf(prefix);
		int endIndex = content.indexOf(suffix);

		if (startIndex >= 0 && endIndex >= 0) {
			return content.substring(startIndex, endIndex + suffix.length());
		}

		return null;
	}

	/**
	 * 公钥加密.
	 *
	 * @param data      待加密数据
	 * @param publicKey 公钥
	 * @return 加密后数据
	 */
	public static byte[] encryptByPublicKey(byte[] data, PublicKey publicKey) {
		return dataHandler(data, publicKey, Cipher.ENCRYPT_MODE, MAX_ENCRYPT_BLOCK);
	}

	/**
	 * 私钥加密.
	 *
	 * @param data       待加密数据
	 * @param privateKey 私钥
	 * @return 加密后数据
	 */
	public static byte[] encryptByPrivateKey(byte[] data, PrivateKey privateKey) {
		return dataHandler(data, privateKey, Cipher.ENCRYPT_MODE, MAX_ENCRYPT_BLOCK);
	}

	/**
	 * 公钥解密.
	 *
	 * @param data      待解密数据
	 * @param publicKey 公钥
	 * @return 解密后数据
	 */
	public static byte[] decryptByPublicKey(byte[] data, PublicKey publicKey) {
		return dataHandler(data, publicKey, Cipher.DECRYPT_MODE, MAX_DECRYPT_BLOCK);
	}

	/**
	 * 私钥解密.
	 *
	 * @param data       待解密数据
	 * @param privateKey 私钥
	 * @return 解密后数据
	 */
	public static byte[] decryptByPrivateKey(byte[] data, PrivateKey privateKey) {
		return dataHandler(data, privateKey, Cipher.DECRYPT_MODE, MAX_DECRYPT_BLOCK);
	}

	/**
	 * 加密/解密处理.
	 *
	 * @param data          待加密/解密数据
	 * @param key           密钥
	 * @param operationMode 操作方式
	 * @param size          单次处理长度
	 * @return 处理后数据
	 */
	private static byte[] dataHandler(byte[] data, Key key, int operationMode, int size) {
		try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
			Cipher cipher = Cipher.getInstance(TRANSFORMATION);
			cipher.init(operationMode, key);

			byte[] cache;
			int start = 0;
			int end;
			while ((end = data.length - start) > 0) {
				cache = cipher.doFinal(data, start, Math.min(end, size));
				out.write(cache, 0, cache.length);
				start += size;
			}

			return out.toByteArray();
		}
		catch (Exception e) {
			throw new RsaException(e.getLocalizedMessage(), e);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy