zoukankan      html  css  js  c++  java
  • 客户端网络pomelo学习笔记 (3) node.js 与 c 客户端 DiffieHellman 密钥交换算法的实现客户端网络

    发一下牢骚和主题无关:

        经过多次测试,现实了与客户端 Diffie-Hellman 钥密交换算法。

        Diffie-Hellman 可以不安全的网络通道上交换钥密,具体理原见 wiki: Diffie–Hellman key exchange

        

        

    Alice   Bob
    Secret Public Calculates Sends Calculates Public Secret
    a p, g   p,g\rightarrow     b
    a p, g, A ga mod p = A A\rightarrow   p, g b
    a p, g, A   \leftarrow B gb mod p = B p, g, A, B b
    a, s p, g, A, B Ba mod p = s   Ab mod p = s p, g, A, B b, s
       

        服务端 (alice):

    > var crypto = require("crypto");
    undefined
    > var alice, bob, A, a, B, b, p, s1, s2;
    undefined
    > alice = crypto.createDiffieHellman(8);
    { _binding: {} }
    > A = alice.generateKeys("hex");
    '3053'
    > p = alice.getPrime("hex");
    '8c7b'

        alice的Public Key : 0x3053 (A),素数:0x8c7b (p),crypto库的础基跟牢固都是2(g)

        客户端(bob)用polarssl库

    #include <polarssl/dhm.h>
    
    #include <polarssl/config.h>
    
    #ifdef _MSC_VER
    #include <basetsd.h>
    typedef UINT32 uint32_t;
    #else
    #include <inttypes.h>
    #endif
    
    #include <assert.h>
    
    /*
     * 32-bit integer manipulation macros (big endian)
     */
    #ifndef GET_UINT32_BE
    #define GET_UINT32_BE(n,b,i)                            \
    {                                                       \
        (n) = ( (uint32_t) (b)[(i)    ] << 24 )             \
            | ( (uint32_t) (b)[(i) + 1] << 16 )             \
            | ( (uint32_t) (b)[(i) + 2] <<  8 )             \
            | ( (uint32_t) (b)[(i) + 3]       );            \
    }
    #endif
    
    #ifndef PUT_UINT32_BE
    #define PUT_UINT32_BE(n,b,i)                            \
    {                                                       \
        (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
        (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
        (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
        (b)[(i) + 3] = (unsigned char) ( (n)       );       \
    }
    #endif
    
    int unhexify(unsigned char *obuf, const char *ibuf)
    {
        unsigned char c, c2;
        int len = strlen(ibuf) / 2;
        assert(!(strlen(ibuf) %1)); // must be even number of bytes
    
        while (*ibuf != 0)
        {
            c = *ibuf++;
            if( c >= '0' && c <= '9' )
                c -= '0';
            else if( c >= 'a' && c <= 'f' )
                c -= 'a' - 10;
            else if( c >= 'A' && c <= 'F' )
                c -= 'A' - 10;
            else
                assert( 0 );
    
            c2 = *ibuf++;
            if( c2 >= '0' && c2 <= '9' )
                c2 -= '0';
            else if( c2 >= 'a' && c2 <= 'f' )
                c2 -= 'a' - 10;
            else if( c2 >= 'A' && c2 <= 'F' )
                c2 -= 'A' - 10;
            else
                assert( 0 );
    
            *obuf++ = ( c << 4 ) | c2;
        }
    
        return len;
    }
    
    void hexify(unsigned char *obuf, const unsigned char *ibuf, int len)
    {
        unsigned char l, h;
    
        while (len != 0)
        {
            h = (*ibuf) / 16;
            l = (*ibuf) % 16;
    
            if( h < 10 )
                *obuf++ = '0' + h;
            else
                *obuf++ = 'a' + h - 10;
    
            if( l < 10 )
                *obuf++ = '0' + l;
            else
                *obuf++ = 'a' + l - 10;
    
            ++ibuf;
            len--;
        }
    }
    
    /**
     * This function just returns data from rand().
     * Although predictable and often similar on multiple
     * runs, this does not result in identical random on
     * each run. So do not use this if the results of a
     * test depend on the random data that is generated.
     *
     * rng_state shall be NULL.
     */
    static int rnd_std_rand( void *rng_state, unsigned char *output, size_t len )
    {
        size_t i;
    
        if( rng_state != NULL )
            rng_state  = NULL;
    
        for( i = 0; i < len; ++i )
            output[i] = rand();
    
        return( 0 );
    }
    
    /**
     * This function only returns zeros
     *
     * rng_state shall be NULL.
     */
    static int rnd_zero_rand( void *rng_state, unsigned char *output, size_t len )
    {
        if( rng_state != NULL )
            rng_state  = NULL;
    
        memset( output, 0, len );
    
        return( 0 );
    }
    
    typedef struct
    {
        unsigned char *buf;
        size_t length;
    } rnd_buf_info;
    
    /**
     * This function returns random based on a buffer it receives.
     *
     * rng_state shall be a pointer to a rnd_buf_info structure.
     * 
     * The number of bytes released from the buffer on each call to
     * the random function is specified by per_call. (Can be between
     * 1 and 4)
     *
     * After the buffer is empty it will return rand();
     */
    static int rnd_buffer_rand( void *rng_state, unsigned char *output, size_t len )
    {
        rnd_buf_info *info = (rnd_buf_info *) rng_state;
        size_t use_len;
    
        if( rng_state == NULL )
            return( rnd_std_rand( NULL, output, len ) );
    
        use_len = len;
        if( len > info->length )
            use_len = info->length;
    
        if( use_len )
        {
            memcpy( output, info->buf, use_len );
            info->buf += use_len;
            info->length -= use_len;
        }
    
        if( len - use_len > 0 )
            return( rnd_std_rand( NULL, output + use_len, len - use_len ) );
    
        return( 0 );
    }
    
    /**
     * Info structure for the pseudo random function
     *
     * Key should be set at the start to a test-unique value.
     * Do not forget endianness!
     * State( v0, v1 ) should be set to zero.
     */
    typedef struct
    {
        uint32_t key[16];
        uint32_t v0, v1;
    } rnd_pseudo_info;
    
    /**
     * This function returns random based on a pseudo random function.
     * This means the results should be identical on all systems.
     * Pseudo random is based on the XTEA encryption algorithm to
     * generate pseudorandom.
     *
     * rng_state shall be a pointer to a rnd_pseudo_info structure.
     */
    static int rnd_pseudo_rand( void *rng_state, unsigned char *output, size_t len )
    {
        rnd_pseudo_info *info = (rnd_pseudo_info *) rng_state;
        uint32_t i, *k, sum, delta=0x9E3779B9;
        unsigned char result[4];
    
        if( rng_state == NULL )
            return( rnd_std_rand( NULL, output, len ) );
    
        k = info->key;
    
        while( len > 0 )
        {
            size_t use_len = ( len > 4 ) ? 4 : len;
            sum = 0;
    
            for( i = 0; i < 32; i++ )
            {
                info->v0 += (((info->v1 << 4) ^ (info->v1 >> 5)) + info->v1) ^ (sum + k[sum & 3]);
                sum += delta;
                info->v1 += (((info->v0 << 4) ^ (info->v0 >> 5)) + info->v0) ^ (sum + k[(sum>>11) & 3]);
            }
    
            PUT_UINT32_BE( info->v0, result, 0 );
            memcpy( output, result, use_len );
            len -= use_len;
        }
    
        return( 0 );
    }
    
    int main() {
    
        dhm_context ctx_cli;
        unsigned char pub_cli[1000];
        unsigned char sec_cli[1000];
        size_t pub_cli_len = 0;
        size_t sec_cli_len = 1000;
        int x_size;
        rnd_pseudo_info rnd_info;
    
        memset( &ctx_cli, 0x00, sizeof( dhm_context ) );
        memset( pub_cli, 0x00, 1000 );
        memset( sec_cli, 0x00, 1000 );
        memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
    
        assert( mpi_read_string( &ctx_cli.P, 10, "35963" ) == 0 ); // Prime of alice
        assert( mpi_read_string( &ctx_cli.G, 10, "2" ) == 0 );
        assert( mpi_read_string( &ctx_cli.GY, 10, "12371" ) == 0 ); // Public Key of alice
        ctx_cli.len = mpi_size( &ctx_cli.P );
    
        x_size = mpi_size( &ctx_cli.P );
    
        pub_cli_len = x_size;
        int r = dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, &rnd_pseudo_rand, &rnd_info );
        assert( r == 0 );
        int i;
        printf("Public Key of bob:");
        for(i = 0; i < pub_cli_len; ++i)
            printf("%02X", (unsigned char)pub_cli[i]);
        printf("\n");
    
        assert( dhm_calc_secret( &ctx_cli, sec_cli, &sec_cli_len ) == 0 );
        
        printf("Shared Secret:");
        for(i = 0; i < sec_cli_len; ++i)
            printf("%02X", (unsigned char)sec_cli[i]);
        printf("\n");
    
        dhm_free( &ctx_cli );
    
        return 0;
    }

        结果:

        Public Key of bob:0D03
    Shared Secret:3213

        

        alice收到bob的Public Key

    > s1 = alice.computeSecret('0D03', "hex", "hex");
    '3213'

        

        

    文章结束给大家分享下程序员的一些笑话语录: 很多所谓的牛人也不过如此,离开了你,微软还是微软,Google还是Google,苹果还是苹果,暴雪还是暴雪,而这些牛人离开了公司,自己什么都不是。

  • 相关阅读:
    Java集合类框架的基本接口有哪些?
    JSR303校验 —— hibernate-validator实现
    JSON和对象或集合间的转换
    Servlet 单例、多线程
    session.invalidate()
    request获取各种路径
    动态加载类并实例化对象 —— newInstance
    js 事件冒泡和事件捕获
    js事件绑定
    css 选择器和优先级
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3031682.html
Copyright © 2011-2022 走看看