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 [sm4Iv, setSm4Iv] = useState('')
|
||||||
const [sm4Message, setSm4Message] = useState('')
|
const [sm4Message, setSm4Message] = useState('')
|
||||||
const [sm4Mode, setSm4Mode] = useState('ecb')
|
const [sm4Mode, setSm4Mode] = useState('ecb')
|
||||||
|
const [sm4PaddingMode, setSm4PaddingMode] = useState<'pkcs7' | 'none'>('pkcs7')
|
||||||
const [sm4Encrypted, setSm4Encrypted] = useState('')
|
const [sm4Encrypted, setSm4Encrypted] = useState('')
|
||||||
const [sm4Decrypted, setSm4Decrypted] = useState('')
|
const [sm4Decrypted, setSm4Decrypted] = useState('')
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ function App() {
|
|||||||
// SM4 加密
|
// SM4 加密
|
||||||
const handleEncryptSm4 = () => {
|
const handleEncryptSm4 = () => {
|
||||||
try {
|
try {
|
||||||
const encrypted = sm4Encrypt(sm4Message, sm4Key, sm4Mode, sm4Iv)
|
const encrypted = sm4Encrypt(sm4Message, sm4Key, sm4Mode, sm4Iv, sm4PaddingMode)
|
||||||
setSm4Encrypted(encrypted)
|
setSm4Encrypted(encrypted)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert('加密失败: ' + (error instanceof Error ? error.message : error))
|
alert('加密失败: ' + (error instanceof Error ? error.message : error))
|
||||||
@ -126,7 +127,7 @@ function App() {
|
|||||||
// SM4 解密
|
// SM4 解密
|
||||||
const handleDecryptSm4 = () => {
|
const handleDecryptSm4 = () => {
|
||||||
try {
|
try {
|
||||||
const decrypted = sm4Decrypt(sm4Encrypted, sm4Key, sm4Mode, sm4Iv)
|
const decrypted = sm4Decrypt(sm4Encrypted, sm4Key, sm4Mode, sm4Iv, sm4PaddingMode)
|
||||||
setSm4Decrypted(decrypted)
|
setSm4Decrypted(decrypted)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert('解密失败: ' + (error instanceof Error ? error.message : error))
|
alert('解密失败: ' + (error instanceof Error ? error.message : error))
|
||||||
@ -347,6 +348,21 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
</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">
|
<div className="form-group">
|
||||||
<label>消息</label>
|
<label>消息</label>
|
||||||
<textarea
|
<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 ivBytes = hexToBytes(iv)
|
||||||
const ivBits = sjcl.codec.bytes.toBits(ivBytes)
|
const ivBits = sjcl.codec.bytes.toBits(ivBytes)
|
||||||
const dataBits = sjcl.codec.bytes.toBits(dataToEncrypt)
|
const dataBits = sjcl.codec.bytes.toBits(dataToEncrypt)
|
||||||
const encryptedResult = sjcl.mode.gcm.encrypt(sm4Key, dataBits, ivBits, sjcl.codec.bytes.toBits([]))
|
// 传递标签长度参数(128 位)
|
||||||
// GCM 模式返回的数据包含 tag,需要分离
|
const encryptedResult = sjcl.mode.gcm.encrypt(sm4Key, dataBits, ivBits, sjcl.codec.bytes.toBits([]), 128)
|
||||||
|
// GCM 模式返回的数据包含 tag
|
||||||
if (!encryptedResult) {
|
if (!encryptedResult) {
|
||||||
throw new Error('GCM encryption failed: result is undefined')
|
throw new Error('GCM encryption failed: result is undefined')
|
||||||
}
|
}
|
||||||
// 检查 encryptedResult 的类型
|
// 检查 encryptedResult 的类型
|
||||||
if (Array.isArray(encryptedResult)) {
|
if (Array.isArray(encryptedResult)) {
|
||||||
// 如果返回的是数组,直接使用
|
// 如果返回的是数组,直接使用(包含了 tag)
|
||||||
const encryptedBytes = sjcl.codec.bytes.fromBits(encryptedResult)
|
const encryptedBytes = sjcl.codec.bytes.fromBits(encryptedResult)
|
||||||
return bytesToHex(encryptedBytes)
|
return bytesToHex(encryptedBytes)
|
||||||
} else if (encryptedResult.data) {
|
} else if (encryptedResult.data) {
|
||||||
// 如果返回的是对象,使用 data 属性
|
// 如果返回的是对象,使用 data 属性(可能已经包含了 tag)
|
||||||
const encryptedBits = encryptedResult.data
|
const encryptedBits = encryptedResult.data
|
||||||
const encryptedBytes = sjcl.codec.bytes.fromBits(encryptedBits)
|
const encryptedBytes = sjcl.codec.bytes.fromBits(encryptedBits)
|
||||||
return bytesToHex(encryptedBytes)
|
return bytesToHex(encryptedBytes)
|
||||||
@ -208,7 +209,8 @@ export const sm4Decrypt = (encrypted: string, key: string, mode: string, iv?: st
|
|||||||
const ivBytes = hexToBytes(iv)
|
const ivBytes = hexToBytes(iv)
|
||||||
const ivBits = sjcl.codec.bytes.toBits(ivBytes)
|
const ivBits = sjcl.codec.bytes.toBits(ivBytes)
|
||||||
const encryptedBits = sjcl.codec.bytes.toBits(encryptedBytes)
|
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 的类型
|
// 检查 decryptedResult 的类型
|
||||||
if (!decryptedResult) {
|
if (!decryptedResult) {
|
||||||
throw new Error('GCM decryption failed: result is undefined')
|
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