使用OpenSSL的KAS-ECC OnepassDH

使用OpenSSL的KAS-ECC OnepassDH,openssl,Openssl,我希望使用OpenSSL为KAS-ECC OnepassDH模式开发代码。这样做的逻辑可以在中找到。所附图像显示了完成此操作的步骤: 我尝试过这样做,如下所示: make_peer() { peer = EC_POINT_new(group); c = BN_CTX_new(); EC_POINT_set_affine_coordinates_GFp(group, peer, x, y, c); } onepassDH() { unsi

我希望使用OpenSSL为KAS-ECC OnepassDH模式开发代码。这样做的逻辑可以在中找到。所附图像显示了完成此操作的步骤:

我尝试过这样做,如下所示:

make_peer() {
    peer = EC_POINT_new(group);
    c = BN_CTX_new();
    EC_POINT_set_affine_coordinates_GFp(group, peer, x, y, c);
}

onepassDH() {
                unsigned char Zs[256];
                unsigned char Ze[256];

                // derive private key from input public key
                qsCAVSx = BN_bin2bn(qsCAVSx, qsCAVSxLength, qsCAVSx);
                qsCAVSy = BN_bin2bn(qsCAVSy, qsCAVSyLength, qsCAVSy);
                peerkey = make_peer(group, qsCAVSx, qsCAVSy);
                if(NULL == peerkey)
                   goto fail;

                // Other party key
                ecKey = EC_KEY_new();
                if ( ecKey == NULL  ) {
                   LOG_ERROR("failed to create ecKey\n");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }
                EC_KEY_set_flags(ecKey, EC_FLAG_COFACTOR_ECDH);  

                if ( 0 == EC_KEY_set_group(ecKey, group) ) {
                   LOG_ERROR("cannot set group\n");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                if ( 0 == EC_KEY_generate_key(ecKey) ) {
                   LOG_ERROR("cannot generate key\n");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                //extract public key from other party's key pair

                ec_ctx = BN_CTX_new();
                if ( !ec_ctx ) {
                   LOG_ERROR("BN_CTX_new() returned NULL in %s at line %d\n", __FILE__, __LINE__);
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }
                qeIUTx = BN_CTX_get(ec_ctx);
                qeIUTy = BN_CTX_get(ec_ctx);
                if ( !qeIUTx || !qeIUTy ) {
                   LOG_ERROR("BN_CTX_get() returned NULL in %s at line %d\n", __FILE__, __LINE__);
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                grp = EC_KEY_get0_group(ecKey);
                if ( grp == NULL ) {
                   LOG_ERROR("EC_KEY_get0_group() returned NULL!");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                pt = EC_KEY_get0_public_key(ecKey);
                if ( pt == NULL ) {
                   LOG_ERROR("EC_KEY_get0_public_key() returned NULL!");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                meth = EC_GROUP_method_of(grp);
                if ( meth == NULL ) {
                   LOG_ERROR("EC_GROUP_method_of() returned NULL\n");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                // this uses "grp", "pt", and "ctx" to set "tx" and "ty"
                EC_POINT_get_affine_coordinates_GFp(grp, pt, qeIUTx, qeIUTy, ec_ctx);


                qeIUTxLength  = BN_num_bytes(qeIUTx);

                qeIUTyLength  = BN_num_bytes(qeIUTy);

                zLength = (EC_GROUP_get_degree(group) + 7)/8;

                ECDH_compute_key(Zs, zLength, peerkey, ecKey, 0);

                // Generate ephemeral key
                de_Key = EC_KEY_new();
                if ( de_Key == NULL  ) {
                   LOG_ERROR("failed to create ecKey\n");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }
                EC_KEY_set_flags(de_Key, EC_FLAG_COFACTOR_ECDH);  // <--- this is the FIPS-dependant part

                if ( 0 == EC_KEY_set_group(de_Key, group) ) {
                   LOG_ERROR("cannot set group\n");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                if ( 0 == EC_KEY_generate_key(de_Key) ) {
                   LOG_ERROR("cannot generate key\n");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                ec_ctx = BN_CTX_new();
                if ( !ec_ctx ) {
                   LOG_ERROR("BN_CTX_new() returned NULL in %s at line %d\n", __FILE__, __LINE__);
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }
                qeIUTx = BN_CTX_get(ec_ctx);
                qeIUTy = BN_CTX_get(ec_ctx);
                if ( !qeIUTx || !qeIUTy ) {
                   LOG_ERROR("BN_CTX_get() returned NULL in %s at line %d\n", __FILE__, __LINE__);
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                grp = EC_KEY_get0_group(de_Key);
                if ( grp == NULL ) {
                   LOG_ERROR("EC_KEY_get0_group() returned NULL!");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                pt = EC_KEY_get0_public_key(de_Key);
                if ( pt == NULL ) {
                   LOG_ERROR("EC_KEY_get0_public_key() returned NULL!");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                meth = EC_GROUP_method_of(grp);
                if ( meth == NULL ) {
                   LOG_ERROR("EC_GROUP_method_of() returned NULL\n");
                   LOG_ERROR("OpenSSL reports:   %s\n", ERR_error_string(ERR_get_error(), NULL));
                   goto fail;
                }

                // this uses "grp", "pt", and "ctx" to set "tx" and "ty"
                EC_POINT_get_affine_coordinates_GFp(grp, pt, qeIUTx, qeIUTy, ec_ctx);
                ECDH_compute_key(Ze, zLength, de_priv_key, ecKey, 0);

                zLength = 2 * ((EC_GROUP_get_degree(group) + 7)/8);
                memcpy(Z, Ze, zLength/2);
                memcpy(Z+(zLength/2), Zs, zLength/2);

                ECDH_compute_key(Z, zLength, peerkey, ecKey, 0);
                // Hash the sharesecret
                ctx = EVP_MD_CTX_create();
                if ( 0 == EVP_DigestInit_ex(ctx, md, NULL) ) {
                   LOG_ERROR("error in %s, line%d; sha_type %d\n", __FILE__, __LINE__, md->md_size * 8);
                   ERR_print_errors_fp(stderr);
                   goto fail;
                }
                if ( 0 == EVP_DigestUpdate(ctx, Z, zLength) ) {
                   LOG_ERROR("error in %s, line%d\n", __FILE__, __LINE__);
                   ERR_print_errors_fp(stderr);
                   goto fail;
                }
                if ( 0 == EVP_DigestFinal_ex(ctx, iutTag, &count) ) {
                   LOG_ERROR("error in %s, line%d\n", __FILE__, __LINE__);
                   ERR_print_errors_fp(stderr);
                   goto fail;
                }
        }
}

KAS-ECC alg的问题是,我在网上看不到多少帮助来实现这一点。我找到了几个链接:,但在为OnePassDH编写代码方面帮不了我多少忙。有人能告诉我我的代码有什么问题吗?现在代码本身不会抛出错误,但对任何输入都会给出相同的结果。

摘要

我已经通过OpenSSL实现了ECDH,并使用测试向量进行测试。我希望这个答案会有所帮助


算法描述

注意:下面的伪代码只是一条路径,因为它是从更复杂的系统简化而来的。将不会提到许多确切的类型或进行错误检查

小结:从曲线创建EC_组,从公钥和私钥的字节数组创建EC_密钥、EVP_PKEY结构,为DH操作创建EVP_PKEY_上下文,派生密钥

  • 按曲线名称创建EC_组:

    auto order = EC_GROUP_new_by_curve_name(NID_curve)
    
  • 创建私钥(这只是一个随机数):

  • 获取另一方的公钥:

    std::vector<uint8_t> otherKey = getOtherKey();
    
  • 衍生秘密:

    EVP_PKEY_derive_set_peer(pkeyCtx, publicEvpPkey);
    size_t length = 0;
    EVP_PKEY_derive(pkeyCtx, nullptr, &length);
    std::vector<uint8_t> secret(length);
    EVP_PKEY_derive(pkeyCtx, secret.data(), &length);
    
    这里[QCAVSx,QCAVSy]和[QIUTx,QIUTy]-分别是CAV(远程用户)和IUT(用户)的公共向量。为了将此数据用作OpenSSL的公钥,我通过连接两个坐标并在开头添加“04”(04是未压缩表单的标记):04[x坐标][y坐标],从这两个坐标创建了未压缩表单。 dIUT是IUT的私钥。 ZIUT是一个秘密,它是参考结果

    我将dIUT和未压缩的QCAVS公钥作为字节数组,通过BN_bin2bn()函数与OpenSSL一起使用,在上述算法的帮助下,我的测试成功了

    std::vector<uint8_t> otherKey = getOtherKey();
    
    //Create EC_KEY
    auto key = EC_KEY_new();
    EC_KEY_set_group(key, group);
    ECDSA_set_method(key, ECDSA_get_default_method());
    EC_KEY_set_private_key(key, prvKey);
    
    //Create EVP_PKEY and set EC_KEY there
    auto pkey = EVP_PKEY_new();
    EVP_PKEY_set1_EC_KEY(pkey, key);
    
    //Create EVP_PKEY for public key:
    auto publicEcKey = EC_KEY_new();
    EC_KEY_set_group(publicEcKey, group);
    ECDSA_set_method(publicEcKey, ECDSA_get_default_method());
    EC_POINT point = EC_POINT_new(group);
    EC_POINT_oct2point(group, point, otherKey.data(), otherKey.size());
    EC_KEY_set_public_key(publicEcKey, point);
    auto publicEvpPkey = EVP_PKEY_new();
    EVP_PKEY_set1_EC_KEY(publicEvpPkey, publicEcKey);
    
    
    //Create EVP_PKEY_CTX
    auto pkeyCtx = EVP_PKEY_CTX_new(pkey, nullptr);
    EVP_PKEY_derive_init(pkeyCtx);
    
    EVP_PKEY_derive_set_peer(pkeyCtx, publicEvpPkey);
    size_t length = 0;
    EVP_PKEY_derive(pkeyCtx, nullptr, &length);
    std::vector<uint8_t> secret(length);
    EVP_PKEY_derive(pkeyCtx, secret.data(), &length);
    
    [P-192]
    
    COUNT = 0
    QCAVSx = 42ea6dd9969dd2a61fea1aac7f8e98edcc896c6e55857cc0
    QCAVSy = dfbe5d7c61fac88b11811bde328e8a0d12bf01a9d204b523
    dIUT = f17d3fea367b74d340851ca4270dcb24c271f445bed9d527
    QIUTx = b15053401f57285637ec324c1cd2139e3a67de3739234b37
    QIUTy = f269c158637482aad644cd692dd1d3ef2c8a7c49e389f7f6
    ZIUT = 803d8ab2e5b6e6fca715737c3a82f7ce3c783124f6d51cd0