Android 数据SM4传输加解密

这篇具有很好参考价值的文章主要介绍了Android 数据SM4传输加解密。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第一:场景介绍

  甲方要求,数据在传输过程中要加密。

第二:选择加解密方式:

这里面Android 和服务端都是选择SM4

第三:实现方式

1:服务端采用SpringBoot,在pom.xml 文件下添加依赖

		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcprov-jdk15on</artifactId>
			<version>1.64</version>
		</dependency>

2:在Android 端同样添加依赖,在module 下面build.gradle

  implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.64'

3:服务端SM4工具类

package com.wansun.datahouse.visit.utils;

import org.apache.tomcat.util.buf.HexUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;

/**
 * TODO:
 * 国密SM4算法
 *
 * @author Blade
 * @date 2022/5/9 17:13
 */
public class Sm4Util {

    /**
     * 算法名称
     */
    public static final String ALGORITHM_NAME = "SM4";

    /**
     * SM4算法ECB模式PKCS5Padding填充方式
     */
    public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";

    /**
     * SM4算法ECB模式不填充
     */
    public static final String ALGORITHM_NAME_ECB_NOPADDING = "SM4/ECB/NoPadding";

    /**
     * SM4算法CBC模式PKCS5Padding填充方式
     */
    public static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";

    /**
     * SM4算法CBC模式不填充
     */
    public static final String ALGORITHM_NAME_CBC_NOPADDING = "SM4/CBC/NoPadding";

    /**
     * 默认key长度
     */
    public static final int DEFAULT_KEY_SIZE = 128;

    static {
        // 加入 BC 实现
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 生成秘钥 key
     *
     * @return key
     * @throws NoSuchAlgorithmException 异常
     * @throws NoSuchProviderException  异常
     */
    private static byte[] generateKey() throws NoSuchAlgorithmException, NoSuchProviderException {
        return generateKey(DEFAULT_KEY_SIZE);
    }

    /**
     * 生成秘钥 key
     *
     * @param keySize 秘钥长度
     * @return key
     * @throws NoSuchAlgorithmException 异常
     * @throws NoSuchProviderException  异常
     */
    private static byte[] generateKey(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
        kg.init(keySize, new SecureRandom());
        return kg.generateKey().getEncoded();
    }

    /**
     * 生成ECB模式的cipher
     *
     * @param algorithmName 算法名称
     * @param mode          模式
     * @param key           秘钥
     * @return {@link Cipher} 密文
     * @throws NoSuchAlgorithmException 异常
     * @throws NoSuchProviderException  异常
     * @throws NoSuchPaddingException   异常
     * @throws InvalidKeyException      异常
     */
    private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key)
            throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
            InvalidKeyException {
        Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
        Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
        cipher.init(mode, sm4Key);
        return cipher;
    }

    /**
     * 用ECB模式和PKCS5Padding填充的方式 进行加密
     *
     * @param key  秘钥
     * @param data 加密前的数据
     * @return 加密后的数据
     * @throws InvalidKeyException       异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws NoSuchPaddingException    异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    private static byte[] encryptEcbPadding(byte[] key, byte[] data)
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,
            NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(data);
    }

    /**
     * 用ECB模式和PKCS5Padding填充的方式 进行解密
     *
     * @param key        秘钥
     * @param cipherText 加密后的数据
     * @return 解密后的数据
     * @throws InvalidKeyException       异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws NoSuchPaddingException    异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    private static byte[] decryptEcbPadding(byte[] key, byte[] cipherText)
            throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
            NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(cipherText);
    }


    /**
     * 用ECB模式和不填充的方式 进行加密
     *
     * @param key  秘钥
     * @param data 加密前的数据
     * @return 加密后的数据
     * @throws InvalidKeyException       异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws NoSuchPaddingException    异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    private static byte[] encryptEcbNoPadding(byte[] key, byte[] data)
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,
            NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_NOPADDING, Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(data);
    }

    /**
     * 用ECB模式和不填充的方式 进行解密
     *
     * @param key        秘钥
     * @param cipherText 解密前的数据
     * @return 解密后的数据
     * @throws InvalidKeyException       异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws NoSuchPaddingException    异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    private static byte[] decryptEcbNoPadding(byte[] key, byte[] cipherText)
            throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
            NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {
        Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_NOPADDING, Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(cipherText);
    }

    /**
     * 生成CBC模式的cipher
     *
     * @param algorithmName 算法名称
     * @param mode          模式
     * @param key           秘钥
     * @param iv            偏移量(自定义的字符串)
     * @return {@link Cipher}
     * @throws NoSuchAlgorithmException 异常
     * @throws NoSuchProviderException  异常
     * @throws NoSuchPaddingException   异常
     * @throws InvalidKeyException      异常
     */
    private static Cipher generateCbcCipher(String algorithmName, int mode, byte[] key, byte[] iv)
            throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
            NoSuchProviderException, NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
        Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(mode, sm4Key, ivParameterSpec);
        return cipher;
    }

    /**
     * 用CBC模式和PKCS5Padding填充的方式 进行加密
     *
     * @param key  秘钥
     * @param iv   偏移量(自定义的字符串)
     * @param data 加密前的数据
     * @return 加密后的数据
     * @throws InvalidKeyException       异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws NoSuchPaddingException    异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    private static byte[] encryptCbcPadding(byte[] key, byte[] iv, byte[] data)
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,
            NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException,
            InvalidAlgorithmParameterException {
        Cipher cipher = generateCbcCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.ENCRYPT_MODE, key, iv);
        return cipher.doFinal(data);
    }

    /**
     * 用CBC模式和PKCS5Padding填充的方式 进行解密
     *
     * @param key        秘钥
     * @param iv         偏移量(自定义的字符串)
     * @param cipherText 解密前的数据
     * @return 解密后的数据
     * @throws InvalidKeyException       异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws NoSuchPaddingException    异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    private static byte[] decryptCbcPadding(byte[] key, byte[] iv, byte[] cipherText)
            throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
            NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
            InvalidAlgorithmParameterException {
        Cipher cipher = generateCbcCipher(ALGORITHM_NAME_CBC_PADDING, Cipher.DECRYPT_MODE, key, iv);
        return cipher.doFinal(cipherText);
    }

    /**
     * 用CBC模式和不填充的方式 进行加密
     *
     * @param key  秘钥
     * @param iv   偏移量(自定义的字符串)
     * @param data 加密前的数据
     * @return 加密后的数据
     * @throws InvalidKeyException       异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws NoSuchPaddingException    异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    private static byte[] encryptCbcNoPadding(byte[] key, byte[] iv, byte[] data)
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,
            NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException,
            InvalidAlgorithmParameterException {
        Cipher cipher = generateCbcCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.ENCRYPT_MODE, key, iv);
        return cipher.doFinal(data);
    }

    /**
     * 用ECB模式和不填充的方式 进行解密
     *
     * @param key        秘钥
     * @param iv         偏移量(自定义的字符串)
     * @param cipherText 加密后的数据
     * @return 解密后的数据
     * @throws InvalidKeyException       异常
     * @throws NoSuchAlgorithmException  异常
     * @throws NoSuchProviderException   异常
     * @throws NoSuchPaddingException    异常
     * @throws IllegalBlockSizeException 异常
     * @throws BadPaddingException       异常
     */
    private static byte[] decryptCbcNoPadding(byte[] key, byte[] iv, byte[] cipherText)
            throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException,
            NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
            InvalidAlgorithmParameterException {
        Cipher cipher = generateCbcCipher(ALGORITHM_NAME_CBC_NOPADDING, Cipher.DECRYPT_MODE, key, iv);
        return cipher.doFinal(cipherText);
    }

    /**
     * 生成key并且转换为16进制字符串
     *
     * @return key
     * @throws NoSuchProviderException  异常
     * @throws NoSuchAlgorithmException 异常
     */
    public static String generateKey_Hex() throws Exception {
        return HexUtils.toHexString(generateKey());
    }

    /**
     * 用CBC模式和PKCS5Padding填充的方式 进行加密
     *
     * @param key  秘钥
     * @param iv   偏移量(自定义的字符串)
     * @param data 加密数据
     * @return 加密后的转换成Hex的数据
     */
    public static String encryptCbcPaddingHex(String key, String iv, String data) throws Exception {

        String iv_hex = HexUtils.toHexString(iv.getBytes());

        return HexUtils.toHexString(encryptCbcPadding(HexUtils.fromHexString(key),
                HexUtils.fromHexString(iv_hex), data.getBytes()));
    }

    /**
     * 用CBC模式和PKCS5Padding填充的方式 进行解密
     *
     * @param key        秘钥
     * @param iv         偏移量(自定义的字符串)
     * @param cipherText 待解密数据
     * @return 解密后的数据
     */
    public static String decryptCbcPaddingHex(String key, String iv, String cipherText) throws Exception {
        return new String(decryptCbcPadding(HexUtils.fromHexString(key), iv.getBytes(),
                HexUtils.fromHexString(cipherText)));
    }

    public static void main(String[] args) throws Exception {
        String data = "{\"test\":\"湖北利川深圳\"}";
        String iv = "blade12345678910";
//        String hexKey = generateKey_Hex();
        String hexKey = "20785fae41a54c65ab95d2db1abc7f9f";
        System.out.println("hexKey===" + hexKey);
        String cipher = encryptCbcPaddingHex(hexKey, iv, data);
        System.out.println("cipher==" + cipher);
        String b = decryptCbcPaddingHex(hexKey, iv, cipher);
        System.out.println(b);
    }
}

4:Android SM4 工具类,要把 

BouncyCastleProvider.PROVIDER_NAME 贴换为 new BouncyCastleProvider()  不然报错

5:

分别在拦截器里面调用 加解密方法。hexKey 可以自己生成。iv 自己定义16位

    String hexKey = "20785fae41a54c65ab95d2db1abc7f9f";
    String iv = "blade12345678910";

加密方法:

String encryptJson = Sm4Util.encryptCbcPaddingHex(hexKey, iv, String.valueOf(json));

解密方法:

 String decryptJson = Sm4Util.decryptCbcPaddingHex(hexKey, iv, String.valueOf(data));

6:这里面就不展示拦截器里面的代码。

7:截图展示加解密后的效果。

sm4在线解密,java,开发语言

 文章来源地址https://www.toymoban.com/news/detail-536582.html

到了这里,关于Android 数据SM4传输加解密的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

原文地址:https://blog.csdn.net/beautifulYuan/article/details/129528518

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包