package cn.hztech.sdk;

import cn.hztech.sdk.crypto.sm2.SM2Util;
import cn.hztech.sdk.crypto.sm4.SM4Util;
import cn.hztech.sdk.crypto.envelope.GmPacket;
import cn.hztech.sdk.crypto.envelope.GmPacketBuilder;
import cn.hztech.sdk.crypto.envelope.GmPacketParser;
import cn.hztech.sdk.exception.CryptoException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.security.*;

import static org.junit.jupiter.api.Assertions.*;

/**
 * SM2加密工具类测试
 */
class SM2UtilTest {

    private SM2Util sm2Util;
    private KeyPair keyPair;

    @BeforeEach
    void setUp() throws Exception {
        sm2Util = new SM2Util();

        // 生成测试用的密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
        keyPairGenerator.initialize(256);
        keyPair = keyPairGenerator.generateKeyPair();
    }

    @Test
    void testEncryptDecrypt() {
        String originalData = "这是一段测试数据";

        // 加密
        String publicKeyBase64 = java.util.Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        String encrypted = sm2Util.encrypt(originalData, publicKeyBase64);
        assertNotNull(encrypted);
        assertNotEquals(originalData, encrypted);

        // 解密
        String privateKeyBase64 = java.util.Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        String decrypted = sm2Util.decrypt(encrypted, privateKeyBase64);
        assertEquals(originalData, decrypted);
    }

    @Test
    void testSignVerify() {
        String data = "待签名数据";

        // 签名
        String privateKeyBase64 = java.util.Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        String signature = sm2Util.sign(data, privateKeyBase64);
        assertNotNull(signature);

        // 验签
        String publicKeyBase64 = java.util.Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        boolean valid = sm2Util.verify(data, signature, publicKeyBase64);
        assertTrue(valid);

        // 篡改数据后验签应该失败
        boolean invalid = sm2Util.verify(data + "被篡改", signature, publicKeyBase64);
        assertFalse(invalid);
    }

    @Test
    void testEncryptWithInvalidKey() {
        assertThrows(CryptoException.class, () -> {
            sm2Util.encrypt("data", "invalid_key");
        });
    }

    @Test
    void testSignWithInvalidKey() {
        assertThrows(CryptoException.class, () -> {
            sm2Util.sign("data", "invalid_key");
        });
    }
}
