Guía Completa de Cifrado SM2: Generación de Claves, Cifrado, Descifrado y Firmas Digitales en Práctica

Codificación

¿Qué es SM2?

SM2 es un algoritmo de cifrado asimétrico publicado por la Administración Nacional de Criptografía de China, basado en criptografía de curva elíptica (ECC), que reemplaza a RSA como estándar nacional.

Comparación SM2 RSA 2048
Longitud de clave 256 bit 2048 bit
Intensidad de seguridad 128 bit 112 bit
Velocidad de firma ~0.5ms ~3ms
Velocidad de verificación ~1ms ~0.1ms
Ratio de longitud de clave 1 8
Estándar nacional GM/T 0003 PKCS#1

SM2 alcanza la intensidad de seguridad de RSA 2048 bit con una clave de 256 bit, clave más corta, velocidad más rápida.


Tres Usos de SM2

Uso Descripción Herramienta Correspondiente
Cifrado/Descifrado Cifrar con clave pública, descifrar con clave privada Cifrado SM2
Firma Digital Firmar con clave privada, verificar con clave pública Firma SM2
Acuerdo de Claves Ambas partes negocian una clave compartida Protocolo ECDH

Paso 1: Generar Par de Claves SM2

Usar la herramienta de ToolsKu

  1. Abrir Herramienta de Cifrado SM2
  2. Hacer clic en "Generar par de claves"
  3. Obtener la clave pública y la clave privada

Usar la línea de comandos

# Instalar gmssl
brew install gmssl  # macOS
# O descargar desde https://github.com/guanzhi/GmSSL/releases

# Generar par de claves SM2
gmssl sm2 -genkey -out sm2.key

# Ver las claves
gmssl sm2 -in sm2.key -text

Usar JavaScript

import { sm2 } from 'sm-crypto';

// Generar par de claves
const keyPair = sm2.generateKeyPairHex();
// keyPair.privateKey → clave privada (64 hexadecimales)
// keyPair.publicKey  → clave pública (128 hexadecimales, 04 + X + Y)

console.log('Clave privada:', keyPair.privateKey);
console.log('Clave pública:', keyPair.publicKey);

Formato de clave

Formato de clave pública SM2:
04 || X (32 bytes) || Y (32 bytes)
↓
04 + 64 hexadecimales X + 64 hexadecimales Y
Longitud total: 130 caracteres hexadecimales (65 bytes)

Formato de clave privada SM2:
Número aleatorio de 32 bytes
Longitud total: 64 caracteres hexadecimales (32 bytes)

Paso 2: Cifrado y Descifrado SM2

Flujo de Cifrado

Texto plano → Cifrado SM2 (clave pública) → Texto cifrado (C1 || C3 || C2)
  • C1: Punto de curva elíptica (65 bytes)
  • C3: Hash SM3 (32 bytes)
  • C2: Datos cifrados

Usar la herramienta de ToolsKu

  1. Abrir Herramienta de Cifrado SM2
  2. Pegar la clave pública
  3. Ingresar el texto plano a cifrar
  4. Seleccionar formato de texto cifrado (C1C3C2 o C1C2C3)
  5. Hacer clic en "Cifrar" para obtener el texto cifrado

Usar JavaScript

import { sm2 } from 'sm-crypto';

const publicKey = '04...'; // 128 hexadecimales
const privateKey = '...';  // 64 hexadecimales

// Cifrar (formato C1C3C2 por defecto)
const cipherText = sm2.doEncrypt('Hola SM2', publicKey, 1);
// Parámetro 1 = formato C1C3C2 (recomendado por el estándar nacional)
// Parámetro 0 = formato C1C2C3 (compatibilidad con versiones anteriores)

console.log('Texto cifrado:', cipherText);

// Descifrar
const plainText = sm2.doDecrypt(cipherText, privateKey, 1);
console.log('Texto plano:', plainText); // "Hola SM2"

Formatos de codificación del texto cifrado

Formato Descripción Escenario de uso
C1C3C2 Formato recomendado por el estándar nacional Proyectos nuevos (por defecto)
C1C2C3 Formato de versión anterior Compatibilidad con sistemas antiguos
ASN.1 Codificación DER Interoperabilidad Java/C#

Paso 3: Firma Digital SM2

Flujo de Firma

Mensaje → Hash SM3 → Firma SM2 (clave privada) → Valor de firma (r, s)

Usar la herramienta de ToolsKu

  1. Abrir Herramienta de Cifrado SM2
  2. Cambiar a la pestaña "Firma"
  3. Ingresar la clave privada y el mensaje a firmar
  4. Hacer clic en "Firmar" para obtener el valor de la firma

Usar JavaScript

import { sm2 } from 'sm-crypto';

const privateKey = '...';
const publicKey = '04...';

// Firmar (aplica hash SM3 automáticamente al mensaje)
const signature = sm2.doSignature('Mensaje a firmar', privateKey);
console.log('Firma:', signature);

// Verificar firma
const verified = sm2.doVerifySignature(
  'Mensaje a firmar',
  signature,
  publicKey
);
console.log('Resultado de verificación:', verified); // true

Firma con ID de usuario

La firma SM2 usa por defecto el ID de usuario 1234567812345678 (valor por defecto del estándar nacional), que se puede personalizar:

// Especificar ID de usuario al firmar
const sig = sm2.doSignature('Mensaje', privateKey, {
  userId: 'customUserId'
});

// Usar el mismo ID de usuario al verificar
const valid = sm2.doVerifySignature('Mensaje', sig, publicKey, {
  userId: 'customUserId'
});

SM2 vs RSA: ¿Cuándo elegir?

Escenario Recomendación Razón
Sistemas gubernamentales nacionales SM2 Requisito de cumplimiento con estándar nacional
Sistemas financieros nacionales SM2 Requisito de UnionPay/Banco Popular
Sistemas de estándares internacionales RSA Compatibilidad internacional
Cifrado en dispositivos móviles SM2 Clave corta, cálculo rápido
Intercambio de datos transfronterizo RSA Estándar internacional

Trío de Cifrado Nacional: SM2 + SM3 + SM4

Algoritmo Tipo Uso Herramienta
SM2 Asimétrico Cifrado/Firma/Acuerdo de claves Herramienta SM2
SM3 Hash Resumen de mensaje (similar a SHA-256) Herramienta SM3
SM4 Simétrico Cifrado de datos (similar a AES-128) Herramienta SM4

Combinación típica: Cifrado híbrido SM2 + SM4

1. Generar clave SM4 aleatoria
2. Cifrar datos grandes con SM4 (rápido)
3. Cifrar la clave SM4 con la clave pública SM2 (transmisión segura)
4. Enviar: SM2(clave SM4) + SM4(datos)
import { sm2, sm4 } from 'sm-crypto';

// 1. Generar clave SM4 aleatoria
const sm4Key = crypto.getRandomValues(new Uint8Array(16));
const sm4KeyHex = Array.from(sm4Key).map(b => b.toString(16).padStart(2, '0')).join('');

// 2. Cifrar datos con SM4
const encryptedData = sm4.encrypt(plainText, sm4KeyHex);

// 3. Cifrar la clave SM4 con SM2
const encryptedKey = sm2.doEncrypt(sm4KeyHex, sm2PublicKey, 1);

// Enviar: encryptedKey + encryptedData

Preguntas Frecuentes

¿Por qué el texto cifrado SM2 es mucho más largo que el texto plano?

Texto cifrado SM2 = C1 (65 bytes) + C3 (32 bytes) + C2 (longitud del texto plano), por lo que el texto cifrado es 97 bytes más largo que el texto plano. Esta es una característica del cifrado asimétrico. Para datos grandes se recomienda cifrado híbrido SM2+SM4.

¿Cuál es la diferencia entre SM2 y ECDSA?

SM2 usa la curva elíptica especificada por el estándar nacional (sm2p256v1), ECDSA usa curvas NIST (P-256). La lógica del algoritmo es similar, pero los parámetros de la curva son diferentes, no son compatibles.

¿Cómo usar SM2 en Java?

// Usar Bouncy Castle + extensión de cifrado nacional
Security.addProvider(new BouncyCastleProvider());

// Generar par de claves
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(new ECParameterSpec(...)); // Parámetros de curva SM2
KeyPair kp = kpg.generateKeyPair();

Resumen

SM2 es el algoritmo de cifrado asimétrico central del sistema de cifrado nacional, con una clave de 256 bit alcanza la intensidad de seguridad de RSA 2048 bit. Domine las tres operaciones principales: generación de claves, cifrado/descifrado y firma digital, junto con hash SM3 y cifrado simétrico SM4, para cumplir con los requisitos de cumplimiento del estándar nacional. ToolsKu ofrece tres herramientas en línea: SM2, SM3, SM4, procesamiento local en el navegador, datos sin carga.

#国密#SM2#非对称加密#数字签名#加密教程