zoukankan      html  css  js  c++  java
  • ntp源码解读(一)

    /*
     * session_key - generate session key
     *
     * This routine generates a session key from the source address,
     * destination address, key ID and private value. The value of the
     * session key is the MD5 hash of these values, while the next key ID is
     * the first four octets of the hash.
     *
     * Returns the next key ID or 0 if there is no destination address.
     */
    keyid_t
    session_key(
        sockaddr_u *srcadr,     /* source address */ 
        sockaddr_u *dstadr,     /* destination address */
        keyid_t    keyno,        /* key ID */
        keyid_t    private,    /* private value */
        u_long    lifetime     /* key lifetime */
        )
    {
        EVP_MD_CTX ctx;        /* message digest context */
        u_char dgst[EVP_MAX_MD_SIZE]; /* message digest */
        keyid_t    keyid;        /* key identifer */
        u_int32    header[10];    /* data in network byte order */
        u_int    hdlen, len;
    
        if (!dstadr)
            return 0;
        
        /*
         * Generate the session key and key ID. If the lifetime is
         * greater than zero, install the key and call it trusted.
         */
        hdlen = 0;
        switch(AF(srcadr)) {
        case AF_INET:
            header[0] = NSRCADR(srcadr);
            header[1] = NSRCADR(dstadr);
            header[2] = htonl(keyno);
            header[3] = htonl(private);
            hdlen = 4 * sizeof(u_int32);
            break;
    
        case AF_INET6:
            memcpy(&header[0], PSOCK_ADDR6(srcadr),
                sizeof(struct in6_addr));
            memcpy(&header[4], PSOCK_ADDR6(dstadr),
                sizeof(struct in6_addr));
            header[8] = htonl(keyno);
            header[9] = htonl(private);
            hdlen = 10 * sizeof(u_int32);
            break;
        }
        EVP_DigestInit(&ctx, EVP_get_digestbynid(crypto_nid));
        EVP_DigestUpdate(&ctx, (u_char *)header, hdlen);
        EVP_DigestFinal(&ctx, dgst, &len);
        memcpy(&keyid, dgst, 4);
        keyid = ntohl(keyid);
        if (lifetime != 0) {
            MD5auth_setkey(keyno, crypto_nid, dgst, len);
            authtrust(keyno, lifetime);
        }
        DPRINTF(2, ("session_key: %s > %s %08x %08x hash %08x life %lu
    ",
                stoa(srcadr), stoa(dstadr), keyno,
                private, keyid, lifetime));
    #ifdef DEBUG
            if (debug)
                printf("session_key:MD5 DIGEST  ====    %08x
    ",dgst);
    #endif
    
    
        return (keyid);
    }

    以上例程是根据the source address, * destination address, key ID and private value这四者做哈希,下一个密钥ID就是这个哈希值的前四个字节。

    同时以上代码展示了,MD5的算法流程,先定义EVP_MD_CTX  ctx,然后定义哈希值的存放地址char * dgst。

    
    
        EVP_DigestInit(&ctx, EVP_get_digestbynid(crypto_nid));
        EVP_DigestUpdate(&ctx, (u_char *)header, hdlen);
        EVP_DigestFinal(&ctx, dgst, &len);
    
    
    

    经过以上步骤,再将结果写入dgst中。

     如果密钥的生存时间不为0,那么就调用MD5auth_setkey来验证密钥是否是可信任的。

    /*
     * authistrusted - determine whether a key is trusted
     */
    int
    authistrusted(
        keyid_t keyno
        )
    {
        struct savekey *sk;
    
        if (keyno == cache_keyid)
            return ((cache_flags & KEY_TRUSTED) != 0);
    
        authkeyuncached++;
        sk = key_hash[KEYHASH(keyno)];
        while (sk != 0) {
            if (keyno == sk->keyid)
                break;
            sk = sk->next;
        }
        if (sk == 0) {
            authkeynotfound++;
    #ifdef DEBUG
                                    if (debug)
                                        printf("authistrusted authkeynotfound++
    ");
    #endif
    
            return (0);
    
        } else if (!(sk->flags & KEY_TRUSTED)) {
    #ifdef DEBUG
                                            if (debug)
                                                printf("authistrusted authkeynotfound++
    ");
    #endif
    
            authkeynotfound++;
            return (0);
        }
        return (1);
    }

    如果密钥ID已经被cache,那么密钥就是可信的。否则就根据key_no做哈希找到sk,查看sk的KEY_TRUSTED有没有置位,如果置位说明密钥可信。整个authistrusted返回1。
    整个函数的传入参数是一个32位的整形,KEYHASH这个宏取出其中的前6位,然后在key_hash这个数组中找到对应的savekey。

  • 相关阅读:
    关键路径的计算
    JSF简单介绍
    介绍:一款Mathematica的替代开源软件Mathetics
    素材链接
    JSP动作--JSP有三种凝视方式
    【InversionCount 逆序对数 + MergeSort】
    全响应跨设备的Zoomla!逐浪CMS2 x2.0正式公布
    DirectSound的应用
    “海归”首选北上广 薪资期望不太高-有感
    Servlet登陆功能的实现
  • 原文地址:https://www.cnblogs.com/flintlovesam/p/5217276.html
Copyright © 2011-2022 走看看