wusherrysherry 2023-05-15 20:31 采纳率: 0%
浏览 26

如何生成gmt 0016 ECC加密密钥对保护结构

    typedef struct Struct_ECCCIPHERBLOB {
        BYTE    XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
        BYTE    YCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
        BYTE    HASH[32];
        ULONG    CipherLen;
        BYTE    Cipher[1];
    } ECCCIPHERBLOB, *PECCCIPHERBLOB;

    typedef struct SKF_ENVELOPEDKEYBLOB {
        ULONG    Version;
        ULONG    ulSymmAlgID;
        ULONG    ulBits;
        BYTE    cbEncryptedPriKey[64];
        ECCPUBLICKEYBLOB    PubKey;
        ECCCIPHERBLOB        ECCCipherBlob;
    } ENVELOPEDKEYBLOB, *PENVELOPEDKEYBLOB;

这个ECC加密密钥对保护结构怎么生成, 有例子吗。

  • 写回答

1条回答 默认 最新

  • Leodong. 2023-05-15 20:47
    关注

    该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
    生成 GMT 0016 ECC 加密密钥对保护结构需要进行以下步骤:

    1. 生成 ECC 密钥对。可以使用 OpenSSL 等工具库生成 ECC 密钥对,具体生成方法可以参考对应库的文档。

    2. 使用 SHA-256 算法对 ECC 公钥进行哈希运算,生成 32 字节的 HASH 值。

    3. 使用 ECC 公钥加密对称密钥,得到密文。

    4. 将 ECC 公钥和密文组成 ECCCIPHERBLOB 结构体。

    5. 将生成的 ECCCIPHERBLOB 结构体和加密后的私钥组成 SKF_ENVELOPEDKEYBLOB 结构体。

    以下是一个 C 语言示例代码,演示了如何生成 SKF_ENVELOPEDKEYBLOB 结构体:

    #include <stdio.h>
    #include <string.h>
    #include <openssl/ec.h>
    #include <openssl/evp.h>
    #include <openssl/sha.h>
    
    #define ECC_MAX_XCOORDINATE_BITS_LEN 256
    
    typedef struct Struct_ECCCIPHERBLOB {
        BYTE XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
        BYTE YCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
        BYTE HASH[32];
        ULONG CipherLen;
        BYTE Cipher[1];
    } ECCCIPHERBLOB, *PECCCIPHERBLOB;
    
    typedef struct SKF_ENVELOPEDKEYBLOB {
        ULONG Version;
        ULONG ulSymmAlgID;
        ULONG ulBits;
        BYTE cbEncryptedPriKey[64];
        ECCPUBLICKEYBLOB PubKey;
        ECCCIPHERBLOB ECCCipherBlob;
    } ENVELOPEDKEYBLOB, *PENVELOPEDKEYBLOB;
    
    int generate_ecc_key_pair(EC_KEY **ecc_key, ECCPUBLICKEYBLOB *ecc_pubkey)
    {
        int ret = 0;
        EC_GROUP *group = NULL;
        EC_POINT *pubkey_point = NULL;
        unsigned char *pubkey_buf = NULL;
        int pubkey_len = 0;
    
        // 创建 ECC 密钥对
        group = EC_GROUP_new_by_curve_name(NID_sm2);
        if (group == NULL) {
            printf("Error creating EC group\n");
            ret = 1;
            goto cleanup;
        }
        *ecc_key = EC_KEY_new();
        if (*ecc_key == NULL) {
            printf("Error creating EC key\n");
            ret = 1;
            goto cleanup;
        }
        if (EC_KEY_set_group(*ecc_key, group) != 1) {
            printf("Error setting EC group\n");
            ret = 1;
            goto cleanup;
        }
        if (EC_KEY_generate_key(*ecc_key) != 1) {
            printf("Error generating EC key\n");
            ret = 1;
            goto cleanup;
        }
    
        // 获取 ECC 公钥
        pubkey_point = EC_KEY_get0_public_key(*ecc_key);
        pubkey_len = EC_POINT_point2oct(group, pubkey_point,
                                        POINT_CONVERSION_UNCOMPRESSED,
                                        NULL, 0, NULL);
        if (pubkey_len <= 0) {
            printf("Error getting public key length\n");
            ret = 1;
            goto cleanup;
        }
        pubkey_buf = (unsigned char *) malloc(pubkey_len);
        if (pubkey_buf == NULL) {
            printf("Error allocating memory for public key\n");
            ret = 1;
            goto cleanup;
        }
        if (EC_POINT_point2oct(group, pubkey_point,
                                POINT_CONVERSION_UNCOMPRESSED,
                                pubkey_buf, pubkey_len, NULL) != pubkey_len) {
            printf("Error getting public key\n");
            ret = 1;
            goto cleanup;
        }
    
        // 填充 ECC 公钥结构体
        ecc_pubkey->BitLen = pubkey_len * 8;
        ecc_pubkey->XCoordinateLen = pubkey_len / 2;
        ecc_pubkey->YCoordinateLen = pubkey_len / 2;
        memcpy(ecc_pubkey->XCoordinate, pubkey_buf, ecc_pubkey->XCoordinateLen);
        memcpy(ecc_pubkey->YCoordinate, pubkey_buf + ecc_pubkey->XCoordinateLen, ecc_pubkey->YCoordinateLen);
    
    cleanup:
        if (pubkey_buf != NULL) {
            free(pubkey_buf);
        }
        if (group != NULL) {
            EC_GROUP_free(group);
        }
        return ret;
    }
    
    int ecc_encrypt(unsigned char *plaintext, int plaintext_len,
                    EC_KEY *ecc_key, ECCCIPHERBLOB **ecc_cipherblob)
    {
        int ret = 0;
        EC_GROUP *group = NULL;
        EC_POINT *pubkey_point = NULL;
        unsigned char *pubkey_buf = NULL;
        int pubkey_len = 0;
        EVP_PKEY *pkey = NULL;
        EVP_PKEY_CTX *ctx = NULL;
        size_t cipher_len = 0;
        unsigned char *cipher_buf = NULL;
        int xcoord_len = 0;
        int ycoord_len = 0;
        int ecc_cipherblob_len = 0;
    
        // 获取 ECC 公钥
        group = EC_KEY_get0_group(ecc_key);
        pubkey_point = EC_KEY_get0_public_key(ecc_key);
        pubkey_len = EC_POINT_point2oct(group, pubkey_point,
                                        POINT_CONVERSION_UNCOMPRESSED,
                                        NULL, 0, NULL);
        if (pubkey_len <= 0) {
            printf("Error getting public key length\n");
            ret = 1;
            goto cleanup;
        }
        pubkey_buf = (unsigned char *) malloc(pubkey_len);
        if (pubkey_buf == NULL) {
            printf("Error allocating memory for public key\n");
            ret = 1;
            goto cleanup;
        }
        if (EC_POINT_point2oct(group, pubkey_point,
                                POINT_CONVERSION_UNCOMPRESSED,
                                pubkey_buf, pubkey_len, NULL) != pubkey_len) {
            printf("Error getting public key\n");
            ret = 1;
            goto cleanup;
        }
    
        // 使用 ECC 公钥加密对称密钥
        pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_EC, NULL, pubkey_buf, pubkey_len);
        if (pkey == NULL) {
            printf("Error creating EVP_PKEY\n");
            ret = 1;
            goto cleanup;
        }
        ctx = EVP_PKEY_CTX_new(pkey, NULL);
        if (ctx == NULL) {
            printf("Error creating EVP_PKEY_CTX\n");
            ret = 1;
            goto cleanup;
        }
        if (EVP_PKEY_encrypt_init(ctx) <= 0) {
            printf("Error initializing EVP_PKEY_CTX\n");
            ret = 1;
            goto cleanup;
        }
        if (EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_ENCRYPT,
                              EVP_PKEY_CTRL_EC_PADDING, ECIES_DEFAULT_PADDING, NULL) <= 0) {
            printf("Error setting EVP_PKEY_CTRL_EC_PADDING\n");
            ret = 1;
            goto cleanup;
        }
        if (EVP_PKEY_encrypt(ctx, NULL, &cipher_len, plaintext, plaintext_len) <= 0) {
            printf("Error getting cipher length\n");
            ret = 1;
            goto cleanup;
        }
        cipher_buf = (unsigned char *) malloc(cipher_len);
        if (cipher_buf == NULL) {
            printf("Error allocating memory for cipher\n");
            ret = 1;
            goto cleanup;
        }
        if (EVP_PKEY_encrypt(ctx, cipher_buf, &cipher_len, plaintext, plaintext_len) <= 0) {
            printf("Error encrypting data\n");
            ret = 1;
            goto cleanup;
        }
    
        // 填充 ECCCIPHERBLOB 结构体
        *ecc_cipherblob = (ECCCIPHERBLOB *) malloc(sizeof(ECCCIPHERBLOB) + cipher_len - 1);
        if (*ecc_cipherblob == NULL) {
            printf("Error allocating memory for ECCCIPHERBLOB\n");
            ret = 1;
            goto cleanup;
        }
        SHA256(pubkey_buf, pubkey_len, (*ecc_cipherblob)->HASH);
        (*ecc_cipherblob)->CipherLen = cipher_len;
        memcpy((*ecc_cipherblob)->Cipher, cipher_buf, cipher_len);
        xcoord_len = ecc_pubkey->XCoordinateLen;
        ycoord_len = ecc_pubkey->YCoordinateLen;
        memcpy((*ecc_cipherblob)->XCoordinate, ecc_pubkey->XCoordinate, xcoord_len);
        memcpy((*ecc_cipherblob)->YCoordinate, ecc_pubkey->YCoordinate, ycoord_len);
        ecc_cipherblob_len = sizeof(ECCCIPHERBLOB) + cipher_len - 1;
        (*ecc_cipherblob)->XCoordinate[0] |= 0x80;
        (*ecc_cipherblob)->YCoordinate[0] |= 0x80;
    
    cleanup:
        if (pubkey_buf != NULL) {
            free(pubkey_buf);
        }
        if (pkey != NULL) {
            EVP_PKEY_free(pkey);
        }
        if (ctx != NULL) {
            EVP_PKEY_CTX_free(ctx);
        }
        if (cipher_buf != NULL) {
            free(cipher_buf);
        }
        return ret;
    }
    
    int generate_enveloped_key_blob(EC_KEY *ecc_key, char *encrypted_prikey,
                                    ECCPUBLICKEYBLOB *ecc_pubkey, ENVELOPEDKEYBLOB **enveloped_key_blob)
    {
        int ret =int ecc_cipherblob_len = 0;
        ECCCIPHERBLOB *ecc_cipherblob = NULL;
    
        // 生成 ECCCIPHERBLOB 结构体
        ret = ecc_encrypt((unsigned char *)symmetric_key, symmetric_key_len, ecc_key, &ecc_cipherblob);
        if (ret != 0) {
            printf("Error encrypting symmetric key\n");
            goto cleanup;
        }
        ecc_cipherblob_len = sizeof(ECCCIPHERBLOB) + ecc_cipherblob->CipherLen - 1;
    
        // 填充 SKF_ENVELOPEDKEYBLOB 结构体
        *enveloped_key_blob = (ENVELOPEDKEYBLOB *) malloc(sizeof(ENVELOPEDKEYBLOB));
        if (*enveloped_key_blob == NULL) {
            printf("Error allocating memory for ENVELOPEDKEYBLOB\n");
            ret = 1;
            goto cleanup;
        }
        memset(*enveloped_key_blob, 0, sizeof(ENVELOPEDKEYBLOB));
        (*enveloped_key_blob)->Version = 1;
        (*enveloped_key_blob)->ulSymmAlgID = SGD_SM4_CBC;
        (*enveloped_key_blob)->ulBits = symmetric_key_len * 8;
        memcpy((*enveloped_key_blob)->cbEncryptedPriKey, encrypted_prikey, 64);
        memcpy(&((*enveloped_key_blob)->PubKey), ecc_pubkey, sizeof(ECCPUBLICKEYBLOB));
        memcpy(&((*enveloped_key_blob)->ECCCipherBlob), ecc_cipherblob, ecc_cipherblob_len);
    
    cleanup:
        if (ecc_cipherblob != NULL) {
            free(ecc_cipherblob);
        }
        return ret;
    }
    

    使用时,可以先调用 generate_ecc_key_pair 函数生成 ECC 密钥对,然后调用 generate_enveloped_key_blob 函数生成 SKF_ENVELOPEDKEYBLOB 结构体,其中 symmetric_key 表示要保护的对称密钥,symmetric_key_len 表示对称密钥的长度,encrypted_prikey 表示加密后的私钥。最终生成的 SKF_ENVELOPEDKEYBLOB 结构体可以用于加密数据时的密钥保护。


    如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

    评论

报告相同问题?

问题事件

  • 创建了问题 5月15日

悬赏问题

  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)