BouncyCastle

发布时间 2023-05-31 22:34:26作者: Zzangg
  1. 在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务
  2. 参考附件内容完成SM2加解密的内容,提交运行结果截图(10‘)
  3. 完成SM3,SM4算法的调用,提交运行结果截图和代码(15’, 选做)

参考https://www.cnblogs.com/fzlzc/p/14595817.html
下载bouncycaslte,将下下来的jar包拷贝到\jre\lib\ext
导入时注意选择classpath,不然会报错

SM2

  • sm2_demo:
点击查看代码
package bouncycastle;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;

import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.util.encoders.Hex;

public class SM2Util {
	/**
	 * SM2加密算法
	 * 
	 * @param publicKey 公钥
	 * @param data      明文数据
	 * @return
	 */
	public String encrypt(PublicKey publicKey, String data) {

		ECPublicKeyParameters ecPublicKeyParameters = null;
		if (publicKey instanceof BCECPublicKey) {
			BCECPublicKey bcecPublicKey = (BCECPublicKey) publicKey;
			ECParameterSpec ecParameterSpec = bcecPublicKey.getParameters();
			ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
					ecParameterSpec.getG(), ecParameterSpec.getN());
			ecPublicKeyParameters = new ECPublicKeyParameters(bcecPublicKey.getQ(), ecDomainParameters);
		}

		SM2Engine sm2Engine = new SM2Engine();
		sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));

		byte[] arrayOfBytes = null;
		try {
			byte[] in = data.getBytes("utf-8");
			arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
		} catch (Exception e) {
			System.out.println("SM2加密时出现异常:");
		}
		return Hex.toHexString(arrayOfBytes);
	}

	/**
	 * SM2解密算法
	 * 
	 * @param privateKey 私钥
	 * @param cipherData 密文数据
	 * @return
	 */
	public String decrypt(PrivateKey privateKey, String cipherData) {
		byte[] cipherDataByte = Hex.decode(cipherData);

		BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) privateKey;
		ECParameterSpec ecParameterSpec = bcecPrivateKey.getParameters();

		ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
				ecParameterSpec.getG(), ecParameterSpec.getN());

		ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(bcecPrivateKey.getD(),
				ecDomainParameters);

		SM2Engine sm2Engine = new SM2Engine();
		sm2Engine.init(false, ecPrivateKeyParameters);

		String result = null;
		try {
			byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
			return new String(arrayOfBytes, "utf-8");
		} catch (Exception e) {
			System.out.println("SM2解密时出现异常");
		}
		return result;
	}

}

  • sm2demo:
点击查看代码
package bouncycastle;

import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.ECGenParameterSpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class sm2_demo {
	private static String test = "lzc_SM2_demo";

	public static void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
		SM2Util sm2 = new SM2Util();
		final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
// 获取一个椭圆曲线类型的密钥对生成器
		final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
// 使用SM2参数初始化生成器
		kpg.initialize(sm2Spec);
// 获取密钥对
		KeyPair keyPair = kpg.generateKeyPair();
		PublicKey publicKey = keyPair.getPublic();
		PrivateKey privateKey = keyPair.getPrivate();
		String data = sm2.encrypt(publicKey, test);
		System.out.println("明文:" + test);
		System.out.println("密文:" + data);
		String text = sm2.decrypt(privateKey, data);
		System.out.println("解密结果:" + text);
	}
}

实现截图:

SM3

sm3——demo:

点击查看代码
package GM_test;


import GM_test.SM3Util;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
public class sm3_demo {
    private static String test="lzc_SM3_demo";
    public static void main(String[] args) throws NoSuchAlgorithmException,
            InvalidAlgorithmParameterException {
        SM3Util sm3 = new SM3Util();
        String data = sm3.plainEncrypt(test);
        System.out.println("明文:"+test);
        System.out.println("哈希值:"+data);
    }
}

SM3Util:

点击查看代码
package GM_test;


import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

/**
 * @Author: dzy
 * @Date: 2018/10/19 16:36
 * @Describe: SM3工具类(杂凑算法-hash算法)
 */

public class SM3Util {

    /**
     * 16进制字符串SM3生成HASH签名值算法
     * @param hexString     16进制字符串
     * @return
     */
    public static String hexEncrypt(String hexString) {
        byte[] srcData = Hex.decode(hexString);
        byte[] encrypt = encrypt(srcData);
        String cipherStr  = Hex.toHexString(encrypt);
        return cipherStr;
    }

    /**
     * 16进制字符串SM3生成HASH签名值算法
     * @param hexKey        16进制密钥
     * @param hexString     16进制字符串
     * @return
     */
    public static String hexEncrypt(String hexKey, String hexString) {
        byte[] key = Hex.decode(hexKey);
        byte[] srcData = Hex.decode(hexString);
        byte[] encrypt = encrypt(key, srcData);
        String cipherStr  = Hex.toHexString(encrypt);
        return cipherStr;
    }

    /**
     * 普通文本SM3生成HASH签名算法
     * @param plain     待签名数据
     * @return
     */
    public static String plainEncrypt(String plain) {
        // 将返回的hash值转换成16进制字符串
        String cipherStr = null;
        try {
            //将字符串转换成byte数组
            byte[] srcData = plain.getBytes(StandardCharsets.UTF_8);
            //调用encrypt计算hash
            byte[] encrypt = encrypt(srcData);
            //将返回的hash值转换成16进制字符串
            cipherStr = Hex.toHexString(encrypt);
        } catch (Exception e) {
            //log.error("将字符串转换为字节时出现异常:", e);
        }
        return cipherStr;
    }

    /**
     * 普通文本SM3生成HASH签名算法
     * @param hexKey        密钥
     * @param plain         待签名数据
     * @return
     */
    public static String plainEncrypt(String hexKey, String plain) {
        // 将返回的hash值转换成16进制字符串
        String cipherStr = null;
        try {
            //将字符串转换成byte数组
            byte[] srcData = plain.getBytes(StandardCharsets.UTF_8);
            //密钥
            byte[] key = Hex.decode(hexKey);
            //调用encrypt计算hash
            byte[] encrypt = encrypt(key, srcData);
            //将返回的hash值转换成16进制字符串
            cipherStr = Hex.toHexString(encrypt);
        } catch (Exception e) {
            //log.error("将字符串转换为字节时出现异常:", e);
        }
        return cipherStr;
    }

    /**
     * SM3计算hashCode
     * @param srcData   待计算数据
     * @return
     */
    public static byte[] encrypt(byte[] srcData) {
        SM3Digest sm3Digest = new SM3Digest();
        sm3Digest.update(srcData, 0, srcData.length);
        byte[] encrypt = new byte[sm3Digest.getDigestSize()];
        sm3Digest.doFinal(encrypt, 0);
        return encrypt;
    }

    /**
     * 通过密钥进行加密
     * @param key       密钥byte数组
     * @param srcData   被加密的byte数组
     * @return
     */
    public static byte[] encrypt(byte[] key, byte[] srcData) {
        KeyParameter keyParameter = new KeyParameter(key);
        SM3Digest digest = new SM3Digest();
        HMac mac = new HMac(digest);
        mac.init(keyParameter);
        mac.update(srcData, 0, srcData.length);
        byte[] result = new byte[mac.getMacSize()];
        mac.doFinal(result, 0);
        return result;
    }

    /**
     * SM3计算hashCode
     * @param srcData   待计算数据
     * @return
     * @throws Exception
     */
    public static byte[] encrypt_0(byte[] srcData) throws Exception {
        MessageDigest messageDigest = MessageDigest.getInstance("SM3", "BC");
        byte[] digest = messageDigest.digest(srcData);
        return digest;
    }

}

image

SM4

sm4_demo:

点击查看代码
package GM_test;


import GM_test.SM4Util;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;

import java.security.*;
import java.security.spec.ECGenParameterSpec;
public class sm4_demo {
    private static String test= "lzc_SM4_demonmsl";
    private static String mykey= "6cef39eb85614df44f6b0f6bbbdd89b6";
    public static void main(String[] args) throws NoSuchAlgorithmException,
            InvalidAlgorithmParameterException {
        SM4Util sm4 = new SM4Util();
        //SM3Util sm3 = new SM3Util();
        //String data_in = sm3.plainEncrypt(test);
        //String data = sm4.encryptByEcb(data_in,mykey);
        String x16 = sm4.strToHexadecimal(test);
        //System.out.println(x16);
        String data = sm4.encryptByEcb(x16,mykey);
        System.out.println("明文:"+test);
        //System.out.println("摘   要:"+data_in);
        System.out.println("密文:"+data);
        String text_16 = sm4.decryptByEcb(data,mykey);
        //System.out.println(text_16);
        //System.out.println(x16.equals(text_16.toUpperCase()));
        String text = sm4.hexadecimalToStr(text_16.toUpperCase());
        System.out.println("解密结果:"+text);
    }
}

SM4Util:

点击查看代码
package GM_test;

import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;

/**
 * @Author: dzy
 * @Date: 2018/10/9 16:41
 * @Describe: SM4算法
 */
public class SM4Util {

    //加解密的字节快大小
    public static final int BLOCK_SIZE = 16;

    /**
     * SM4ECB加密算法
     * @param in            待加密内容
     * @param keyBytes      密钥
     * @return
     */
    public static byte[] encryptByEcb0(byte[] in, byte[] keyBytes) {
        SM4Engine sm4Engine = new SM4Engine();
        sm4Engine.init(true, new KeyParameter(keyBytes));
        int inLen = in.length;
        byte[] out = new byte[inLen];

        int times = inLen / BLOCK_SIZE;

        for (int i = 0; i < times; i++) {
            sm4Engine.processBlock(in, i * BLOCK_SIZE, out, i * BLOCK_SIZE);
        }

        return out;
    }

    /**
     * SM4ECB加密算法
     * @param in            待加密内容
     * @param keyBytes      密钥
     * @return
     */
    public static String encryptByEcb(byte[] in, byte[] keyBytes) {
        byte[] out = encryptByEcb0(in, keyBytes);
        String cipher = Hex.toHexString(out);
        return cipher;
    }

    /**
     * SM4的ECB加密算法
     * @param content   待加密内容
     * @param key       密钥
     * @return
     */
    public static String encryptByEcb(String content, String key) {
        byte[] in = Hex.decode(content);
        byte[] keyBytes = Hex.decode(key);

        String cipher = encryptByEcb(in, keyBytes);
        return cipher;
    }

    /**
     * SM4的ECB解密算法
     * @param in        密文内容
     * @param keyBytes  密钥
     * @return
     */
    public static byte[] decryptByEcb0(byte[] in, byte[] keyBytes) {
        SM4Engine sm4Engine = new SM4Engine();
        sm4Engine.init(false, new KeyParameter(keyBytes));
        int inLen = in.length;
        byte[] out = new byte[inLen];

        int times = inLen / BLOCK_SIZE;

        for (int i = 0; i < times; i++) {
            sm4Engine.processBlock(in, i * BLOCK_SIZE, out, i * BLOCK_SIZE);
        }

        return out;
    }

    /**
     * SM4的ECB解密算法
     * @param in        密文内容
     * @param keyBytes  密钥
     * @return
     */
    public static String decryptByEcb(byte[] in, byte[] keyBytes) {
        byte[] out = decryptByEcb0(in, keyBytes);
        String plain = Hex.toHexString(out);
        return plain;
    }

    /**
     * SM4的ECB解密算法
     * @param cipher    密文内容
     * @param key       密钥
     * @return
     */
    public static String decryptByEcb(String cipher, String key) {
        byte[] in = Hex.decode(cipher);
        byte[] keyBytes = Hex.decode(key);

        String plain = decryptByEcb(in, keyBytes);
        return plain;
    }

    public static String strToHexadecimal(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString().trim();
    }

    public static String hexadecimalToStr(String hexStr) {
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;
        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        return new String(bytes);
    }
}

image