Chiffrement et déchiffrement de l'algorithme secret national SM2

Un point du principe de conception de la sécurité de l'interface est que les données ne peuvent pas être transmises en texte brut. En plus de la demande nécessaire de https, le cryptage des données d'interface est également une méthode importante. Ce qui suit décrit l'utilisation du cryptage et du décryptage de l'algorithme secret national SM2.

Ici, je présenterai brièvement comment utiliser correctement SM2les algorithmes pour chiffrer et déchiffrer les données en fonction de la séparation actuelle des architectures front-end et back-end. L'introduction est divisée en chiffrement et déchiffrement back-end et chiffrement et déchiffrement front-end.

1. Chiffrement et déchiffrement du backend

1.1 Importer des dépendances POM

<!-- hutool -->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.5</version>
</dependency>
<!-- 加解密依赖包 -->
<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15to18</artifactId>
  <version>1.71</version>
</dependency>

1.2 Générer une clé publique, une paire de clés privées

/**
 * 生成公钥、私钥,这个保存好,尤其是私钥,切记不可泄漏
 */
public static void generateCommonKey() {
    
    
  SM2 sm2 = SmUtil.sm2();
  // 私钥:这个保存好,切记不要泄漏,真的泄露了就重新生成一下
  byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
  // 公钥:这个是前后端加密用的,不压缩选择带04的,不带04到时候前端会报错
  byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
  Console.log("公钥:\n{}", HexUtil.encodeHexStr(publicKey));
  Console.log("私钥:\n{}", HexUtil.encodeHexStr(privateKey));
}

1.3 Chiffrement et déchiffrement

/**
 * sm2明文加密
 * PRIVATE_KEY:生成的私钥
 * PUBLIC_KEY:生成的公钥
 * @param data 加密前的明文
 * @return 加密后的密文
 */
public static String encryptData(String data) {
    
    
  SM2 sm2 = SmUtil.sm2(ECKeyUtil.toSm2PrivateParams(PRIVATE_KEY), ECKeyUtil.toSm2PublicParams(PUBLIC_KEY));
  String encryptBcd = sm2.encryptBcd(data, KeyType.PublicKey);
  // 这里的处理前端也可以处理,这个就看怎么约定了,其实都无伤大雅
  if (StrUtil.isNotBlank(encryptBcd)) {
    
    
    // 生成的加密密文会带04,因为前端sm-crypto默认的是1-C1C3C2模式,这里需去除04才能正常解密
    if (encryptBcd.startsWith("04")) {
    
    
      encryptBcd = encryptBcd.substring(2);
    }
    // 前端解密时只能解纯小写形式的16进制数据,这里需要将所有大写字母转化为小写
    encryptBcd = encryptBcd.toLowerCase();
  }
  return encryptBcd;
}

/**
 * sm2密文解密
 * PRIVATE_KEY:生成的私钥
 * PUBLIC_KEY:生成的公钥
 * @param encryptData 加密密文
 * @return 解密后的明文字符串
 */
public static String decryptData(String encryptData) throws Exception {
    
    
  if (StrUtil.isBlank(encryptData)) {
    
    
    throw new RuntimeException("解密串为空,解密失败");
  }
  SM2 sm2 = SmUtil.sm2(ECKeyUtil.toSm2PrivateParams(PRIVATE_KEY), ECKeyUtil.toSm2PublicParams(PUBLIC_KEY));
  // BC库解密时密文开头必须带04,如果没带04则需补齐
  if (!encryptData.startsWith("04")) {
    
    
    encryptData = "04".concat(encryptData);
  }
  byte[] decryptFromBcd = sm2.decryptFromBcd(encryptData, KeyType.PrivateKey);
  if (decryptFromBcd != null && decryptFromBcd.length > 0) {
    
    
    return StrUtil.utf8Str(decryptFromBcd);
  } else {
    
    
    throw new Exception("密文解密失败");
  }
}

2. Chiffrement et déchiffrement frontal

2.1 Installer les dépendances du package NPM

npm install --save sm-crypto

2.2 Créer un nouveau sm2.js public

const sm2 = require('sm-crypto').sm2;
// 加密策略,1 - C1C3C2,0 - C1C2C3,默认为1
const encryptMode = 1;
const publicUiKey = '后端生成的公钥';
const privateKey = '后端生成的私钥';

/**
 * 加密数据
 * @param {Object} data 明文数据
 */
export function encryptData(data) {
    
    
	if (data && (typeof data === 'string') && (data.constructor === String)) {
    
    
		return '04'.concat(sm2.doEncrypt(data, publicUiKey, encryptMode));
	}
	return data;
}


/**
 * 加密对象数据
 * @param {Object} data 对象明文
 */
export function encryptObjectData(data) {
    
    
	if (data) {
    
    
		return '04'.concat(sm2.doEncrypt(JSON.stringify(data), publicUiKey, encryptMode));
	}
	return data;
}

/**
 * 解密数据
 * @param {Object} dataHex 加密的密文数据
 */
export function decryptData(encryptData) {
    
    
	if (encryptData && (typeof encryptData === 'string') && (encryptData.constructor === String)) {
    
    
		const decryptData = sm2.doDecrypt(encryptData, privateKey, encryptMode);
		return decryptData;
	}
}

2.3 utilisation

import {
    
     encryptData, decryptData} from "../../../request/sm2.js";
encryptData('明文');
decryptData('密文');

3. Documents de référence

https://www.npmjs.com/package/sm-crypto

Je suppose que tu aimes

Origine blog.csdn.net/active_pig/article/details/126921695
conseillé
Classement