zoukankan      html  css  js  c++  java
  • 数据处理思想和程序架构: 使用Mbedtls包中的SSL,和服务器进行网络加密通信

    <p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/单片机知识点总结/directory.html" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>

    单向认证忽略认证方式

    1.首先保证自己的程序已经实现了普通TCP连接通信

    确保自己的单片机的程序存储空间在60KB以上!

    确保自己的单片机有至少64KB及其以上的RAM空间!

    如果使用的STM32那么推荐的型号为 STM32F103RFT6/RGT6/VFT6/VGT6/ZFT6/ZGT6

    为了保证此篇文章能够让所有人都能应用,我就假设我的程序里面已经实现了TCP连接

    然后规定:

    /*假设接收网络数据函数*/
    int net_recv(char *data);
    /*假设TCP发送数据函数*/
    int net_send(char *data,int len);

    2.按照上一节 把MBEDTLS包添加到工程

    3.config.h打开以下宏

    #define MBEDTLS_HAVE_ASM

    #define MBEDTLS_NO_UDBL_DIVISION

    #define MBEDTLS_HAVE_TIME

    #define MBEDTLS_ENTROPY_HARDWARE_ALT

    #define MBEDTLS_AES_ROM_TABLES

    #define MBEDTLS_CIPHER_MODE_CBC

    #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED

    #define MBEDTLS_NO_PLATFORM_ENTROPY

    #define MBEDTLS_PKCS1_V15

    #define MBEDTLS_SSL_PROTO_TLS1_2

    #define MBEDTLS_AES_C

    #define MBEDTLS_ASN1_PARSE_C

    #define MBEDTLS_ASN1_WRITE_C

    #define MBEDTLS_BIGNUM_C

    #define MBEDTLS_CIPHER_C

    #define MBEDTLS_CTR_DRBG_C

    #define MBEDTLS_ENTROPY_C

    #define MBEDTLS_GCM_C

    #define MBEDTLS_MD_C

    #define MBEDTLS_MD5_C

    #define MBEDTLS_OID_C

    #define MBEDTLS_PK_C

    #define MBEDTLS_PK_PARSE_C

    #define MBEDTLS_PLATFORM_C

    #define MBEDTLS_RSA_C

    #define MBEDTLS_SHA1_C

    #define MBEDTLS_SHA256_C

    #define MBEDTLS_SHA512_C

    #define MBEDTLS_SSL_CLI_C

    #define MBEDTLS_SSL_TLS_C

    #define MBEDTLS_X509_USE_C

    #define MBEDTLS_X509_CRT_PARSE_C

    //下面这个是自己设置的加密套件

    #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256

    4.编译一下

    5.方式1:修改一下源码即可

    方式2:如果不愿意修改源码可以 选择C99模式

    6.再编译一下

    7.增加自己的随机数函数 和 时间戳返回函数

    /*随机数函数*/
    int mbedtls_hardware_poll( void *data,
                        unsigned char *output, size_t len, size_t *olen )
    {
        unsigned long randomValue = ((rand()*20) + 1000);//生成随机数
        ((void) data);
        *olen = 0;
        
        if( len < sizeof(unsigned long) ) return( 0 );    
    
        memcpy( output, &randomValue, sizeof(unsigned long) );
        *olen = sizeof(unsigned long);
      return 0;
    }
    
    /**
    * @brief  时间函数(SSL底层会调用时间验证证书是否过期)
    **/
    //struct tm *lcTime;
    //time_t startTime;
    //    lcTime = localtime (&startTime);
    _ARMABI time_t time(time_t *t)
    {
    //    time_t it;
        if (t) {
            return *t;
        }
        else
        {
    //        startTime = 0;
    //        lcTime = localtime (&startTime);
    //        it = mktime(lcTime);
    //        return it ;
            return 0;
        }
    }

    8.增加SSL底层获取数据函数

    咱们在后面设置好SSL接收回调函数以后, SSL底层会调用 custom_ssl_recv 函数

    SSL底层要多少个数据,咱们才返回多少个数据,这是SSL底层规定的,所以为了配合SSL底层,程序写的比较多.

    SSL底层调用的时候最后一个参数 size_t len是指定要多少个数据.

    /**
    * @brief  自定义接收函数(把自己的接收函数放到此函数中)
    * @param  None
    * @param  None
    * @param  None
    * @retval None
    * @example 
    **/
    int net_recv_data_len=0; 
    int net_recv_data_len_count=0;
    char net_recv_buff[2000];
    static int custom_ssl_recv( void *ctx, unsigned char *buf, size_t len )
    {
        int rbCanReadLen;
        
        if(net_recv_data_len ==0)
        {
            net_recv_data_len=net_recv(net_recv_buff);//调用自己的函数接收数据
            if(net_recv_data_len>0)//有数据
            {
                if(len >= net_recv_data_len)//希望读取的数据个数大于实际的数据个数
                {
                    len = net_recv_data_len;
                    memcpy(buf, net_recv_buff, len);
                    
                    net_recv_data_len = 0;
                    net_recv_data_len_count=0;
                    return len;
                }
                else//实际的数据个数比希望读取的多
                {
                    memcpy(buf, net_recv_buff, len);
                    net_recv_data_len_count = len;
                    return len;
                }
            }
            else
            {
                return MBEDTLS_ERR_NET_RECV_FAILED;
            }
        }
        else
        {
            if(len >= net_recv_data_len - net_recv_data_len_count)//希望读取的数据个数大于实际的数据个数
            {
                len = net_recv_data_len - net_recv_data_len_count;
                memcpy(buf, net_recv_buff+net_recv_data_len_count, len);
                net_recv_data_len = 0;
                net_recv_data_len_count=0;
                return len;
            }
            else//实际的数据个数比希望读取的多
            {
                memcpy(buf, net_recv_buff + net_recv_data_len_count, len);
                net_recv_data_len_count = net_recv_data_len_count + len;
                return len;
            }
        }
    }

    9.增加发送函数以供SSL底层调用


    /*增加发送函数*/
    static int custom_ssl_send( void *ctx, unsigned char *buf, size_t len )
    {
        ctx = ctx;
        net_send(buf,len);//调用自己的TCP发送函数
        return (int)len;
    }

    10,定义需要的变量,并初始化SSL

    int ret;//
    const char *pers = "ssl_client1";
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    
    
    void ssl_int(void)
    {
        mbedtls_ssl_close_notify( &ssl );
        mbedtls_ssl_free( &ssl );
        mbedtls_ssl_config_free( &conf );
        mbedtls_ctr_drbg_free( &ctr_drbg );
        mbedtls_entropy_free( &entropy );
        
        //    mbedtls_debug_set_threshold( 1 );//
        mbedtls_ssl_init( &ssl );
        mbedtls_ssl_config_init( &conf );
        mbedtls_ctr_drbg_init( &ctr_drbg );
        mbedtls_entropy_init( &entropy );
    
        printf( "
      . Seeding the random number generator..." );
        //DRBG---->Deterministic Random Bit Generators 伪随机数产生器
        if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                                                             (const unsigned char *) pers,
                                                             strlen( pers ) ) ) != 0 )
        {
                printf( " failed
      ! mbedtls_ctr_drbg_seed returned %d
    ", ret );
        }
        
        
        //MBEDTLS_SSL_IS_CLIENT 表示配置为客户端
        //MBEDTLS_SSL_TRANSPORT_STREAM 表示传输方式为TLS
        //设置版本, MBEDTLS_SSL_PRESET_DEFAULT 表示 TLS1.0
        if( ( ret = mbedtls_ssl_config_defaults( &conf,
                                        MBEDTLS_SSL_IS_CLIENT,
                                        MBEDTLS_SSL_TRANSPORT_STREAM,
                                        MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
        {
                printf( " failed
      ! mbedtls_ssl_config_defaults returned %d
    ", ret );
        }
     
     
        /*设置数字证书检查模式 
        *  MBEDTLS_SSL_VERIFY_NONE:      peer certificate is not checked
        *                        (default on server)
        *                        (insecure on client)
        *
        *  MBEDTLS_SSL_VERIFY_OPTIONAL:  peer certificate is checked, however the
        *                        handshake continues even if verification failed;
        *                        mbedtls_ssl_get_verify_result() can be called after the
        *                        handshake is complete.
        *
        *  MBEDTLS_SSL_VERIFY_REQUIRED:  peer *must* present a valid certificate,
        *                        handshake is aborted if verification failed.
        *                        (default on client)
        */
        mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE );
        // 配置随机数生成器的回调函数
        mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
        // 配置调试回调函数
        //    mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
        
        // 根据conf设置ssl结构
        if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
        {
                mbedtls_printf( " failed
      ! mbedtls_ssl_setup returned 0x%x
    ", -ret );
        }
    
        // 设置host name 用到动态内存分配
        if( ( ret = mbedtls_ssl_set_hostname( &ssl, "替换自己证书的CN字段填写的值" ) ) != 0 )
        {
                mbedtls_printf( " failed
      ! mbedtls_ssl_set_hostname returned %d
    ", ret );
        }
        // 设置发送和接收接口
        mbedtls_ssl_set_bio( &ssl, NULL, custom_ssl_send, custom_ssl_recv, NULL );
    }

    11.关于 替换自己证书的CN字段

    看上一节

    12,连接上TCP以后,等待SSL握手成功

    13,发送和接收数据

    注意:

    1.如果显示这个..单片机不行,换个内存大点的

    2.我堆设置的是  a000

    3.如果不能连接,可以打开DEBUG

    #define MBEDTLS_DEBUG_C

    4.配置DEBUG

    /*设置 debug 输出函数*/
    static void my_debug( void *ctx, int level,
                          const char *file, int line, const char *str )
    {
        printf("%s:%04d: %s
    ", file, line, str );
    }

  • 相关阅读:
    React项目搭建与部署
    桌面应用之electron开发与转换
    React Native之支付集成(微信 支付宝)(ios android)
    WEB通知和React Native之即时通讯(iOS Android)
    React Native之配置URL Scheme(iOS Android)
    Mybatis操作oracle数据库的一些坑
    java -jar和hadoop jar的区别
    springBoot启动的时候动态选择装载某些bean
    Java常用正则表达式
    java获取当前运行的方法名称
  • 原文地址:https://www.cnblogs.com/yangfengwu/p/13845772.html
Copyright © 2011-2022 走看看