OpenHarmony解读之设备认证:sts协议-服务端响应sts start请求

一、概述

上文讲到,客户端设备向服务端设备发起认证start请求,本文将介绍服务端接收到请求消息后的处理过程以及如何响应客户端。

二、源码分析

这一模块的源码位于:/base/security/deviceauth。

1. 首先根据消息码字段查表得到对应解析函数parse_auth_start_request,解析认证start请求消息。
/*
函数功能:解析认证start请求消息
函数参数:
    payload:消息负载
    data_type:数据类型
函数返回值:
    成功:返回解析出来的数据结构
    失败:NULL
*/
void *parse_auth_start_request(const char *payload, enum json_object_data_type data_type)
{
    struct sts_start_request_data *auth_start_request =
        (struct sts_start_request_data *)MALLOC(sizeof(struct sts_start_request_data));//申请sts_start_request_data结构体空间保存解析的数据
    if (auth_start_request == NULL) {
        return NULL;
    }
    (void)memset_s(auth_start_request, sizeof(*auth_start_request), 0, sizeof(*auth_start_request));//清空该空间
    json_pobject obj = parse_payload(payload, data_type);//如果消息负载为json格式的字符串,则将json格式的数据解析成cjson结构体对象
    if (obj == NULL) {
        LOGE("Parse Auth Start Request parse payload failed");
        goto error;
    }
    /* op */
    int32_t op = get_json_int(obj, FIELD_OPERATION_CODE);//获取操作码
    if (op == -1) {
        LOGE("Parse Auth Start Request failed, field is null in operationCode");
        goto error;
    }
    auth_start_request->operation_code = op;
    /* challenge */
    int32_t result = byte_convert(obj, FIELD_CHALLENGE, auth_start_request->challenge.challenge,
                                  &auth_start_request->challenge.length, CHALLENGE_BUFF_LENGTH);//获取challenge值
    if (result != HC_OK) {
        LOGE("Parse Add AuthInfo Data failed, field is null in challenge");
        goto error;
    }
    /* epk */
    result = byte_convert(obj, FIELD_EPK, (uint8_t *)auth_start_request->epk.stpk,
                          &auth_start_request->epk.length, HC_ST_PUBLIC_KEY_LEN);//获取epk
    if (result != HC_OK) {
        LOGE("Parse Add AuthInfo Data failed, field is null in epk");
        goto error;
    }
    /* pkgName */
    (void)string_convert(obj, FIELD_PKG_NAME, (uint8_t *)auth_start_request->package_name.name,
                         &auth_start_request->package_name.length, HC_PACKAGE_NAME_BUFF_LEN);//获取pkgName
    /* peerAuthId */
    (void)byte_convert(obj, FIELD_PEER_AUTH_ID, (uint8_t *)auth_start_request->self_auth_id.auth_id,
                       &auth_start_request->self_auth_id.length, HC_AUTH_ID_BUFF_LEN);//获取peerAuthId
    /* peerUserType */
    int peer_user_type = get_json_int(obj, FIELD_PEER_USER_TYPE);//获取peerUserType

    auth_start_request->peer_user_type = peer_user_type;
    /* version */
    json_pobject obj_ver = get_json_obj(obj, FIELD_VERSION);//获取version
    bool ret = parse_version(obj_ver, &auth_start_request->peer_version, &auth_start_request->peer_support_version);//解析版本号
    if (!ret) {
        LOGE("Parse Auth Start Request, field is null in version");
        goto error;
    }
    free_payload(obj, data_type);//释放负载空间
    return (void *)auth_start_request;//返回解析出来的数据结构
error:
    free_payload(obj, data_type);
    FREE(auth_start_request);
    return NULL;
}
2. 根据解析出的信息,调用build_sts_server_object函数创建sts服务端对象。
//创建sts服务端对象
static void *build_sts_server_object(struct hichain *hichain, const void *params)
{
    (void)params;
    struct hc_pin pin = { 0, {0} };//定义并初始化PIN码
    struct operation_parameter para;//定义操作参数

    (void)memset_s(&para, sizeof(para), 0, sizeof(para));//清空操作参数空间
    hichain->cb.get_protocol_params(&hichain->identity, hichain->operation_code, &pin, &para);//获取协议参数,主要获取认证会话密钥长度、对端认证id和本端认证id
    if (check_param_is_valid(&para) == false) {//检查操作参数是否有效
        LOGE("Protocol param invalid");
        return NULL;
    }
    return build_sts_server(hichain, para.key_length, &para.peer_auth_id, &para.self_auth_id);//创建sts服务端对象
}

/*
函数功能:创建sts服务端对象
函数参数:
    hichain_handle:hichain实例
    key_length:密钥长度
    client:客户端认证id
    server:服务端认证id
函数返回值:
    sts服务端对象
*/
struct sts_server *build_sts_server(const hc_handle hichain_handle, uint32_t key_length,
    const struct hc_auth_id *client, const struct hc_auth_id *server)
{
    struct sts_server *sts_server = (struct sts_server *)MALLOC(sizeof(struct sts_server));//为该sts服务端对象申请空间
    if (sts_server == NULL) {
        LOGE("Build sts server object failed");
        return NULL;
    }
    (void)memset_s(sts_server, sizeof(*sts_server), 0, sizeof(*sts_server));//清空该空间
    const struct server_virtual_func_group funcs = { parse_start_request_data, build_start_response_data,
                                                     parse_end_request_data, build_end_response_data };//定义并初始化客户端虚函数组

    init_server(&sts_server->server_info, &funcs);//初始化服务端状态和打包函数
    LOGI("Build sts server object %u success", sts_server_sn(sts_server));
    sts_server->self_id = *server;//赋值服务端认证id
    sts_server->peer_id = *client;//赋值客户端认证id
    sts_server->identity = &((struct hichain *)hichain_handle)->identity;//赋值会话标识
    sts_server->key_length = key_length;//赋值密钥长度
    sts_server->hichain_handle = hichain_handle;//赋值hichain实例
    sts_server->start_request = 0;//start请求标志为0
    sts_server->ack_request = 0;//ack请求标志为0
    return sts_server;
}
3. 接着进入消息处理阶段,根据消息码查表得到对应的处理函数为proc_sts_request_message,处理sts请求消息。
/*
函数功能:处理sts请求消息
函数参数:
    handle:hichain实例
    nav:导航消息,消息头格式
    receive:接收的消息
    send:待发送消息地址
函数返回值:
    成功:0
    失败:error num
*/
static int32_t proc_sts_request_message(struct hichain *handle, struct header_analysis *nav,
    struct message *receive, struct message *send)
#if !(defined(_CUT_STS_) || defined(_CUT_STS_SERVER_))
{
    DBG_OUT("Object %u proc sts %d request message", sts_server_sn(handle->sts_server), nav->msg_type);
    int32_t ret;

    if (nav->msg_type == STS_START_MSG) {//如果消息类型为STS_START_MSG
        ret = send_sts_start_response(handle->sts_server, receive, send);//构造sts的start响应数据
    } else if (nav->msg_type == STS_END_MSG) {//如果消息类型为STS_END_MSG
        ret = send_sts_end_response(handle->sts_server, receive, send);//构造sts的end响应数据
        if (ret == HC_OK) {
            handle->cb.set_session_key(&handle->identity, &handle->sts_server->service_key);//设置会话密钥为service_key
            (void)memset_s(handle->sts_server->service_key.session_key, HC_SESSION_KEY_LEN, 0, HC_SESSION_KEY_LEN);
        }
    } else {
        return HC_UNKNOW_MESSAGE;
    }
    return ret;
}
4. 然后根据消息类型码构造响应数据,send_sts_start_response函数,构造sts协议start响应数据。
/*
函数功能:构造sts协议start响应数据
函数参数:
    handle:sts服务端对象
    receive:接收到的消息
    send:待发送的数据缓冲区地址
函数返回值:
    成功:0
    失败:error num
*/
int32_t send_sts_start_response(struct sts_server *handle, struct message *receive, struct message *send)
{
    DBG_OUT("Called send sts start response");
    check_ptr_return_val(handle, HC_INPUT_ERROR);//检查参数有效性
    check_ptr_return_val(receive, HC_INPUT_ERROR);
    check_ptr_return_val(send, HC_INPUT_ERROR);
    int32_t ret = HC_OK;
    struct sts_start_response_data *send_data =
        (struct sts_start_response_data *)MALLOC(sizeof(struct sts_start_response_data));//申请sts_start_response_data结构体空间send_data

    if (send_data == NULL) {
        LOGE("Malloc struct sts_start_request_data failed");
        return HC_MALLOC_FAILED;
    }
    (void)memset_s(send_data, sizeof(*send_data), 0, sizeof(*send_data));//清空该空间

    if (handle->start_request == 0) {
        struct sts_start_request_data *receive_data = receive->payload;//用sts_start_request_data结构接收消息负载
        ret = send_start_response(handle, receive_data, send_data);//构造start响应消息
        if (ret != HC_OK) {//执行失败
            LOGE("Called send_start_response failed, error code is %d", ret);
            FREE(send_data);
            send_data = NULL;
            send->msg_code = INFORM_MESSAGE;
        } else {//执行成功
            DBG_OUT("Called send_start_response success");
            send->msg_code = AUTH_START_RESPONSE;//设置消息码
            send->payload = send_data;//赋值待发送的数据
            handle->start_request = 1;//将start_request标志置1
            (void)memcpy_s(&handle->start_response_data, sizeof(struct sts_start_response_data),
                           send_data, sizeof(struct sts_start_response_data));//将准备好的数据拷贝到start_response_data中
        }
    } else {//如果start_request不为0,则再次调用send_start_response
        DBG_OUT("Called send_start_response again");
        send->msg_code = AUTH_START_RESPONSE;//置响应消息码为AUTH_START_RESPONSE
        (void)memcpy_s(send_data, sizeof(struct sts_start_response_data),
                       &handle->start_response_data, sizeof(struct sts_start_response_data));
        send->payload = send_data;//赋值消息负载
    }

    return ret;
}
5. send_start_response函数,构造start响应消息。
/*
函数功能:构造start响应消息
函数参数:
    handle:用于接收hichain对象
    receive_data:接收的数据
    send_data:待发送数据地址
函数返回值:
    成功:0
    失败:error
*/
int32_t send_start_response(void *handle, void *receive_data, void *send_data)
{
    check_ptr_return_val(handle, HC_INPUT_ERROR);//检查参数有效性
    check_ptr_return_val(receive_data, HC_INPUT_ERROR);
    check_ptr_return_val(send_data, HC_INPUT_ERROR);
    struct key_agreement_server *server = handle;
    struct key_agreement_protocol *base = &server->protocol_base_info;//赋值协议基础信息

    DBG_OUT("Object %u begin receive start request data and send start response data", base->sn);
    if (is_state_error(server, SEND_START_RESPONSE)) {//判断协议状态是否错误
        LOGE("Object %u state error", base->sn);
        return PROTOCOL_STATE_ERROR;
    }
    const struct server_virtual_func_group *funcs = &server->package_funcs;//赋值服务端打包函数
    int32_t ret = funcs->parse_start_request_data(handle, receive_data);//执行解析函数解析接收数据
    if (ret != HC_OK) {
        set_state(base, PROTOCOL_ERROR);
        LOGE("Object %u parse start request data failed, error code is %d", base->sn, ret);
        return ret;
    }
    ret = funcs->build_start_response_data(handle, send_data);//调用回调函数构造start响应消息
    if (ret != HC_OK) {
        set_state(base, PROTOCOL_ERROR);//设置协议状态为PROTOCOL_ERROR
        LOGE("Object %u build start response data failed, error code is %d", base->sn, ret);
        return ret;
    }
    set_state(base, START_RESPONSE);//设置协议状态为START_RESPONSE
    set_last_time_sec(base);
    DBG_OUT("Object %u receive start request data send start response data succcess", base->sn);
    return HC_OK;
}
6. 执行parse_start_request_data回调函数,解析客户端start请求数据。
/*
函数功能:解析客户端start请求数据
函数参数:
    handle:sts服务端对象
    receive_data:接收数的消息数据
函数返回值:
    成功:0
    失败:error num
*/
static int32_t parse_start_request_data(void *handle, void *receive_data)
{
    DBG_OUT("Called parse start request data");
    struct sts_server *sts_server = handle;//接收sts服务端对象
    struct sts_start_request_data *auth_start_req = receive_data;//以sts_start_request_data结构体接收数据

    DBG_OUT("Object %u begin parse PAKE start request data", sts_server_sn(sts_server));
    if (!is_peer_support_current_version(&auth_start_req->peer_version, &auth_start_req->peer_support_version)) {//检查对端是否支持当前版本
        LOGE("Object %u peer is not support current version", sts_server_sn(sts_server));
        return HC_VERSION_UNSUPPORT;
    }

    sts_server->peer_challenge = auth_start_req->challenge;//赋challenge值给sts服务端对象的对端challenge值
    sts_server->peer_public_key = auth_start_req->epk;//赋epk值给sts服务端对象的对端epk值
    sts_server->peer_user_type = auth_start_req->peer_user_type;//赋peer_user_type给sts服务端对象的对端peer_user_type

    if (sts_server->server_info.protocol_base_info.state == PROTOCOL_INIT) {//如果协议状态为初始状态
        struct st_key_pair key_pair;//定义临时密钥对
        int32_t ret = generate_st_key_pair(&key_pair);//根据X25519算法生成临时密钥对
        if (ret != HC_OK) {//生成失败
            LOGE("Object %u generate_st_key_pair failed, error code is %d", sts_server_sn(sts_server), ret);
            return HC_ST_KEY_PAIR_FAILED;
        }
        sts_server->self_public_key = key_pair.st_public_key;//将生成的密钥对作为本端密钥对
        sts_server->self_private_key = key_pair.st_private_key;

        struct random_value salt = generate_random(CHALLENGE_BUFF_LENGTH);//产生随机值salt
        if (salt.length == 0) {
            LOGE("Generate random value failed");
            return HC_GEN_RANDOM_FAILED;
        }
        if (memcpy_s(sts_server->salt.salt, sizeof(sts_server->salt.salt), salt.random_value, salt.length) != EOK) {
            return memory_copy_error(__func__, __LINE__);//拷贝salt值给服务端对象
        }
        sts_server->salt.length = salt.length;//赋值长度
    }

    struct sts_shared_secret shared_secret;//定义共享密钥shared_secret

    int32_t ret = compute_sts_shared_secret(&sts_server->self_private_key, &sts_server->peer_public_key,
                                            &shared_secret);//基于本端临时私钥和对端临时公钥利用X25519算法计算出shared_secret共享密钥
    if (ret != HC_OK) {
        LOGE("Object %u compute_shared_secret failed, error code is %d", sts_server_sn(sts_server), ret);
        return HC_COMPUTE_STS_SHARED_SECRET_FAILED;
    }
    //基于shared_secret、salt以及"hichain_auth_info"利用hkdf算法计算出一个派生密钥作为服务端会话密钥session_key
    ret = compute_hkdf((struct var_buffer *)&shared_secret, &sts_server->salt, HICHAIN_AUTH_INFO,
        STS_SESSION_KEY_LENGTH, (struct var_buffer *)&sts_server->session_key);
    if (ret != HC_OK) {
        LOGE("Object %u compute_hkdf failed, error code is %d", sts_server_sn(sts_server), ret);
        return HC_COMPUTE_HKDF_FAILED;
    }
    LOGI("Called parse start request data success!");
    return HC_OK;
}
7. build_start_response_data函数,构造start响应数据。
/*
函数功能:构造start响应数据
函数参数:
    handle:sts服务端对象
    send_data:待发送数据缓冲区地址
函数返回值:
    成功:0
    失败:error num
*/
static int32_t build_start_response_data(void *handle, void *send_data)
{
    struct sts_start_response_data *auth_start_res = send_data;//接收待发送数据
    struct signature signature;//定义签名
    int32_t ret = generate_sts_response_sign(handle, &signature);//生成sts响应签名signature
    struct sts_server *srv = handle;//接收sts服务端对象
    if (ret != HC_OK) {
        LOGE("Object %u sign failed, error code is %d", sts_server_sn(srv), ret);
        return HC_SIGN_EXCHANGE_FAILED;
    }

    struct uint8_buff auth_data;//定义认证数据缓冲区,用与存储加密的签名信息
    ret = init_auth_data(&auth_data);//初始化认证数据,获取认证数据长度,申请认证数据空间
    if (ret != HC_OK) {
        return ret;
    }
    struct aes_aad aes_aad;//aes GCM附加验证数据

    if (memcpy_s(aes_aad.aad, sizeof(aes_aad.aad), srv->peer_challenge.challenge, srv->peer_challenge.length) != EOK) {//将对端challenge值拷贝到aes_aad
        FREE(auth_data.val);
        return memory_copy_error(__func__, __LINE__);
    }
    aes_aad.length = srv->peer_challenge.length;//获取长度
    struct uint8_buff plain = { signature.signature, signature.length, signature.length };//明文信息为签名数据

    ret = aes_gcm_encrypt((struct var_buffer *)&srv->session_key, &plain, &aes_aad, &auth_data);//用会话密钥对该明文进行aes_gcm加密,输出密文保存在auth_data中
    if (ret != HC_OK) {//加密失败
        FREE(auth_data.val);
        LOGE("Object %u aes_gcm_encrypt failed, error code is %d", sts_server_sn(srv), ret);
        return HC_ENCRYPT_FAILED;
    }

    if (memcpy_s(auth_start_res->auth_data.auth_data, HC_AUTH_DATA_BUFF_LEN, auth_data.val, auth_data.length) != EOK) {//将加密后的auth_data拷贝到待发送的响应消息体中
        FREE(auth_data.val);
        return memory_copy_error(__func__, __LINE__);
    }
    auth_start_res->auth_data.length = auth_data.length;//赋值加密认证数据长度
    if (srv->server_info.protocol_base_info.state == PROTOCOL_INIT) {//如果协议为初始状态
        struct random_value random_value = generate_random(CHALLENGE_BUFF_LENGTH);//生成随机值
        if (random_value.length == 0) {
            FREE(auth_data.val);
            return HC_GEN_RANDOM_FAILED;
        }
        //产生本端的challenge值
        if (memcpy_s(srv->my_challenge.challenge, sizeof(srv->my_challenge.challenge),
            random_value.random_value, random_value.length) != EOK) {
            FREE(auth_data.val);
            return memory_copy_error(__func__, __LINE__);
        }
        srv->my_challenge.length = random_value.length;//获取challenge长度
    }
    auth_start_response_fill(srv, auth_start_res);//填充待发送响应数据

    FREE(auth_data.val);
    return HC_OK;
}
8. generate_sts_response_sign函数,生成sts响应签名。
/*
函数功能:生成sts响应签名
函数参数:
    handle:sts服务端对象
    signature:输出参数,签名地址
函数返回值:
    成功:0
    失败:error num
详细:
    首先获取要进行签名的内容:{本端公钥、本端认证id、对端公钥、对端认证id},
然后通过服务id和本端认证id生成密钥别名,利用密钥别名对该内容进行ED25519算法私钥签名,
输出内容保存在参数signature中。
*/
static int32_t generate_sts_response_sign(void *handle, struct signature *signature)
{
    struct sts_server *sts_server = handle;//接收sts服务端对象
    int32_t len = sts_server->self_public_key.length + sts_server->self_id.length +
                  sts_server->peer_public_key.length + sts_server->peer_id.length;//本端公钥、本端认证id、对端公钥、对端认证id长度之和
    uint8_t *info2 = (uint8_t *)MALLOC(len);//申请len长度的缓冲区
    if (info2 == NULL) {
        LOGE("Malloc failed");
        return HC_MALLOC_FAILED;
    }
    int32_t pos = 0;
    //将本端公钥、本端认证id、对端公钥、对端认证id按顺序拷贝到info2缓冲区中
    (void)memcpy_s(info2 + pos, len - pos, sts_server->self_public_key.stpk, sts_server->self_public_key.length);
    pos += sts_server->self_public_key.length;
    (void)memcpy_s(info2 + pos, len - pos, sts_server->self_id.auth_id, sts_server->self_id.length);
    pos += sts_server->self_id.length;
    (void)memcpy_s(info2 + pos, len - pos, sts_server->peer_public_key.stpk, sts_server->peer_public_key.length);
    pos += sts_server->peer_public_key.length;
    (void)memcpy_s(info2 + pos, len - pos, sts_server->peer_id.auth_id, sts_server->peer_id.length);
    //即 info2 = {本端公钥、本端认证id、对端公钥、对端认证id}

    struct service_id service_id = generate_service_id(sts_server->identity);//生成服务id,由会话标识符的HC包名称和HC服务类型通过sha256哈希算法计算出哈希值作为服务id
    if (service_id.length == 0) {
        LOGE("Generate service id failed");
        FREE(info2);
        return HC_GEN_SERVICE_ID_FAILED;
    }
#if (defined(_SUPPORT_SEC_CLONE_) || defined(_SUPPORT_SEC_CLONE_SERVER_))
    struct hc_key_alias key_alias = generate_key_alias(&service_id, &sts_server->self_id, KEY_ALIAS_LT_KEY_PAIR);
#else
    struct hc_key_alias key_alias = generate_key_alias(&service_id, &sts_server->self_id, KEY_ALIAS_ACCESSOR_PK);//通过服务id和本端认证id生成密钥别名,密钥类型为KEY_ALIAS_ACCESSOR_PK
#endif
    if (key_alias.length == 0) {
        LOGE("Generate key alias failed");//生成密钥别名失败
        FREE(info2);
        return HC_GEN_ALIAS_FAILED;
    }
    struct uint8_buff sign_message = { info2, len, len };//定义签名消息体
    int32_t ret = sign(&key_alias, &sign_message, signature);//将{本端公钥、本端认证id、对端公钥、对端认证id}信息利用ED25519算法进行私钥签名,输出结果保存在signature中

    FREE(info2);
    return ret;
}

//填充待发送响应数据
static void auth_start_response_fill(const struct sts_server *srv, struct sts_start_response_data *auth_start_res)
{
    auth_start_res->challenge = srv->my_challenge;//服务端challenge
    auth_start_res->salt = srv->salt;//赋值salt值
    auth_start_res->epk = srv->self_public_key;//服务端临时公钥
    auth_start_res->self_version = get_current_version();//获取当前版本
    auth_start_res->self_support_version = get_current_version();
    auth_start_res->self_auth_id = srv->self_id;//赋值本端认证id
    auth_start_res->peer_user_type = ((struct hichain *)srv->hichain_handle)->type == HC_CENTRE ?
        HC_USER_TYPE_CONTROLLER : HC_USER_TYPE_ACCESSORY;//赋值对端用户类型
}
9. 最后执行make_auth_start_response函数构造json格式的认证start响应消息。
/*
函数功能:构造json格式的认证start响应消息
函数参数:
    data:待发送数据内容地址
函数返回值:
    成功:json格式的字符串
    失败:NULL
*/
char *make_auth_start_response(void *data)
{
    struct sts_start_response_data *as_res = data;//接收该响应数据
    struct sts_start_response_data_hex tmp_hex = {0, 0, 0, 0, 0};//定义临时变量结构体
    /* authData */
    tmp_hex.tmp_auth_data_hex = raw_byte_to_hex_string(as_res->auth_data.auth_data, as_res->auth_data.length);//将原始的authData字节数据转换为十六进制的字符串
    if (tmp_hex.tmp_auth_data_hex == NULL) {
        return NULL;
    }
    /* challenge */
    tmp_hex.tmp_cha_data_hex = raw_byte_to_hex_string(as_res->challenge.challenge, as_res->challenge.length);//将原始的challenge字节数据转换为十六进制的字符串
    if (tmp_hex.tmp_cha_data_hex == NULL) {
        FREE(tmp_hex.tmp_auth_data_hex);//转换失败,释放相关内存并返回NULL
        return NULL;
    }
    /* salt */
    tmp_hex.tmp_salt_data_hex = raw_byte_to_hex_string(as_res->salt.salt, as_res->salt.length);//将原始的salt字节数据转换为十六进制的字符串
    if (tmp_hex.tmp_salt_data_hex == NULL) {
        FREE(tmp_hex.tmp_auth_data_hex);
        FREE(tmp_hex.tmp_cha_data_hex);//转换失败,释放相关内存并返回NULL
        return NULL;
    }
    /* epk */
    tmp_hex.tmp_epk_data_hex = raw_byte_to_hex_string(as_res->epk.stpk, as_res->epk.length);//将原始的epk字节数据转换为十六进制的字符串
    if (tmp_hex.tmp_epk_data_hex == NULL) {
        FREE(tmp_hex.tmp_auth_data_hex);
        FREE(tmp_hex.tmp_cha_data_hex);
        FREE(tmp_hex.tmp_salt_data_hex);//转换失败,释放相关内存并返回NULL
        return NULL;
    }
    /* peerAuthId */
    tmp_hex.tmp_auth_id_data_hex = raw_byte_to_hex_string(as_res->self_auth_id.auth_id, as_res->self_auth_id.length);//将原始的peerAuthId字节数据转换为十六进制的字符串
    if (tmp_hex.tmp_auth_id_data_hex == NULL) {
        FREE(tmp_hex.tmp_epk_data_hex);
        FREE(tmp_hex.tmp_cha_data_hex);
        FREE(tmp_hex.tmp_salt_data_hex);
        FREE(tmp_hex.tmp_auth_data_hex);//转换失败,释放相关内存并返回NULL
        return NULL;
    }
    char *ret_str = make_response_json_str(as_res, tmp_hex);

    FREE(tmp_hex.tmp_auth_data_hex);//释放相关内存
    FREE(tmp_hex.tmp_cha_data_hex);//释放相关内存
    FREE(tmp_hex.tmp_salt_data_hex);//释放相关内存
    FREE(tmp_hex.tmp_epk_data_hex);//释放相关内存
    FREE(tmp_hex.tmp_auth_id_data_hex);//释放相关内存
    return ret_str;
}

//构造json字符串响应消息
static char *make_response_json_str(struct sts_start_response_data *as_res,
                                    struct sts_start_response_data_hex tmp_hex)
{
    char *tmp_str = (char *)MALLOC(RET_STR_LENGTH);//申请字符串空间
    if (tmp_str == NULL) {
        return NULL;
    }

    (void)memset_s(tmp_str, RET_STR_LENGTH, 0, RET_STR_LENGTH);//清空该空间
    if (snprintf_s(tmp_str, RET_STR_LENGTH, RET_STR_LENGTH - 1,
        "{\"%s\":%d,\"%s\":%d,\"%s\":{\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":\"%s\",\"%s\":\"%s\","
        "\"%s\":{\"%s\":\"%u.%u.%u\",\"%s\":\"%u.%u.%u\"},\"%s\":\"%s\",\"%s\":\"%d\"}}",
        FIELD_AUTH_FORM, AUTH_FORM, FIELD_MESSAGE, AUTH_START_RESPONSE, FIELD_PAYLOAD, FIELD_AUTH_DATA,
        tmp_hex.tmp_auth_data_hex, FIELD_CHALLENGE, tmp_hex.tmp_cha_data_hex, FIELD_EPK,
        tmp_hex.tmp_epk_data_hex, FIELD_SALT, tmp_hex.tmp_salt_data_hex,
        FIELD_VERSION, FIELD_CURRENT_VERSION, as_res->self_version.first,
        as_res->self_version.second, as_res->self_version.third, FIELD_MIN_VERSION,
        as_res->self_support_version.first, as_res->self_support_version.second,
        as_res->self_support_version.third, FIELD_PEER_AUTH_ID, tmp_hex.tmp_auth_id_data_hex,
        FIELD_PEER_USER_TYPE, as_res->peer_user_type) < 0) {
        LOGE("String generate failed");
        FREE(tmp_str);
        tmp_str = NULL;
    }//构造json字符串
    return tmp_str;
}

三、小结

经过分析,得到服务端回复的响应消息格式如下:

{
    "authForm":0,           //AUTH_FORM
    "message":0x8011,       //消息码:AUTH_START_RESPONSE
    "payload":
    {
        "authData":"十六进制格式的字符串",      //加密的签名消息,ED25519算法进行私钥签名
        "challenge":"十六进制格式的字符串",     //基于“挑战/响应”方式的挑战值,是一个随机值
        "epk":"十六进制格式的字符串",           //服务端临时公钥
        "salt":"十六进制格式的字符串",          //由服务端生成的一个随机值
        "version":
        {
            "currentVersion":"1.0.0",
            "minVersion":"1.0.0",
        },
        "peerAuthId":"十六进制格式的字符串",    //对端认证id(服务端)
        "peerUserType":""
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值