Полное руководство по шифрованию 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
- Открыть Инструмент шифрования SM2
- Нажать «Сгенерировать пару ключей»
- Получить открытый и закрытый ключи
Использование командной строки
# Установить 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
- Открыть Инструмент шифрования SM2
- Вставить открытый ключ
- Ввести открытый текст для шифрования
- Выбрать формат шифротекста (C1C3C2 или C1C2C3)
- Нажать «Зашифровать» для получения шифротекста
Использование 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
- Открыть Инструмент шифрования SM2
- Переключиться на вкладку «Подпись»
- Ввести закрытый ключ и сообщение для подписи
- Нажать «Подписать» для получения значения подписи
Использование 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, локальная обработка в браузере, данные не загружаются.