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

com.gitlab.summercattle.commons.security.crypto.SmUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitlab.summercattle.commons.security.crypto;

import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.engines.SM2Engine.Mode;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.gitlab.summercattle.commons.exception.CommonException;
import com.gitlab.summercattle.commons.exception.ExceptionWrapUtils;
import com.gitlab.summercattle.commons.security.crypto.constants.PaddingType;

/**
 * 国密工具
 * @author orange
 *
 */
public class SmUtils {

	private static final String SM2_KEY_ALGORITHM = "EC";

	private static final String SM4_KEY_ALGORITHM = "SM4";

	private static final String SM2_ALGORITHM_PARAMETER_SPEC = "sm2p256v1";

	public static KeyPair getSm2EncryptKey() throws CommonException {
		try {
			ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec(SM2_ALGORITHM_PARAMETER_SPEC);
			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(SM2_KEY_ALGORITHM, getProvider());
			keyPairGenerator.initialize(ecGenParameterSpec, new SecureRandom());
			return keyPairGenerator.generateKeyPair();
		}
		catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static PublicKey getSm2PublicKey(byte[] publicKey) throws CommonException {
		if (publicKey == null) {
			throw new CommonException("公有密钥为空");
		}
		try {
			X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
			KeyFactory keyFactory = KeyFactory.getInstance(SM2_KEY_ALGORITHM, getProvider());
			return keyFactory.generatePublic(x509EncodedKeySpec);
		}
		catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static PrivateKey getSm2PrivateKey(byte[] privateKey) throws CommonException {
		if (privateKey == null) {
			throw new CommonException("私有密钥为空");
		}
		try {
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey);
			KeyFactory keyFactory = KeyFactory.getInstance(SM2_KEY_ALGORITHM, getProvider());
			return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		}
		catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static byte[] sm2Encrypt(byte[] data, Mode mode, PublicKey publicKey) throws CommonException {
		if (data == null) {
			throw new CommonException("数据为空");
		}
		if (publicKey == null) {
			throw new CommonException("公有密钥为空");
		}
		if (mode == null) {
			throw new CommonException("国密2模式为空");
		}
		try {
			CipherParameters publicKeyCipherParameters = ECUtil.generatePublicKeyParameter(publicKey);
			ParametersWithRandom parametersWithRandom = new ParametersWithRandom(publicKeyCipherParameters);
			SM2Engine sm2Engine = new SM2Engine(mode);
			sm2Engine.init(true, parametersWithRandom);
			return sm2Engine.processBlock(data, 0, data.length);
		}
		catch (InvalidCipherTextException | InvalidKeyException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static byte[] sm2Decrypt(byte[] encryptData, Mode mode, PrivateKey privateKey) throws CommonException {
		if (encryptData == null) {
			throw new CommonException("加密后的数据为空");
		}
		if (privateKey == null) {
			throw new CommonException("私有密钥为空");
		}
		if (mode == null) {
			throw new CommonException("SM2模式为空");
		}
		try {
			CipherParameters privateKeyCipherParameters = ECUtil.generatePrivateKeyParameter(privateKey);
			SM2Engine sm2Engine = new SM2Engine(mode);
			sm2Engine.init(false, privateKeyCipherParameters);
			return sm2Engine.processBlock(encryptData, 0, encryptData.length);
		}
		catch (InvalidCipherTextException | InvalidKeyException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static byte[] sm2Sign(byte[] data, PrivateKey privateKey) throws CommonException {
		if (data == null) {
			throw new CommonException("需签名的数据为空");
		}
		if (privateKey == null) {
			throw new CommonException("私有密钥为空");
		}
		try {
			SM2Signer sm2Signer = new SM2Signer();
			CipherParameters privateKeyCipherParameters = ECUtil.generatePrivateKeyParameter(privateKey);
			ParametersWithRandom parametersWithRandom = new ParametersWithRandom(privateKeyCipherParameters);
			sm2Signer.init(true, parametersWithRandom);
			sm2Signer.update(data, 0, data.length);
			return sm2Signer.generateSignature();
		}
		catch (CryptoException | InvalidKeyException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static boolean sm2Verify(byte[] data, PublicKey publicKey, byte[] sign) throws CommonException {
		if (data == null) {
			throw new CommonException("数据为空");
		}
		if (publicKey == null) {
			throw new CommonException("公有密钥为空");
		}
		if (sign == null) {
			throw new CommonException("签名为空");
		}
		try {
			SM2Signer sm2Signer = new SM2Signer();
			CipherParameters publicKeyCipherParameters = ECUtil.generatePublicKeyParameter(publicKey);
			sm2Signer.init(false, publicKeyCipherParameters);
			sm2Signer.update(data, 0, data.length);
			return sm2Signer.verifySignature(sign);
		}
		catch (InvalidKeyException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static byte[] sm3(byte[] data) {
		SM3Digest sm3Digest = new SM3Digest();
		sm3Digest.update(data, 0, data.length);
		byte[] result = new byte[sm3Digest.getDigestSize()];
		sm3Digest.doFinal(result, 0);
		return result;
	}

	public static byte[] getSm4EncryptKey() throws CommonException {
		try {
			KeyGenerator keyGenerator = KeyGenerator.getInstance(SM4_KEY_ALGORITHM, getProvider());
			keyGenerator.init(128, new SecureRandom());
			SecretKey secretKey = keyGenerator.generateKey();
			return secretKey.getEncoded();
		}
		catch (NoSuchAlgorithmException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static byte[] encryptSm4Cbc(byte[] data, byte[] key, byte[] iv, PaddingType paddingType) throws CommonException {
		if (data == null) {
			throw new CommonException("数据为空");
		}
		if (key == null) {
			throw new CommonException("密钥为空");
		}
		if (iv == null) {
			throw new CommonException("IV初始向量为空");
		}
		if (paddingType == null) {
			throw new CommonException("填充类型为空");
		}
		try {
			Cipher cipher = getSm4Cipher("CBC", paddingType);
			initSm4CbcCipher(cipher, key, iv, Cipher.ENCRYPT_MODE);
			return cipher.doFinal(data);
		}
		catch (IllegalBlockSizeException | BadPaddingException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static byte[] decyrptSm4Cbc(byte[] encryptData, byte[] key, byte[] iv, PaddingType paddingType) throws CommonException {
		if (encryptData == null) {
			throw new CommonException("加密后的数据为空");
		}
		if (key == null) {
			throw new CommonException("密钥为空");
		}
		if (iv == null) {
			throw new CommonException("IV初始向量为空");
		}
		if (paddingType == null) {
			throw new CommonException("填充类型为空");
		}
		try {
			Cipher cipher = getSm4Cipher("CBC", paddingType);
			initSm4CbcCipher(cipher, key, iv, Cipher.DECRYPT_MODE);
			return cipher.doFinal(encryptData);
		}
		catch (IllegalBlockSizeException | BadPaddingException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static byte[] encryptSm4Ecb(byte[] data, byte[] key, PaddingType paddingType) throws CommonException {
		if (data == null) {
			throw new CommonException("数据为空");
		}
		if (key == null) {
			throw new CommonException("密钥为空");
		}
		if (paddingType == null) {
			throw new CommonException("填充类型为空");
		}
		try {
			Cipher cipher = getSm4Cipher("ECB", paddingType);
			initSm4EcbCipher(cipher, key, Cipher.ENCRYPT_MODE);
			return cipher.doFinal(data);
		}
		catch (IllegalBlockSizeException | BadPaddingException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	public static byte[] decyrptSm4Ecb(byte[] encryptData, byte[] key, PaddingType paddingType) throws CommonException {
		if (encryptData == null) {
			throw new CommonException("加密后的数据为空");
		}
		if (key == null) {
			throw new CommonException("密钥为空");
		}
		if (paddingType == null) {
			throw new CommonException("填充类型为空");
		}
		try {
			Cipher cipher = getSm4Cipher("ECB", paddingType);
			initSm4EcbCipher(cipher, key, Cipher.DECRYPT_MODE);
			return cipher.doFinal(encryptData);
		}
		catch (IllegalBlockSizeException | BadPaddingException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	private static Cipher getSm4Cipher(String encryptMode, PaddingType paddingType) throws CommonException {
		try {
			String transformation = SM4_KEY_ALGORITHM + "/" + encryptMode + "/" + paddingType.toString();
			return Cipher.getInstance(transformation, getProvider());
		}
		catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	private static void initSm4EcbCipher(Cipher cipher, byte[] key, int opmode) throws CommonException {
		try {
			SecretKeySpec secretKeySpec = new SecretKeySpec(key, SM4_KEY_ALGORITHM);
			cipher.init(opmode, secretKeySpec);
		}
		catch (InvalidKeyException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	private static void initSm4CbcCipher(Cipher cipher, byte[] key, byte[] iv, int opmode) throws CommonException {
		try {
			SecretKeySpec secretKeySpec = new SecretKeySpec(key, SM4_KEY_ALGORITHM);
			AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(SM4_KEY_ALGORITHM, getProvider());
			algorithmParameters.init(new IvParameterSpec(iv));
			cipher.init(opmode, secretKeySpec, algorithmParameters);
		}
		catch (NoSuchAlgorithmException | InvalidParameterSpecException | InvalidKeyException | InvalidAlgorithmParameterException e) {
			throw ExceptionWrapUtils.wrap(e);
		}
	}

	private static Provider getProvider() {
		return new BouncyCastleProvider();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy