Huks功能之frameworks解析:hks_access.h hks_access.c cipher.h cipher.c_huks加密文件-程序员宅基地

技术标签: c语言  华为  harmonyos  

1.huks功能概括

huks为应用提供密钥库及密钥管理功能,包括密钥的生成,删除,更新。
为系统下应用提供KeyStore密钥库管理以及Crypto密钥密码学相关操作。
其中的Crypto面向应用层
KeyStore的管理操作不能由应用层直接接触,而是需要获得更高的权限才能访问。

2.frameworks重点头文件和库功能分析

2.1代码也有“程序正义”之hks_access.h

很关键的变量声明:int32_t status
之前一直以为是状态的标志,标志着操作的正在进行or已完成
但是根据这个变量在本文件函数返回值大频率出现,结合各函数的作用,以及对安全性的考虑,这个status应该是权限的意思,即描述命令发出者到底有没有权限进行所请求的安全操作。
这样一来,整个文件的作用也发生了改变。
这个文件主要用来申请各种操作权限。就像一封文书,要经过道道关卡的审核才能公开发表,说白了就是走流程

1.安全请求与操作权限:“想做与能做” sec_mod_msg结构体

命令者不光要发送安全请求,还要携带该请求的权限许可才能进行相关操作。
该结构体中的枚举类型hks_cmd_type列举了13中可进行的安全操作
union共用体中存储了描述各种安全操作的结构体

struct sec_mod_msg {
    
    enum hks_cmd_type cmd_id;   //枚举类型
    int32_t status;//权限
    union {
     
        struct hks_generate_key_msg generate_key_msg;//产生密钥的安全操作
        struct hks_generate_ex_msg generate_ex_msg;
        struct hks_encrypt_decrypt_msg encrypt_decrypt_msg;//加密解密
        struct hks_sign_verify_msg sign_verify_msg;//核实信息
        struct hks_import_key_msg import_key_msg;//导入密钥
        struct hks_export_key_msg export_key_msg;//导出密钥
        struct hks_delete_key_msg delete_key_msg;//删除密钥信息
        struct hks_get_key_param_msg get_key_param_msg;//获取密钥关键信息
        struct hks_key_exist_msg key_exist_msg;//判断密钥是否存在
        struct hks_generate_random_msg generate_random_msg;//产生随机数
        struct hks_key_agreement_msg key_agreement_msg;//hks协议
        struct hks_key_derivation_msg key_derivation_msg;
        struct hks_hmac_msg hmac_msg;
        struct hks_hash_msg hash_msg;//哈希运算信息
        struct hks_bn_exp_mod_msg bn_exp_mod_msg;
        struct hks_get_pub_key_list_msg get_pub_key_list_msg;//获取公钥列表信息
    } msg_data;
};

以生成密钥HKS_GENERATE_KEY请求为例
在枚举hks_cmd_type中描述生成密钥的信息标志为HKS_GENERATE_KEY
结构体描述生成密钥的所需信息

struct hks_generate_key_msg {
    
    const struct hks_blob *key_alias;//密钥别名
    const struct hks_key_param *key_param; //密钥参数
    struct hks_encrypt_material *key_material; //密钥材料
};

2.操作权限申请之:KeyStore操作相关函数声明:

主要定义了KeyStore相关操作,如安全操作确认、密钥产生、删除、核实、导入导出。在密钥加密以及解密过程中加以AEAD来确保密钥的完整性,进而保证加密与解密过程的正确性。

typedef void (*hks_handle_func_p)(struct sec_mod_msg *msg_box);
void hks_enter_secure_mode(struct sec_mod_msg *msg); //进入安全模式并调用处理安全请求
void hks_handle_secure_call(void);//处理安全请求

int32_t hks_access_init(void);//权限初始化
void hks_access_destroy(void);//权限销毁
int32_t hks_access_refresh_key_info(void);//更新密钥信息
int32_t hks_access_generate_key(const struct hks_blob *key_alias,
    const struct hks_key_param *key_param);//生成密钥信息,传入密钥别名、关键信息
int32_t hks_access_generate_key_ex(                              
    const struct hks_key_param *key_param, struct hks_blob *priv_key, struct hks_blob *pub_key);//生成密钥对,包括私钥公钥
int32_t hks_access_sign(const struct hks_blob *key_alias,
    const struct hks_key_param *key_param, const struct hks_blob *hash, struct hks_blob *signature);//hks签名
int32_t hks_access_verify(const struct hks_blob *key_alias,
    const struct hks_blob *hash, const struct hks_blob *signature);//hks核实确认,包括密码别名、哈希值、签名,确认密钥没有被更改,保护密钥的完整性
int32_t hks_access_aead_encrypt(const struct hks_blob *key,
    const struct hks_key_param *key_param, const struct hks_crypt_param *crypt_param,
    const struct hks_blob *plain_text, struct hks_blob *cipher_text_with_tag);//利用AEAD在加密过程中对密钥的完整性进行保护措施
int32_t hks_access_aead_decrypt(const struct hks_blob *key,
    const struct hks_key_param *key_param, const struct hks_crypt_param *crypt_param,
    const struct hks_blob *cipher_text_with_tag, struct hks_blob *plain_text);//利用AEAD确认解密过程的正确性,即保证密钥的在传输中不被修改
int32_t hks_access_import_key(const struct hks_blob *key_alias,
    const struct hks_key_param *key_param, const struct hks_blob *key);//密钥库管理之导入密钥
int32_t hks_access_export_key(const struct hks_blob *key_alias, struct hks_blob *key);//密钥库管理之导出密钥
int32_t hks_access_delete_key(const struct hks_blob *key_alias);//删除密钥
int32_t hks_access_is_key_exist(const struct hks_blob *key_alias);//判断密钥是否存在
int32_t hks_access_get_key_param(const struct hks_blob *key_alias,
    struct hks_key_param *key_param);//获取密钥关键参数
int32_t hks_access_get_random(struct hks_blob *random);//获取随机数
int32_t hks_access_hmac(const struct hks_blob *key,
    uint32_t alg, const struct hks_blob *src_data, struct hks_blob *output);
int32_t hks_access_hash(uint32_t alg, const struct hks_blob *src_data, struct hks_blob *hash);
int32_t hks_access_key_agreement(struct hks_blob *agreed_key,
    const struct hks_key_param *private_key_param, const struct hks_blob *private_key,
    const struct hks_blob *peer_public_key, const uint32_t agreement_alg);
int32_t hks_access_key_derivation(struct hks_blob *derived_key,
    const struct hks_blob *kdf_key, const struct hks_blob *salt,
    const struct hks_blob *label, const struct hks_key_param *key_params);
int32_t hks_access_bn_exp_mod(struct hks_blob *x,
    const struct hks_blob *a, const struct hks_blob *e, const struct hks_blob *n);
int32_t hks_access_get_pub_key_alias_list(
    struct hks_blob *key_alias_list, uint32_t *list_count);

2.2密码学操作之cipher.h*

此头文件用来定义加密模式、密文、密钥、初始化向量等相关结构体及相关函数,供cipher_aes.c和cipher_rsa.c使用
密文=明文+密钥+初始化向量

typedef enum {
    
    CIPHER_AES_ECB,//ECB模式加密,初始定义为0
    CIPHER_AES_CBC//CBC模式加密,初始定义为1
} CipherAesMode;//AES加密模式

typedef struct {
    
    char *text;//要加密的密文
    char *key;//密钥
    int32_t action;
    int32_t textLen;//密文长度
    int32_t keyLen;//密钥长度
} CryptData;//密文

typedef struct {
    
    char *transformation;//向量的更新
    char *ivBuf;
    int32_t ivOffset;//向量补偿
    int32_t ivLen;//向量长度
} AesIvMode;//aes生成初始化向量向量

typedef struct {
    
    CryptData data;//密文
    CipherAesMode mode;//密钥
    AesIvMode iv;//向量
} AesCryptContext;

typedef struct {
    
    char *data;
    size_t length;
} RsaData;

typedef struct {
    
    char *trans;
    char *action;
    char *key;
    size_t keyLen;
} RsaKeyData;//rsa密文

int32_t InitAesCryptData(const char *action, const char *text, const char *key,const AesIvMode *iv, AesCryptContext *aesCryptCxt);//
int32_t AesCrypt(AesCryptContext *aesCryptCxt);
void DeinitAesCryptData(AesCryptContext *aesCryptCxt);
int32_t RsaCrypt(RsaKeyData *key, RsaData *inData, RsaData *outData);

3.关键函数分析

3.1“程序正义”之hks_access.c

一个人拎包入住酒店的时候,先要去前台选房间,然后领房卡,才能入住。
选房间就像选择13种安全请求,分配房卡就是这个函数的作用。
这个函数主要是给命令发出者分配权限,以执行发出的安全请求。
但是,对于一个命令发出者,不是它所有的安全请求都能给分配权限
就像酒店有些房间就是只有高权限人员才能刷卡进入,比如机房、设备间等

1.安全请求

进入安全模式了
__hks_handle_secure_call(struct sec_mod_msg *msg_box)

static void __hks_handle_secure_call(struct sec_mod_msg *msg_box)
{
    
    if (msg_box == NULL)
        return;
    //通过msg_box访问存储了安全操作请求描述信息的结构体sec_mod_msg内cmd_id变量,判断操作信息是否为0~13中的一个,是则进行下一步权限判断确认
    if (msg_box->cmd_id < HKS_CMD_MAX) {
    
        if (g_hks_handle_func[msg_box->cmd_id])
            g_hks_handle_func[msg_box->cmd_id](msg_box);
    } else {
    
        msg_box->status = HKS_ERROR_NOT_SUPPORTED; //未定义cmd_id所表述的操作信息,不支持进行的操作
    }
}

首先用安全请求结构体指针msg_box接收传入的安全请求信息
如果msg_box为空则结束该函数
如果0<cmd_id<13则进入调用相关函数处理

2.有些安全请求不给权限

数组g_hks_handle_func[HKS_CMD_MAX]的初始化

hks_handle_func_p g_hks_handle_func[HKS_CMD_MAX] = {
    
#ifndef _CUT_AUTHENTICATE_  //如果_CUT_authenticate_被define过,则给数组赋值所有安全操作。
    hks_handle_generate_key,
    hks_handle_generate_key_ex,
    hks_handle_sign,
    hks_handle_verify,
    hks_handle_encrypt,
    hks_handle_decrypt,
    hks_handle_import,
    hks_handle_export,
    hks_handle_get_random,
    hks_handle_key_agreement,
    hks_handle_key_deviration,
    hks_handle_hmac,
    hks_handle_hash,
    hks_handle_bn_exp_mod,
#else//如果没定义过,则仅赋值一部分安全请求,配合hks_handle_secure_call里面的条件判断使用。
    NULL,
    NULL,
    NULL,
    NULL,
    hks_handle_encrypt,
    hks_handle_decrypt,
    NULL,
    NULL,
    hks_handle_get_random,
    NULL,
    hks_handle_key_deviration,
    hks_handle_hmac,
    NULL,
    hks_handle_bn_exp_mod,
#endif
};

其中 CUT_AUTHENTICATE 是标志该请求是否有减少认证环节的权限。
如果通过,则将数组每位初始化为对应的操作标志数,后续直接调用相关函数。
如果没有,则仅可以执行一些低权限操作。
我们观察成为NULL的几个权限,发现都与密钥库有关。
有了房卡,只能进出房间,但没有权限对房卡管理系统进行操作
房卡管理系统就是密钥库

3.密钥对的产生:“房卡制造”

产生密钥对(公钥与私钥)
//将密钥信息描述放在这里方便查看

struct hks_generate_key_msg {
    
    const struct hks_blob *key_alias;//密钥别名
    const struct hks_key_param *key_param; //密钥参数
    struct hks_encrypt_material *key_material; //密钥材料
};

此函数主要是用传入的信息给密钥变量赋值,包括密钥别名、密钥关键信息等等。
在给密钥变量赋值的同时,发出安全请求,并进入安全模式。

//接收密钥别名和密钥关键参数(密钥结构体)
int32_t hks_access_generate_key(const struct hks_blob *key_alias,
    const struct hks_key_param *key_param)
{
    
    
    struct sec_mod_msg msg_box;//声明安全模式变量

    (void)memset_s(&msg_box, sizeof(msg_box), 0, sizeof(msg_box));
	//用0填充msg_box地址区域
    struct hks_generate_key_msg *msg = &msg_box.msg_data.generate_key_msg;//指针msg指向存有描述密钥信息的地址。
	
    msg_box.cmd_id = HKS_GENERATE_KEY;//将cmd_id变量设置为“生成密钥”安全请求信息
    msg->key_alias = key_alias;//给对象密钥别名赋值
    msg->key_param = key_param;//给对象密钥关键信息赋值
    hks_enter_secure_mode(&msg_box);
    return msg_box.status;//返回权限
}

该函数主要用来申请生成公钥私钥的权限,包括在过程中更新安全请求状态。过程与hks_access_generate_key类似

int32_t hks_access_generate_key_ex(const struct hks_key_param *key_param, struct hks_blob *priv_key//私钥,
    struct hks_blob *pub_key//公钥)
{
    
    struct sec_mod_msg msg_box;
    (void)memset_s(&msg_box, sizeof(msg_box), 0, sizeof(msg_box));

    struct hks_generate_ex_msg *msg = &msg_box.msg_data.generate_ex_msg;

    msg_box.cmd_id = HKS_GENERATE_KEY_EX;//将安全请求调整为“生成密钥对”
    msg->key_param = key_param;
    msg->priv_key = priv_key;
    msg->pub_key = pub_key;
    hks_enter_secure_mode(&msg_box);
    return msg_box.status;
}


4.密钥对完整性保护:“防止房卡被篡改”

在对称加密算法中,任何一把密钥都可以对密文进行解密操作,但是仅有加密时使用的那把密钥能解密出正确完整的明文。所以酒店房间长得跟图片上不一样,可能是房卡出错了哦(doge)

int32_t hks_access_aead_encrypt(const struct hks_blob *key, const struct hks_key_param *key_param,
    const struct hks_crypt_param *crypt_param, const struct hks_blob *plain_text, struct hks_blob *cipher_text_with_tag)
    //传入密钥、密钥参数、加密参数、明文、密码的签名
{
    
    struct sec_mod_msg msg_box;

    (void)memset_s(&msg_box, sizeof(msg_box), 0, sizeof(msg_box));

    struct hks_encrypt_decrypt_msg *msg = &msg_box.msg_data.encrypt_decrypt_msg;

    msg_box.cmd_id = HKS_ENCRYPT;//安全请求设为加密
    //给相关参数赋值
    msg->key = key;
    msg->key_param = key_param;
    msg->crypt_param = crypt_param;
    msg->plain_text = (struct hks_blob *)plain_text;
    msg->cipher_text_with_tag = cipher_text_with_tag;
    hks_enter_secure_mode(&msg_box);//进入安全模式

    return msg_box.status;//返回权限
}

//解密与加密类似
int32_t hks_access_aead_decrypt(const struct hks_blob *key, const struct hks_key_param *key_param,
    const struct hks_crypt_param *crypt_param, const struct hks_blob *cipher_text_with_tag, struct hks_blob *plain_text)
{
    
    struct sec_mod_msg msg_box;

    (void)memset_s(&msg_box, sizeof(msg_box), 0, sizeof(msg_box));

    struct hks_encrypt_decrypt_msg *msg = &msg_box.msg_data.encrypt_decrypt_msg;

    msg_box.cmd_id = HKS_DECRYPT;
    msg->key = key;
    msg->key_param = key_param;
    msg->crypt_param = crypt_param;
    msg->plain_text = plain_text;
    msg->cipher_text_with_tag = (struct hks_blob *)cipher_text_with_tag;
    hks_enter_secure_mode(&msg_box);

    return msg_box.status;
}
5.密钥库管理相关函数:“将新房卡录入系统”
a.密钥库导入导出
#ifndef _CUT_AUTHENTICATE_
int32_t hks_access_import_key(const struct hks_blob *key_alias, const struct hks_key_param *key_param,
    const struct hks_blob *key)//导入密钥进密钥库
{
    
    struct sec_mod_msg msg_box;

    (void)memset_s(&msg_box, sizeof(msg_box), 0, sizeof(msg_box));

    struct hks_import_key_msg *msg = &msg_box.msg_data.import_key_msg;

    msg_box.cmd_id = HKS_IMPORT_KEY;//安全请求设置为“导入密钥”
    msg->key_alias = key_alias;
    msg->key_param = key_param;
    msg->key_data = key;
    hks_enter_secure_mode(&msg_box);//进入安全模式,判断安全请求

    return msg_box.status;//返回权限
}

//与导入密钥类似
int32_t hks_access_export_key(const struct hks_blob *key_alias, struct hks_blob *key)
{
    
    struct sec_mod_msg msg_box;

    (void)memset_s(&msg_box, sizeof(msg_box), 0, sizeof(msg_box));

    struct hks_export_key_msg *msg = &msg_box.msg_data.export_key_msg;

    msg_box.cmd_id = HKS_EXPORT_KEY;//安全请求设置为“导出密钥”
    msg->key_alias = key_alias;
    msg->key_data = key;
    hks_enter_secure_mode(&msg_box);

    return msg_box.status;
}
b.申请密钥删除权限
//申请删除密钥权限
int32_t hks_access_delete_key(const struct hks_blob *key_alias)
{
    
    int32_t status = hks_service_delete_key(key_alias);

    hks_if_status_error_return(status);

    return status;
}
c.获取判断密钥是否存在的权限
int32_t hks_access_is_key_exist(const struct hks_blob *key_alias)
{
    
    //hks
    int32_t status = hks_service_is_key_exist(key_alias);

    hks_if_status_error_return(status);

    return status;
}
d.获取获得密钥参数的权限
int32_t hks_access_get_key_param(const struct hks_blob *key_alias,
    struct hks_key_param *key_param)
{
    
    int32_t status = hks_service_get_key_param(key_alias, key_param);

    hks_if_status_error_return(status);

    return status;
}
e.获取获得公钥别名列表的权限
int32_t hks_access_get_pub_key_alias_list(struct hks_blob *key_alias_list, uint32_t *list_count)
{
    
    int32_t status = hks_service_get_pub_key_alias_list(key_alias_list, list_count);

    hks_if_status_error_return(status);

    return status;
}
#endif

3.2房卡制造工艺之cipher_aes.c

本函数主要实现AES密码学相关操作,如密钥、向量的产生、明文的加密解密、密文的存储相关操作

1.采用256位密码操作:#define AES_BYTE_SIZE 256

2.补齐明文长度。

使得明文长度为256字长的整数倍

static int32_t PaddingPkcs5(char *data, size_t inSize)
{
    
    if (inSize % AES_BLOCK_SIZE == 0) {
    
        return strlen((const char *)(uintptr_t)data);
    }//如果长度正好为256的整数倍则不用补齐

    int32_t paddingLen = AES_BLOCK_SIZE - inSize % AES_BLOCK_SIZE;
    //需要补齐的位数
    int32_t needLen = paddingLen + inSize;
    //明文加上补齐位后的长度
    for (int32_t i = 0; i < paddingLen; i++) {
    
        data[inSize + i] = paddingLen;
    }//明文末尾后的每一位分别初始化,直到长度等于needLen

    return needLen;
}

从在同一个.c文件中的函数InitAesData中一行代码可确定传入的参数就是明文以及明文长度

data->textLen = PaddingPkcs5(data->text, strlen(text));

3.去掉填充位


static int32_t UnpaddingPkcs5(char *data, size_t dataLen)
{
    
    int32_t padLen = data[dataLen - 1];//最后一位记录的是填充的数据长度

    if (padLen <= 0 || padLen >= AES_BLOCK_SIZE) {
    
        return ERROR_CODE_GENERAL;
    }//检查填充的数据长度是否大于256位。

    for (int32_t i = 0; i < padLen; i++) {
    
        if (data[dataLen - 1 - i] != padLen) {
    
            return ERROR_CODE_GENERAL;
        }//检查填充位是否与paddingLen相同,即检验是否正确进行了pkcs5填充。
        data[dataLen - 1 - i] = '\0';//从后向前依次抹去填充位。
    }
    return (dataLen - padLen);
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_50294842/article/details/120068262

智能推荐

python字符串类型定义_python--字符串类型-程序员宅基地

文章浏览阅读1.2k次。*************** 字符串类型 ***************1.字符串的定义:第一种方式:str1 = 'our company is westos'第二种方式:str2 = "our company is westos"第三种方式:str3 = """our company is westos"""2.转义符号一个反斜线加一个单一字符可以表示一个特殊字符,通常是不可打印的字符\n:..._python字符串类型定义

计算机图形学和工程图学,计算机图形学与印刷工程我与工程图学及计算机图形学...-程序员宅基地

文章浏览阅读418次。一、我与浙大工程图学一同发展      我国工程图学课程量大面广,从新中国成立以来主要承袭于前苏联,经过50多年的建设、改革和发展,课程体系形成了较明显的中国特色,既不同于欧美,也不同于前苏联。可以分为如下四个发展阶段:第一阶段***1949-1962年***称为初期阶段,1957年教育部邀请苏联专家在清华大学举办了画法几何及机械制图教学研究进修班,在总结交流基础上,初步形成了中国模式的工程制图教..._印刷工程 计算机相关课程

(转)C语言家族扩展_c语言家族分支-程序员宅基地

文章浏览阅读3.1k次。(转)C语言家族扩展 翻译:5.1--5.6林峰5.7--5.20董溥5.21--5.26王聪5.27--5.34刘洋5.35--5.43贾孟树致谢:感谢陈老师指出其中的一些错误,已修订。 修订记录: 修订一些用词和标点符号。(董溥)2007年1月12号修订一些用词和错别字。(王聪)2006年12月14号修正一些错误的标签。(王聪,董溥)2006年12月13号GNU C提供了多种在ISO标准C中没有的特性。(‘-pedantic’选项会使GC_c语言家族分支

elementui css,elementUI——主题及自定义-程序员宅基地

文章浏览阅读1.3k次。说明:本文基于[email protected],源码详见element。一、主题相关代码结构:可以看出两点:a. 每个element ui组件基本都对应有单独的scss文件;b. 单独的组件scss文件,支持了组件按需引入时,样式部分也能按需引入的诉求;c.theme-chalk/src/common和theme-chalk/src/mixins目录下,主要是一些公共样式的设置,全局sass变量..._elementui css

H5 如何实现唤起 APP_如何实现拼多多h5直接跳转淘宝或者拼多多-程序员宅基地

文章浏览阅读1.5k次。写过hybrid的同学,想必都会遇到这样的需求,如果用户安装了自己的APP,就打开APP或跳转到APP内某个页面,如果没安装则引导用户到对应页面或应用商店下载。这里就涉及到了H5与Native之间的交互,为什么H5能够唤起APP并且跳转到对应的页面?就算你没写过想必也体验过,最常见的就是一些广告了,如果你点击了广告,他判断你手机装了对应APP,那他就会去打开那个APP,如果没安装,他会帮你跳转到应用商店去下载,这个还算人性化一点的,有些直接后台给你去下载,你完全无感知。_如何实现拼多多h5直接跳转淘宝或者拼多多

《计算机网络技术》教材分析,《计算机网络技术基础》教学计划-程序员宅基地

文章浏览阅读324次。《《计算机网络技术基础》教学计划》由会员分享,可在线阅读,更多相关《《计算机网络技术基础》教学计划(4页珍藏版)》请在人人文库网上搜索。1、临 湘 市 职 业 中 专教师工作计划及实施情况表姓 名 周 小 敏 任教科目 计算机网络技术基础 任教年级 高 二 班 次 14级计算机、苹果班 教研组长 李 岳 军 教务主任 冯 云 主管校长 李 晓 红 时 间 2016 年 上 学期本期教学的主要任务和..._计算机网络教材分析

随便推点

php mysql安装图解_MySQL安装教程图解-程序员宅基地

文章浏览阅读245次。下面的是MySQL安装的图解,用的可执行文件安装的,详细说明了一下!打开下载的mysql安装文件mysql-5.0.27-win32.zip,双击解压缩,运行setup.exe,出现如下界面 mysql安装图文教程1 mysql安装向导启动,按Next继续 mysql图文安装教程2 选择安装类型,有Typica下面的是MySQL安装的图解,用的可执行文件安装的,详细说明了一下!打开下载的mysql..._php-mysql安装

python支持oracle的驱动_python 支持oracle数据库-程序员宅基地

文章浏览阅读339次。大年初一mark一下新的一年将会下线个人ORACLE外文blog,精力有限,会全力在阿里云云栖社区分享,主要内容还是数据库相关,包括但不限于以下内容:ORACLE数据库性能分析PostgreSQL数据库全栈支持PPAS数据库全栈支持专注ORACLE数据库和应用迁移至阿里云PPAS、PostgreSQL等数据...文章唐修2019-02-051169浏览量PostgreSQL修炼之道:从小工到专家...._python官方镜像里面没有oracle驱动

mysql导入报错1071_导入sql文件报错:1071 Specified key was too long; max key length is 767 bytes...-程序员宅基地

文章浏览阅读644次。一、背景今天把服务器的数据库导出了一份sql文件,准备导入到本地,但是在导入的时候,报了个错:Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes这就很奇怪了,明明服务器上都可以,凭什么我这边就报错呢。二、错误分析1、错误部分的sql文件CREATE TABLE ..._mysql导入报错[err] cannot create table [商品成本]: 1071 - specified key was

小米路由r2d论坛_小米路由器R2D固件 V2.24.10 官方稳定版-程序员宅基地

文章浏览阅读3k次。小米路由器R2D固件是小米官方为其推出的路由器刷机更新固件,优化了Wifi能力,同时修复了系统中的一些小问题,提升了系统的稳定性和安全性,如果你的路由器出现了一些小问题,可以通过这个固件来更新下系统。【更新说明】1.优化了共享WiFi功能,提升了使用体验2.修复了一些小问题,提高了系统安全性及稳定性【刷机教程】1、准备一个系统格式为FAT或FAT32的U盘;重要的事情再说三遍:U盘刷机会清空硬盘上..._小米路由r2d论坛

OpenWRT使用SNMP监测网络状态_openwrt snmp-程序员宅基地

文章浏览阅读1.9w次。最近在写毕业论文,需要监测路由器的网络状态,路由器是TP-Link TL1043ND v2,操作系统版本是OpenWRT 15.05,本来打算在路由器和监测机上使用Socket通信来交互信息的,写着写着发现太麻烦了,因为路由器有许多个,就需要在监测机上要实现多线程之类的东西,后来发现OpenWRT上已经有编译好的SNMP包了,于是就直接用它了,然后通过配置snmpd.config文件来扩展,调用iw_openwrt snmp

python中concat的用法_pandas中concat()的用法-程序员宅基地

文章浏览阅读5.4k次。pandas.concat()通常用来连接DataFrame对象。默认情况下是对两个DataFrame对象进行纵向连接, 当然通过设置参数,也可以通过它实现DataFrame对象的横向连接。让我们通过几个例子来看看concat()的用法。1. 纵向连接DataFrame对象(1)两个DataFrame对象的列完全相同# 初始化两个DataFrame对象df1 = pd.DataFrame([['a..._python中concat函数

推荐文章

热门文章

相关标签