中国商用暗号SM2完全ガイド:鍵生成、暗号化・復号、デジタル署名の実践
SM2とは?
SM2は中国国家暗号管理局が発表した非対称暗号アルゴリズムで、楕円曲線暗号(ECC)をベースに、RSAに代わる中国商用暗号(国密)標準となっています。
| 比較項目 | SM2 | RSA 2048 |
|---|---|---|
| 鍵長 | 256 bit | 2048 bit |
| セキュリティ強度 | 128 bit | 112 bit |
| 署名速度 | ~0.5ms | ~3ms |
| 検証速度 | ~1ms | ~0.1ms |
| 鍵長の比率 | 1 | 8 |
| 標準規格 | GM/T 0003 | PKCS#1 |
SM2は256ビットの鍵でRSA 2048ビット相当のセキュリティ強度を実現し、鍵が短く、処理も高速です。
SM2の3つの用途
| 用途 | 説明 | 対応ツール |
|---|---|---|
| 暗号化/復号 | 公開鍵で暗号化し、秘密鍵で復号 | 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桁の16進数)
// keyPair.publicKey → 公開鍵(128桁の16進数、04 + X + Y)
console.log('秘密鍵:', keyPair.privateKey);
console.log('公開鍵:', keyPair.publicKey);
鍵フォーマットの説明
SM2公開鍵フォーマット:
04 || X(32バイト) || Y(32バイト)
↓
04 + 64桁の16進数X + 64桁の16進数Y
合計長:130文字の16進数(65バイト)
SM2秘密鍵フォーマット:
32バイトの乱数
合計長:64文字の16進数(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...'; // 130桁の16進数
const privateKey = '...'; // 64桁の16進数
// 暗号化(デフォルトは C1C3C2 フォーマット)
const cipherText = sm2.doEncrypt('Hello 国密', publicKey, 1);
// 引数 1 = C1C3C2 フォーマット(国標推奨)
// 引数 0 = C1C2C3 フォーマット(旧版との互換用)
console.log('暗号文:', cipherText);
// 復号
const plainText = sm2.doDecrypt(cipherText, privateKey, 1);
console.log('平文:', plainText); // "Hello 国密"
暗号文のエンコードフォーマット
| フォーマット | 説明 | 使用シーン |
|---|---|---|
| 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 | 銀聯/中国人民銀行の要件 |
| 国際標準システム | RSA | 国際的な互換性 |
| モバイル端末の暗号化 | SM2 | 鍵が短く、計算が速い |
| 越境データ交換 | RSA | 国際的に広く利用可能 |
中国商用暗号3点セット:SM2 + SM3 + SM4
| アルゴリズム | タイプ | 用途 | ツール |
|---|---|---|---|
| SM2 | 非対称 | 暗号化/署名/鍵共有 | SM2ツール |
| SM3 | ハッシュ | メッセージダイジェスト(SHA-256相当) | SM3ツール |
| SM4 | 対称 | データ暗号化(AES-128相当) | SM4ツール |
典型的な組み合わせ:SM2 + SM4 ハイブリッド暗号
1. ランダムなSM4鍵を生成
2. SM4で大容量データを暗号化(高速)
3. SM2公開鍵でSM4鍵を暗号化(安全に送信)
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. SM2でSM4鍵を暗号化
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)を使用します。アルゴリズムのロジックは似ていますが、曲線パラメータが異なるため、互換性はありません。
JavaでSM2を使うには?
// Bouncy Castle + 国密拡張を使用
Security.addProvider(new BouncyCastleProvider());
// 鍵ペアを生成
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
kpg.initialize(new ECParameterSpec(...)); // SM2曲線パラメータ
KeyPair kp = kpg.generateKeyPair();
まとめ
SM2は中国商用暗号体系の中核となる非対称暗号アルゴリズムで、256ビットの鍵でRSA 2048ビット相当のセキュリティ強度を実現します。鍵生成、暗号化・復号、デジタル署名の3つの操作をマスターし、SM3ハッシュやSM4対称暗号と組み合わせれば、国密コンプライアンス要件を満たせます。ToolsKuはSM2、SM3、SM4の3つのオンラインツールを提供しており、ブラウザ内でローカル処理されるため、データが外部に送信されることはありません。
#国密#SM2#非对称加密#数字签名#加密教程