«
PCQQ ECDH算法源码

时间:2021-12-9    作者:范文泉    分类: 编程


.h文件

#ifndef __ECDH_H_
#define __ECDH_H_

#include <string>

namespace qq{

    typedef void        EC_KEY;
    typedef void        EC_GROUP;
    typedef void        EC_POINT;
    typedef void        BN_CTX;

    typedef enum {
        /** the point is encoded as z||x, where the octet z specifies
        *  which solution of the quadratic equation y is  */
        POINT_CONVERSION_COMPRESSED = 2,
        /** the point is encoded as z||x||y, where z is the octet 0x04  */
        POINT_CONVERSION_UNCOMPRESSED = 4,
        /** the point is encoded as z||x||y, where the octet z specifies
        *  which solution of the quadratic equation y is  */
        POINT_CONVERSION_HYBRID = 6
    } point_conversion_form_t;

    typedef EC_KEY*  (__cdecl *PFN_EC_KEY_new_by_curve_name)(int nid);
    typedef EC_GROUP* (__cdecl *PFN_EC_KEY_get0_group)(EC_KEY* ecKey);
    typedef EC_POINT* (__cdecl *PFN_EC_POINT_new)(const EC_GROUP *group);
    typedef int(__cdecl *PFN_EC_KEY_generate_key)(EC_KEY* ecKey);
    typedef int(__cdecl *PFN_EC_POINT_point2oct)(const EC_GROUP *group, const EC_POINT *p, point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *ctx);
    typedef const EC_POINT* (__cdecl *PFN_EC_KEY_get0_public_key)(const EC_KEY *key);
    typedef int(__cdecl *PFN_EC_POINT_oct2point)(const EC_GROUP *group, EC_POINT *p, const unsigned char *buf, size_t len, BN_CTX *ctx);
    typedef int(__cdecl *PFN_ECDH_compute_key)(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *ecdh, void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen));

    #define NID_secp192k1           711 

    class ECDH{
    public:
        ECDH();
        ~ECDH();

    private:
        void* m_pEC_Key;
        void* m_pEC_Group;
        void* m_pEC_Point;

        PFN_EC_KEY_new_by_curve_name EC_KEY_new_by_curve_name;
        PFN_EC_KEY_get0_group EC_KEY_get0_group;
        PFN_EC_POINT_new EC_POINT_new;
        PFN_EC_KEY_generate_key EC_KEY_generate_key;
        PFN_EC_POINT_point2oct EC_POINT_point2oct;
        PFN_EC_KEY_get0_public_key EC_KEY_get0_public_key;
        PFN_EC_POINT_oct2point EC_POINT_oct2point;
        PFN_ECDH_compute_key ECDH_compute_key;

    public:
        bool First(std::string& strPublic, std::string& strShare);
        std::string Twice(unsigned char* tk);
    };

}

#endif

.cpp文件

#include "StdAfx.h"
#include "ECDH.h"
#include "../Util/string_ext.h"

namespace qq {

    ECDH::ECDH() :
        m_pEC_Key(NULL),
        m_pEC_Group(NULL),
        m_pEC_Point(NULL)
    {
        HMODULE hModule = ::LoadLibrary("libeay32.dll");        
        if (hModule == NULL)
        {
            MessageBox(0, "请检查目录下是否存在libeay32.dll!", "错误", MB_ICONERROR|MB_OK);
            exit(0);
        }

        EC_KEY_new_by_curve_name = (PFN_EC_KEY_new_by_curve_name)::GetProcAddress(hModule, "EC_KEY_new_by_curve_name");
        EC_KEY_get0_group = (PFN_EC_KEY_get0_group)::GetProcAddress(hModule, "EC_KEY_get0_group");
        EC_POINT_new = (PFN_EC_POINT_new)::GetProcAddress(hModule, "EC_POINT_new");
        EC_KEY_generate_key = (PFN_EC_KEY_generate_key)::GetProcAddress(hModule, "EC_KEY_generate_key");
        EC_POINT_point2oct = (PFN_EC_POINT_point2oct)::GetProcAddress(hModule, "EC_POINT_point2oct");
        EC_KEY_get0_public_key = (PFN_EC_KEY_get0_public_key)::GetProcAddress(hModule, "EC_KEY_get0_public_key");
        EC_POINT_oct2point = (PFN_EC_POINT_oct2point)::GetProcAddress(hModule, "EC_POINT_oct2point");
        ECDH_compute_key = (PFN_ECDH_compute_key)::GetProcAddress(hModule, "ECDH_compute_key");
    }

    ECDH::~ECDH()
    {   
    }

    bool ECDH::First(std::string& strPublic, std::string& strShare)
    {
        strPublic = _T("");
        strShare = _T("");

        //QQ的tk,不同版本可能会变,这里是8.9的
        unsigned char tk[49] = { 0x04, 0xBF, 0x47, 0xA1, 0xCF, 0x78, 0xA6, 0x29, 0x66, 0x8B,
            0x0B, 0xC3, 0x9F, 0x8E, 0x54, 0xC9, 0xCC, 0xF3, 0xB6, 0x38,
            0x4B, 0x08, 0xB8, 0xAE, 0xEC, 0x87, 0xDA, 0x9F, 0x30, 0x48,
            0x5E, 0xDF, 0xE7, 0x67, 0x96, 0x9D, 0xC1, 0xA3, 0xAF, 0x11,
            0x15, 0xFE, 0x0D, 0xCC, 0x8E, 0x0B, 0x17, 0xCA, 0xCF
        };

        unsigned char ucPublic[25] = {0};
        unsigned char ucShare[16] = {0};

        m_pEC_Key = EC_KEY_new_by_curve_name(NID_secp192k1);
        m_pEC_Group = EC_KEY_get0_group(m_pEC_Key);
        m_pEC_Point = EC_POINT_new(m_pEC_Group);
        if (EC_KEY_generate_key(m_pEC_Key) == 1){
            EC_POINT_point2oct(m_pEC_Group, EC_KEY_get0_public_key(m_pEC_Key), POINT_CONVERSION_COMPRESSED, ucPublic, 25, 0);
            if (EC_POINT_oct2point(m_pEC_Group, m_pEC_Point, tk, 49, 0) == 1){
                ECDH_compute_key(ucShare, 16, m_pEC_Point, m_pEC_Key, 0);
            }
        }

        strPublic = byte_to_hexstr(ucPublic, 25);
        strShare = byte_to_hexstr(ucShare, 16);

        return true;
    }

    std::string ECDH::Twice(unsigned char* tk)
    {
        unsigned char ucShare[16] = { 0 };
        if (EC_POINT_oct2point(m_pEC_Group, m_pEC_Point, tk, 49, 0) == 1)
            ECDH_compute_key(ucShare, 16, m_pEC_Point, m_pEC_Key, 0);

        return byte_to_hexstr(ucShare, 16);
    }
}

标签: pcqq 算法 加密