Compare commits

..

No commits in common. "a7aef0f7ddd6f692817c982010f771f646a0dbf6" and "ffd4d17f5ddded6d4309443f1e0d2c248f2554e7" have entirely different histories.

9 changed files with 14 additions and 224 deletions

View File

@ -1,45 +0,0 @@
# SM3 测试用例
## 测试用例列表
### sm3-001
- **输入**: "616263" "abc" 的 hex 表示)
- **预期输出**: "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0"
### sm3-002
- **输入**: "6162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364" "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd" 的 hex 表示)
- **预期输出**: "debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732"
### sm3-003
- **输入**: "6162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364616263646162636461626364" (长字符串的 hex 表示)
- **预期输出**: "6888fa292df4b51341e82e3072fbdd63598439c64eda318a81756ca71a7a6c15"
### sm3-004
- **来源**: [GBT.32918.2-2016] A.2 Example 1
- **输入**: "0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A20AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857"
- **预期输出**: "f4a38489e32b45b6f876e3ac2168ca392362dc8f23459c1d1146fc3dbfb7bc9a"
### sm3-005
- **来源**: [GBT.32918.2-2016] A.2 Example 2
- **输入**: "F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A6D65737361676520646967657374"
- **预期输出**: "b524f552cd82b8b028476e005c377fb19a87e6fc682d48bb5d42e3d9b9effe76"
### sm3-006
- **来源**: GB/T 32918.2-2016 A.3 Example 1
- **输入**: "0090414C494345313233405941484F4F2E434F4D00000000000000000000000000000000000000000000000000000000000000000000E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E0165961645281A8626607B917F657D7E9382F1EA5CD931F40F6627F357542653B201686522130D590FB8DE635D8FCA715CC6BF3D05BEF3F75DA5D543454448166612"
- **预期输出**: "26352af82ec19f207bbc6f9474e11e90ce0f7ddace03b27f801817e897a81fd5"
### sm3-007
- **来源**: [GBT.32918.2-2016] A.3 Example 2
- **输入**: "26352AF82EC19F207BBC6F9474E11E90CE0F7DDACE03B27F801817E897A81FD56D65737361676520646967657374"
- **预期输出**: "ad673cbda311417129a9eaa5f9ab1aa1633ad47718a84dfd46c17c6fa0aa3b12"
### sm3-008
- **来源**: GB/T 32918.4-2016 A.3 Example 1
- **输入**: "01C6271B31F6BE396A4166C0616CF4A8ACDA5BEF4DCBF2DD42656E6372797074696F6E207374616E646172640147AF35DFA1BFE2F161521BCF59BAB83564868D9295881735"
- **预期输出**: "f0a41f6f48ac723cecfc4b767299a5e25c0641679fbd2d4d20e9ffd5b9f0dab8"
### sm3-009
- **来源**: GB/T 32918.4-2016 A.3 Example 2
- **输入**: "0083E628CF701EE3141E8873FE55936ADF24963F5DC9C6480566C80F8A1D8CC51B656E6372797074696F6E207374616E6461726401524C647F0C0412DEFD468BDA3AE0E5A80FCC8F5C990FEE11602929232DCD9F36"
- **预期输出**: "73a48625d3758fa37b3eab80e9cfcaba665e3199ea15a1fa8189d96f579125e4"

View File

@ -1,27 +0,0 @@
# SM3 HMAC 测试用例
## 测试用例列表
### sm3hmac-001
- **输入**:
- 密钥: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"
- 消息: "6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f70716162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071" "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 的 hex 表示)
- **预期输出**: "ca05e144ed05d1857840d1f318a4a8669e559fc8391f414485bfdf7bb408963a"
### sm3hmac-002
- **输入**:
- 密钥: "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425"
- 消息: "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
- **预期输出**: "220bf579ded555393f0159f66c99877822a3ecf610d1552154b41d44b94db3ae"
### sm3hmac-003
- **输入**:
- 密钥: "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
- 消息: "4869205468657265" "Hi There" 的 hex 表示)
- **预期输出**: "c0ba18c68b90c88bc07de794bfc7d2c8d19ec31ed8773bc2b390c9604e0be11e"
### sm3hmac-004
- **输入**:
- 密钥: "4a656665" "Jefe" 的 hex 表示)
- 消息: "7768617420646f2079612077616e7420666f72206e6f7468696e673f" "what do ya want for nothing?" 的 hex 表示)
- **预期输出**: "2e87f1d16862e6d964b50a5200bf2b10b764faa9680a296a2405f24bec39f882"

View File

@ -1,57 +0,0 @@
\[
{
input: 'abc',
hash: '66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0'
},
{
input: 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd',
hash: 'debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732'
},
{
input:
'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd',
hash: '6888fa292df4b51341e82e3072fbdd63598439c64eda318a81756ca71a7a6c15'
},
{
// From \[GBT.32918.2-2016] A.2 Example 1
input: sjcl.codec.hex.toBits(
'0090414C494345313233405941484F4F2E434F4D787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E49863E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A20AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857'
),
hash: 'f4a38489e32b45b6f876e3ac2168ca392362dc8f23459c1d1146fc3dbfb7bc9a'
},
{
// From \[GBT.32918.2-2016] A.2 Example 2
input: sjcl.codec.hex.toBits(
'F4A38489E32B45B6F876E3AC2168CA392362DC8F23459C1D1146FC3DBFB7BC9A6D65737361676520646967657374'
),
hash: 'b524f552cd82b8b028476e005c377fb19a87e6fc682d48bb5d42e3d9b9effe76'
},
{
// GB/T 32918.2-2016 A.3 Example 1
input: sjcl.codec.hex.toBits(
'0090414C494345313233405941484F4F2E434F4D00000000000000000000000000000000000000000000000000000000000000000000E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E0165961645281A8626607B917F657D7E9382F1EA5CD931F40F6627F357542653B201686522130D590FB8DE635D8FCA715CC6BF3D05BEF3F75DA5D543454448166612'
),
hash: '26352af82ec19f207bbc6f9474e11e90ce0f7ddace03b27f801817e897a81fd5'
},
{
// From \[GBT.32918.2-2016] A.3 Example 2
input: sjcl.codec.hex.toBits(
'26352AF82EC19F207BBC6F9474E11E90CE0F7DDACE03B27F801817E897A81FD56D65737361676520646967657374'
),
hash: 'ad673cbda311417129a9eaa5f9ab1aa1633ad47718a84dfd46c17c6fa0aa3b12'
},
{
// GB/T 32918.4-2016 A.3 Example 1
input: sjcl.codec.hex.toBits(
'01C6271B31F6BE396A4166C0616CF4A8ACDA5BEF4DCBF2DD42656E6372797074696F6E207374616E646172640147AF35DFA1BFE2F161521BCF59BAB83564868D9295881735'
),
hash: 'f0a41f6f48ac723cecfc4b767299a5e25c0641679fbd2d4d20e9ffd5b9f0dab8'
},
{
// GB/T 32918.4-2016 A.3 Example 2
input: sjcl.codec.hex.toBits(
'0083E628CF701EE3141E8873FE55936ADF24963F5DC9C6480566C80F8A1D8CC51B656E6372797074696F6E207374616E6461726401524C647F0C0412DEFD468BDA3AE0E5A80FCC8F5C990FEE11602929232DCD9F36'
),
hash: '73a48625d3758fa37b3eab80e9cfcaba665e3199ea15a1fa8189d96f579125e4'
}
]

View File

@ -25,7 +25,6 @@ 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('')
@ -117,7 +116,7 @@ function App() {
// SM4 加密 // SM4 加密
const handleEncryptSm4 = () => { const handleEncryptSm4 = () => {
try { try {
const encrypted = sm4Encrypt(sm4Message, sm4Key, sm4Mode, sm4Iv, sm4PaddingMode) const encrypted = sm4Encrypt(sm4Message, sm4Key, sm4Mode, sm4Iv)
setSm4Encrypted(encrypted) setSm4Encrypted(encrypted)
} catch (error) { } catch (error) {
alert('加密失败: ' + (error instanceof Error ? error.message : error)) alert('加密失败: ' + (error instanceof Error ? error.message : error))
@ -127,7 +126,7 @@ function App() {
// SM4 解密 // SM4 解密
const handleDecryptSm4 = () => { const handleDecryptSm4 = () => {
try { try {
const decrypted = sm4Decrypt(sm4Encrypted, sm4Key, sm4Mode, sm4Iv, sm4PaddingMode) const decrypted = sm4Decrypt(sm4Encrypted, sm4Key, sm4Mode, sm4Iv)
setSm4Decrypted(decrypted) setSm4Decrypted(decrypted)
} catch (error) { } catch (error) {
alert('解密失败: ' + (error instanceof Error ? error.message : error)) alert('解密失败: ' + (error instanceof Error ? error.message : error))
@ -348,21 +347,6 @@ 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

View File

@ -1,22 +0,0 @@
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())
})
})

View File

@ -139,4 +139,3 @@ describe('SM4 算法测试', () => {
} }
}) })
}) })

View File

@ -5,33 +5,14 @@ const isValidHex = (hex: string): boolean => {
return /^[0-9a-fA-F]*$/.test(hex) && hex.length % 2 === 0 return /^[0-9a-fA-F]*$/.test(hex) && hex.length % 2 === 0
} }
// ArrayBuffer 转 hex 字符串
const arrayBufferToHex = (buffer: ArrayBuffer): string => {
const bytes = new Uint8Array(buffer)
return Array.from(bytes).map(byte => byte.toString(16).padStart(2, '0')).join('')
}
// SM3 计算 // SM3 计算
export const sm3Digest = (message: string): string => { export const sm3Digest = (message: string): string => {
try {
// 验证消息是否为有效的 hex 字符串 // 验证消息是否为有效的 hex 字符串
if (!isValidHex(message)) { if (!isValidHex(message)) {
throw new Error('Invalid message: must be hex string') throw new Error('Invalid message: must be hex string')
} }
console.log('Input hex message:', message) // 直接使用 message 作为输入gm-crypto 会自动处理
const result = SM3.digest(message)
// 直接使用 hex 字符串计算 SM3 return typeof result === 'string' ? result : Buffer.from(result).toString('hex')
const result = SM3.digest(message, 'hex')
console.log('SM3 result:', result)
// 处理返回结果
const hexResult = typeof result === 'string' ? result : arrayBufferToHex(result)
console.log('Hex result:', hexResult)
return hexResult
} catch (error) {
console.error('SM3 digest error:', error)
throw error
}
} }

View File

@ -122,19 +122,18 @@ 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)
// 传递标签长度参数128 位) const encryptedResult = sjcl.mode.gcm.encrypt(sm4Key, dataBits, ivBits, sjcl.codec.bytes.toBits([]))
const encryptedResult = sjcl.mode.gcm.encrypt(sm4Key, dataBits, ivBits, sjcl.codec.bytes.toBits([]), 128) // GCM 模式返回的数据包含 tag需要分离
// 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 属性(可能已经包含了 tag // 如果返回的是对象,使用 data 属性
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)
@ -209,8 +208,7 @@ 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)
// 传递标签长度参数128 位) const decryptedResult = sjcl.mode.gcm.decrypt(sm4Key, encryptedBits, ivBits, sjcl.codec.bytes.toBits([]))
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')

View File

@ -1,21 +0,0 @@
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);
}