web 端 sm4 验证正确
This commit is contained in:
parent
ffd4d17f5d
commit
fe1f7c14b4
20
src/App.tsx
20
src/App.tsx
@ -25,6 +25,7 @@ function App() {
|
||||
const [sm4Iv, setSm4Iv] = useState('')
|
||||
const [sm4Message, setSm4Message] = useState('')
|
||||
const [sm4Mode, setSm4Mode] = useState('ecb')
|
||||
const [sm4PaddingMode, setSm4PaddingMode] = useState<'pkcs7' | 'none'>('pkcs7')
|
||||
const [sm4Encrypted, setSm4Encrypted] = useState('')
|
||||
const [sm4Decrypted, setSm4Decrypted] = useState('')
|
||||
|
||||
@ -116,7 +117,7 @@ function App() {
|
||||
// SM4 加密
|
||||
const handleEncryptSm4 = () => {
|
||||
try {
|
||||
const encrypted = sm4Encrypt(sm4Message, sm4Key, sm4Mode, sm4Iv)
|
||||
const encrypted = sm4Encrypt(sm4Message, sm4Key, sm4Mode, sm4Iv, sm4PaddingMode)
|
||||
setSm4Encrypted(encrypted)
|
||||
} catch (error) {
|
||||
alert('加密失败: ' + (error instanceof Error ? error.message : error))
|
||||
@ -126,7 +127,7 @@ function App() {
|
||||
// SM4 解密
|
||||
const handleDecryptSm4 = () => {
|
||||
try {
|
||||
const decrypted = sm4Decrypt(sm4Encrypted, sm4Key, sm4Mode, sm4Iv)
|
||||
const decrypted = sm4Decrypt(sm4Encrypted, sm4Key, sm4Mode, sm4Iv, sm4PaddingMode)
|
||||
setSm4Decrypted(decrypted)
|
||||
} catch (error) {
|
||||
alert('解密失败: ' + (error instanceof Error ? error.message : error))
|
||||
@ -347,6 +348,21 @@ function App() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label>填充模式</label>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
|
||||
{(['pkcs7', 'none'] as const).map(paddingMode => (
|
||||
<button
|
||||
key={paddingMode}
|
||||
className={sm4PaddingMode === paddingMode ? 'primary' : ''}
|
||||
onClick={() => setSm4PaddingMode(paddingMode)}
|
||||
>
|
||||
{paddingMode}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label>消息</label>
|
||||
<textarea
|
||||
|
||||
22
src/__tests__/algorithm/sm4-gcm.test.ts
Normal file
22
src/__tests__/algorithm/sm4-gcm.test.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { sm4Encrypt, sm4Decrypt } from '../../utils/algorithm/sm4'
|
||||
|
||||
describe('SM4 GCM 模式测试(用户提供的测试用例)', () => {
|
||||
test('用户提供的 GCM 测试用例', () => {
|
||||
const key = '00000000000000000000000000000000'
|
||||
const iv = '000000000000000000000000'
|
||||
const message = '00000000000000000000000000000000'
|
||||
const expected = '7de2aa7f1110188218063be1bfeb6d89b851b5f39493752be508f1bb4482c557'
|
||||
|
||||
const encrypted = sm4Encrypt(message, key, 'gcm', iv, 'none')
|
||||
console.log('实际结果:', encrypted)
|
||||
console.log('预期结果:', expected)
|
||||
console.log('结果是否匹配:', encrypted.toUpperCase() === expected.toUpperCase())
|
||||
|
||||
// 验证加密结果
|
||||
expect(encrypted.toUpperCase()).toBe(expected.toUpperCase())
|
||||
|
||||
// 验证解密结果
|
||||
const decrypted = sm4Decrypt(encrypted, key, 'gcm', iv, 'none')
|
||||
expect(decrypted.toUpperCase()).toBe(message.toUpperCase())
|
||||
})
|
||||
})
|
||||
@ -139,3 +139,4 @@ describe('SM4 算法测试', () => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -122,18 +122,19 @@ export const sm4Encrypt = (message: string, key: string, mode: string, iv?: stri
|
||||
const ivBytes = hexToBytes(iv)
|
||||
const ivBits = sjcl.codec.bytes.toBits(ivBytes)
|
||||
const dataBits = sjcl.codec.bytes.toBits(dataToEncrypt)
|
||||
const encryptedResult = sjcl.mode.gcm.encrypt(sm4Key, dataBits, ivBits, sjcl.codec.bytes.toBits([]))
|
||||
// GCM 模式返回的数据包含 tag,需要分离
|
||||
// 传递标签长度参数(128 位)
|
||||
const encryptedResult = sjcl.mode.gcm.encrypt(sm4Key, dataBits, ivBits, sjcl.codec.bytes.toBits([]), 128)
|
||||
// GCM 模式返回的数据包含 tag
|
||||
if (!encryptedResult) {
|
||||
throw new Error('GCM encryption failed: result is undefined')
|
||||
}
|
||||
// 检查 encryptedResult 的类型
|
||||
if (Array.isArray(encryptedResult)) {
|
||||
// 如果返回的是数组,直接使用
|
||||
// 如果返回的是数组,直接使用(包含了 tag)
|
||||
const encryptedBytes = sjcl.codec.bytes.fromBits(encryptedResult)
|
||||
return bytesToHex(encryptedBytes)
|
||||
} else if (encryptedResult.data) {
|
||||
// 如果返回的是对象,使用 data 属性
|
||||
// 如果返回的是对象,使用 data 属性(可能已经包含了 tag)
|
||||
const encryptedBits = encryptedResult.data
|
||||
const encryptedBytes = sjcl.codec.bytes.fromBits(encryptedBits)
|
||||
return bytesToHex(encryptedBytes)
|
||||
@ -208,7 +209,8 @@ export const sm4Decrypt = (encrypted: string, key: string, mode: string, iv?: st
|
||||
const ivBytes = hexToBytes(iv)
|
||||
const ivBits = sjcl.codec.bytes.toBits(ivBytes)
|
||||
const encryptedBits = sjcl.codec.bytes.toBits(encryptedBytes)
|
||||
const decryptedResult = sjcl.mode.gcm.decrypt(sm4Key, encryptedBits, ivBits, sjcl.codec.bytes.toBits([]))
|
||||
// 传递标签长度参数(128 位)
|
||||
const decryptedResult = sjcl.mode.gcm.decrypt(sm4Key, encryptedBits, ivBits, sjcl.codec.bytes.toBits([]), 128)
|
||||
// 检查 decryptedResult 的类型
|
||||
if (!decryptedResult) {
|
||||
throw new Error('GCM decryption failed: result is undefined')
|
||||
|
||||
21
test-gcm.js
Normal file
21
test-gcm.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { sm4Encrypt } from './src/utils/algorithm/sm4.ts';
|
||||
|
||||
// 用户提供的测试用例
|
||||
const key = '00000000000000000000000000000000';
|
||||
const iv = '000000000000000000000000';
|
||||
const message = '00000000000000000000000000000000';
|
||||
const expected = '7de2aa7f1110188218063be1bfeb6d89b851b5f39493752be508f1bb4482c557';
|
||||
|
||||
console.log('测试 SM4 GCM 模式...');
|
||||
console.log('密钥:', key);
|
||||
console.log('IV:', iv);
|
||||
console.log('消息:', message);
|
||||
console.log('预期结果:', expected);
|
||||
|
||||
try {
|
||||
const result = sm4Encrypt(message, key, 'gcm', iv, 'none');
|
||||
console.log('实际结果:', result);
|
||||
console.log('结果是否匹配:', result.toUpperCase() === expected.toUpperCase());
|
||||
} catch (error) {
|
||||
console.error('错误:', error.message);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user