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

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":""    }}