Полное руководство по шифрованию SM2: генерация ключей, шифрование, расшифровка и цифровая подпись на практике

Кодирование

Что такое SM2?

SM2 — это алгоритм асимметричного шифрования, опубликованный Национальным управлением криптографии Китая, основанный на криптографии эллиптических кривых (ECC), заменяющий RSA в качестве национального стандарта.

Сравнение SM2 RSA 2048
Длина ключа 256 бит 2048 бит
Стойкость безопасности 128 бит 112 бит
Скорость подписи ~0.5мс ~3мс
Скорость проверки ~1мс ~0.1мс
Отношение длины ключа 1 8
Национальный стандарт GM/T 0003 PKCS#1

SM2 достигает стойкости безопасности RSA 2048 бит с ключом 256 бит, ключ короче, скорость выше.


Три варианта использования SM2

Применение Описание Соответствующий инструмент
Шифрование/Расшифровка Шифрование открытым ключом, расшифровка закрытым Шифрование SM2
Цифровая подпись Подпись закрытым ключом, проверка открытым Подпись SM2
Согласование ключей Обе стороны согласовывают общий ключ Протокол ECDH

Шаг 1: Генерация пары ключей SM2

Использование инструмента ToolsKu

  1. Открыть Инструмент шифрования SM2
  2. Нажать «Сгенерировать пару ключей»
  3. Получить открытый и закрытый ключи

Использование командной строки

# Установить gmssl
brew install gmssl  # macOS
# Или скачать с https://github.com/guanzhi/GmSSL/releases

# Сгенерировать пару ключей SM2
gmssl sm2 -genkey -out sm2.key

# Просмотреть ключи
gmssl sm2 -in sm2.key -text

Использование JavaScript

import { sm2 } from 'sm-crypto';

// Генерация пары ключей
const keyPair = sm2.generateKeyPairHex();
// keyPair.privateKey → закрытый ключ (64 шестнадцатеричных символа)
// keyPair.publicKey  → открытый ключ (128 шестнадцатеричных символов, 04 + X + Y)

console.log('Закрытый ключ:', keyPair.privateKey);
console.log('Открытый ключ:', keyPair.publicKey);

Формат ключа

Формат открытого ключа SM2:
04 || X (32 байта) || Y (32 байта)
↓
04 + 64 шестнадцатеричных X + 64 шестнадцатеричных Y
Общая длина: 130 шестнадцатеричных символов (65 байт)

Формат закрытого ключа SM2:
Случайное число 32 байта
Общая длина: 64 шестнадцатеричных символа (32 байта)

Шаг 2: Шифрование и расшифровка SM2

Процесс шифрования

Открытый текст → Шифрование SM2 (открытый ключ) → Шифротекст (C1 || C3 || C2)
  • C1: Точка эллиптической кривой (65 байт)
  • C3: Хеш SM3 (32 байта)
  • C2: Зашифрованные данные

Использование инструмента ToolsKu

  1. Открыть Инструмент шифрования SM2
  2. Вставить открытый ключ
  3. Ввести открытый текст для шифрования
  4. Выбрать формат шифротекста (C1C3C2 или C1C2C3)
  5. Нажать «Зашифровать» для получения шифротекста

Использование JavaScript

import { sm2 } from 'sm-crypto';

const publicKey = '04...'; // 128 шестнадцатеричных символов
const privateKey = '...';  // 64 шестнадцатеричных символа

// Шифрование (формат C1C3C2 по умолчанию)
const cipherText = sm2.doEncrypt('Привет SM2', publicKey, 1);
// Параметр 1 = формат C1C3C2 (рекомендован национальным стандартом)
// Параметр 0 = формат C1C2C3 (совместимость со старыми версиями)

console.log('Шифротекст:', cipherText);

// Расшифровка
const plainText = sm2.doDecrypt(cipherText, privateKey, 1);
console.log('Открытый текст:', plainText); // "Привет SM2"

Форматы кодирования шифротекста

Формат Описание Сценарий использования
C1C3C2 Формат, рекомендованный национальным стандартом Новые проекты (по умолчанию)
C1C2C3 Формат старой версии Совместимость со старыми системами
ASN.1 Кодировка DER Взаимодействие Java/C#

Шаг 3: Цифровая подпись SM2

Процесс подписи

Сообщение → Хеш SM3 → Подпись SM2 (закрытый ключ) → Значение подписи (r, s)

Использование инструмента ToolsKu

  1. Открыть Инструмент шифрования SM2
  2. Переключиться на вкладку «Подпись»
  3. Ввести закрытый ключ и сообщение для подписи
  4. Нажать «Подписать» для получения значения подписи

Использование JavaScript

import { sm2 } from 'sm-crypto';

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

// Подпись (автоматический хеш SM3 сообщения)
const signature = sm2.doSignature('Сообщение для подписи', privateKey);
console.log('Подпись:', signature);

// Проверка подписи
const verified = sm2.doVerifySignature(
  'Сообщение для подписи',
  signature,
  publicKey
);
console.log('Результат проверки:', verified); // true

Подпись с ID пользователя

Подпись SM2 по умолчанию использует ID пользователя 1234567812345678 (значение по умолчанию национального стандарта), который можно настроить:

// Указать ID пользователя при подписи
const sig = sm2.doSignature('Сообщение', privateKey, {
  userId: 'customUserId'
});

// Использовать тот же ID пользователя при проверке
const valid = sm2.doVerifySignature('Сообщение', sig, publicKey, {
  userId: 'customUserId'
});

SM2 vs RSA: когда выбирать?

Сценарий Рекомендация Причина
Национальные правительственные системы SM2 Требование соответствия национальному стандарту
Национальные финансовые системы SM2 Требование UnionPay/Народного банка
Системы международных стандартов RSA Международная совместимость
Шифрование на мобильных устройствах SM2 Короткий ключ, быстрые вычисления
Трансграничный обмен данными RSA Международный стандарт

Тройка национальной криптографии: SM2 + SM3 + SM4

Алгоритм Тип Назначение Инструмент
SM2 Асимметричный Шифрование/Подпись/Согласование ключей Инструмент SM2
SM3 Хеш Дайджест сообщений (аналог SHA-256) Инструмент SM3
SM4 Симметричный Шифрование данных (аналог AES-128) Инструмент SM4

Типичная комбинация: гибридное шифрование SM2 + SM4

1. Сгенерировать случайный ключ SM4
2. Зашифровать большие данные с помощью SM4 (быстро)
3. Зашифровать ключ SM4 открытым ключом SM2 (безопасная передача)
4. Отправить: SM2(ключ SM4) + SM4(данные)
import { sm2, sm4 } from 'sm-crypto';

// 1. Сгенерировать случайный ключ SM4
const sm4Key = crypto.getRandomValues(new Uint8Array(16));
const sm4KeyHex = Array.from(sm4Key).map(b => b.toString(16).padStart(2, '0')).join('');

// 2. Зашифровать данные с помощью SM4
const encryptedData = sm4.encrypt(plainText, sm4KeyHex);

// 3. Зашифровать ключ SM4 с помощью SM2
const encryptedKey = sm2.doEncrypt(sm4KeyHex, sm2PublicKey, 1);

// Отправить: encryptedKey + encryptedData

Часто задаваемые вопросы

Почему шифротекст SM2 намного длиннее открытого текста?

Шифротекст SM2 = C1 (65 байт) + C3 (32 байта) + C2 (длина открытого текста), поэтому шифротекст на 97 байт длиннее открытого текста. Это особенность асимметричного шифрования. Для больших данных рекомендуется гибридное шифрование SM2+SM4.

В чём разница между SM2 и ECDSA?

SM2 использует эллиптическую кривую, указанную национальным стандартом (sm2p256v1), ECDSA использует кривые NIST (P-256). Логика алгоритма схожа, но параметры кривых различаются, они несовместимы.

Как использовать SM2 в Java?

// Использовать Bouncy Castle + расширение национальной криптографии
Security.addProvider(new BouncyCastleProvider());

// Генерация пары ключей
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(new ECParameterSpec(...)); // Параметры кривой SM2
KeyPair kp = kpg.generateKeyPair();

Итоги

SM2 — центральный алгоритм асимметричного шифрования национальной криптографической системы, достигающий стойкости безопасности RSA 2048 бит с ключом 256 бит. Освойте три основные операции: генерацию ключей, шифрование/расшифровку и цифровую подпись, в сочетании с хешированием SM3 и симметричным шифрованием SM4, для соответствия требованиям национального стандарта. ToolsKu предоставляет три онлайн-инструмента: SM2, SM3, SM4, локальная обработка в браузере, данные не загружаются.

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