• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            無我

            讓內(nèi)心永遠燃燒著偉大的光明的精神之火!
            靈活的思考,嚴謹?shù)膶崿F(xiàn)
            豪邁的氣魄、頑強的意志和周全的思考

            eSNACC對BIT STRING的編碼和解碼

            本文剖析asn-bits.h/c,從源代碼來學習eSNACC對BIT STRING的編碼和解碼。

            比特字符串的編碼和解碼比較復雜,我們來仔細分析一下代碼吧。

             

            eSNACC用一個結(jié)構(gòu)體來表示BIT STRING,定義如下:

            typedef struct AsnBits
            {
              
            int    bitLen;//bit位總長度
              char    *bits;
            }
             AsnBits;

            這兩個參數(shù)分別是:

            bitlen代表這個比特串的bit位的總長度,注意是bit位,不是字節(jié)數(shù)!

            bits用來存放比特串;要注意這是一個bit串,不是字符串,也就是說中間可以有0.這不是一個要求以null結(jié)尾的字符串!

             

            在頭文件中其他的就是BER、DER的編碼解碼的聲明,還有一些幫助函數(shù)的聲明和宏定義。

             

            來研究一下主要實現(xiàn):

            先看最外層編碼和解碼函數(shù):

            /*
             * encodes universal TAG LENGTH and Contents of and ASN.1 BIT STRING
             
            */

            AsnLen
            BEncAsnBits PARAMS ((b, data),
                GenBuf 
            *b _AND_
                AsnBits 
            *data)
            {
                AsnLen len;

                len 
            =  BEncAsnBitsContent (b, data);
                len 
            += BEncDefLen (b, len);
                len 
            += BEncTag1 (b, UNIV, PRIM, BITSTRING_TAG_CODE);
                
            return len;
            }
              /* BEncAsnInt */


            /*
             * decodes universal TAG LENGTH and Contents of and ASN.1 BIT STRING
             
            */

            void
            BDecAsnBits PARAMS ((b, result, bytesDecoded, env),
                GenBuf 
            *b _AND_
                AsnBits    
            *result _AND_
                AsnLen 
            *bytesDecoded _AND_
                jmp_buf env)
            {
                AsnTag tag;
                AsnLen elmtLen;

                
            if (((tag =BDecTag (b, bytesDecoded, env)) !=
                    MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE)) 
            &&
                    (tag 
            != MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE)))
                
            {
                     Asn1Error (
            "BDecAsnBits: ERROR - wrong tag on BIT STRING.\n");
                     longjmp (env, 
            -40);
                }


                elmtLen 
            = BDecLen (b, bytesDecoded, env);
                BDecAsnBitsContent (b, tag, elmtLen, result, bytesDecoded, env);

            }
              /* BDecAsnBits */

             我們發(fā)現(xiàn)在BEncAsnBits中編碼時對比特串的標簽只可能是UNIV-PRIM-BITSTRING_TAG_CODE,但是解碼時卻支持兩種標簽:UNIV-PRIM-BITSTRING_TAG_CODE和UNIV-CONS-BITSTRING_TAG_CODE。

            第一個UNIV-PRIM-BITSTRING_TAG_CODE就是原生的比特串,而第二個UNIV-CONS-BITSTRING_TAG_CODE是對應多個原生或者連接型比特串構(gòu)造而成的比特串(嵌套)。這種數(shù)據(jù)是在什么時候編碼形成的就留到以后的文章來研究了。反正在當前這對文件的編碼中肯定不會產(chǎn)生。

             

            我們看一下真正編碼比特串內(nèi)容的函數(shù):

            /*
             * Encodes the BIT STRING value (including the unused bits
             * byte) to the given buffer.
             
            */

            AsnLen
            BEncAsnBitsContent PARAMS ((b, bits),
                GenBuf 
            *b _AND_
                AsnBits 
            *bits)
            {
                unsigned 
            long unusedBits;
                unsigned 
            long byteLen;
                
            int i = 0;
                
            /* Check for a dumb special case */
                
            for (i=0; i <bits->bitLen/8 + 1; i++)
                
            {
                    
            if (bits->bits[i] != 0)
                        
            break;
                }

                
            if (i == bits->bitLen/8 + 1)
                
            {
                    bits
            ->bitLen = 1;
                    unusedBits 
            = 7;
                }


                
            /* Work out number of unused bits */
                unusedBits 
            = (bits->bitLen % 8);
                
            if (unusedBits != 0)
                    unusedBits 
            = 8 - unusedBits;

                
            /* Work out number of bytes */
                
            if (bits->bitLen == 0{
                    byteLen 
            = 0;
                }

                
            else {
                  byteLen 
            = ((bits->bitLen-1/ 8+ 1;
                  
                  
            /* Ensure last byte is zero padded */
                  
            if (unusedBits) {
                      
            //此處為什么只在字節(jié)長度為1時才做這個處理呢?
                      if ((byteLen == 1&& (bits->bits[0!= 0))
                      
            {
                        bits
            ->bits[byteLen-1= (char)(bits->bits[byteLen-1& 
                        (
            0xff << unusedBits));
                      }

                  }

                }


                BufPutSegRvs (b, bits
            ->bits, byteLen);
               
                
            /* check for special DER encoding rules to return 03 01 00 not
                   03 02 07 00    RWC 
            */

                
            if ( ((bits->bits[0!= 0|| (byteLen > 1)) 
                    
            && (unusedBits != 7) )
                
            {
                   BufPutByteRvs (b, (unsigned 
            char)unusedBits);
                   
            return byteLen + 1;
                }

                
            else
                   
            return byteLen;//如果未用的位的數(shù)目為7,并且長度大于1,或者第一字節(jié)不為0,就不在填充了,這是為什么呢?這不就和解碼時相沖突了嗎?

            }
             /* BEncAsnBitsContent */

            我對這個函數(shù)還存在幾個問題,就如同在上面注釋中寫的。

            首先我們看到他判斷要編碼的串是不是就是一個空串,如果是空串,就把長度設為1,未使用字節(jié)數(shù)設為7。然后計算了一下將位長度轉(zhuǎn)為字節(jié)(8位)時會產(chǎn)生的未使用的字節(jié)數(shù)。

            接著就是實戰(zhàn)了,根據(jù)bit長度來取得要保存這些bit需要的字節(jié)數(shù):byteLen = ((bits->bitLen-1) / 8) + 1;然后如果根據(jù)前面計算的如果有未使用的字節(jié)數(shù),就要用0填充。但是這里不知道他為什么要把這步操作放到if中:只在字節(jié)長度為1時才做這個處理!?除非就是外部傳進來的bits->bits本來就是用0填充好了的,所以不需要修正。但是如果是填充好了的,那對1個字節(jié)長度的也不需要做這個操作了。

            另外就是,在填充無效位數(shù)時,為什么是這樣一個條件?因為在解碼函數(shù)(下面分析)中,都始終會減去代表這個未用位字節(jié)。

             

            我們來看看解碼函數(shù)

            /*
             * Decodes the content of a BIT STRING (including the unused bits octet)
             * Always returns a single contiguous bit string
             
            */

            void
            BDecAsnBitsContent PARAMS ((b, tagId, len, result, bytesDecoded, env),
                GenBuf 
            *b _AND_
                AsnTag tagId _AND_
                AsnLen len _AND_
                AsnBits 
            *result _AND_
                AsnLen 
            *bytesDecoded _AND_
                jmp_buf env)
            {
                
            /*
                 * tagId is encoded tag shifted into long int.
                 * if CONS bit is set then constructed bit string
                 
            */

                
            if (TAG_IS_CONS (tagId))
                    BDecConsAsnBits (b, len, result, bytesDecoded, env);
                
            else /* primitive octet string */
                
            {
                    
            if (len == INDEFINITE_LEN)
                    
            {
                         Asn1Error (
            "BDecAsnBitsContent: ERROR - indefinite length on primitive\n");
                         longjmp (env, 
            -65);
                    }

                    (
            *bytesDecoded) += len;
                    len
            --;//減去代表未用位的那個字節(jié)
                    result->bitLen = (len * 8- (unsigned int)BufGetByte (b);//得到有效位。
                    result->bits =  Asn1Alloc (len);
                    CheckAsn1Alloc (result
            ->bits, env);
                    BufCopy (result
            ->bits, b, len);
                    
            if (BufReadError (b))
                    
            {
                        Asn1Error (
            "BDecAsnBitsContent: ERROR - decoded past end of data\n");
                        longjmp (env, 
            -4);
                    }

                }

            }
              /* BDecAsnBitsContent */

            他通過標簽走了兩條分支,對應原生比特串,解碼過程如下:

            必須定義確定的長度,否則報錯。然后數(shù)據(jù)指針先加上指定長度。

            注意此時先將len--!為什么呢?這是對應這個len還包含了存放那個說明未使用位的值的1個字節(jié),所以len先減去這個。而下一句就是用BufGetByte獲取那個字節(jié),從而得到未使用的bit位的數(shù)目。所以用字節(jié)數(shù)len*8減去這個值就是全部有用的bit位的數(shù)了。而后面的邏輯就很清楚了:分配一個len個字節(jié)的空間并且把bit串拷貝進去。

              

            eSNACC對應ConsAsnBits解碼的兩個函數(shù)就不深入分析了,其原理構(gòu)造了一個結(jié)構(gòu)體,里面包含一些長度信息等,和一張指針表,表中有128個指針,用于指向比特串碎片,所以先對分散的比特串分別解析,最后分配一整塊大內(nèi)存,再把指針指向的碎片的中內(nèi)容拷貝過來。詳細代碼剖析可以參見eSNACC對OCTET STRING 的編碼和解碼

             

            文件中其他的一些幫助函數(shù)理解起來都比較簡單,但是似乎發(fā)現(xiàn)AsnBitsEquiv中存在一個bug:

            /*
             * Returns TRUE if the given BIT STRINGs are identical.
             * Otherwise returns FALSE.
             
            */

            int
            AsnBitsEquiv PARAMS ((b1, b2),
                AsnBits 
            *b1 _AND_
                AsnBits 
            *b2)
            {
                
            int octetsLessOne;
                
            int unusedBits;

                
            if ((b1->bitLen == 0&& (b2->bitLen == 0))
                    
            return TRUE;

                octetsLessOne 
            = (b1->bitLen-1)/8;//字節(jié)長度減一
                unusedBits = b1->bitLen % 8;
                
            if (unusedBits != 0)
                   unusedBits 
            = 8 - unusedBits;

                
            /* trailing bits may not be significant  */
                
            //此處應該是一個bug。。
                /*return b1->bitLen == b2->bitLen && !memcmpeq (b1->bits, b2->bits, octetsLessOne) && 
                ((b1->bits[octetsLessOne] & (0xFF << unusedBits)) == (b1->bits[octetsLessOne] & (0xFF << unusedBits)));
            */

                
            return b1->bitLen == b2->bitLen && !memcmpeq (b1->bits, b2->bits, octetsLessOne) && 
                    ((b1
            ->bits[octetsLessOne] & (0xFF << unusedBits)) == (b2->bits[octetsLessOne] & (0xFF << unusedBits)));

            }
             /* AsnBitsEquiv */

            bug就是函數(shù)最后這句話,原來那句我就是被注釋的那句,他目的是比較:1、兩個比特串長度要相等;2、有效bit位長度字節(jié)數(shù)減1的串要相同(也就是不考慮后面可能需要補齊的字節(jié));3、檢查可能需要被補齊的那個字節(jié)的對應有效位是否相等。很明顯,應該是b1和b2的,所以修正在注釋下面。

             

            分析到此,發(fā)現(xiàn)比特串的編碼解碼模塊存在bug,似乎還有上面說的設計問題,比較困惑:是不是作者在寫這個模塊時處在XXX時期?呵呵~ 

            posted on 2012-04-22 18:20 Tim 閱讀(980) 評論(3)  編輯 收藏 引用 所屬分類: eSNACC學習

            評論

            # re: eSNACC對BIT STRING的編碼和解碼 2012-04-23 14:02 嵌入式培訓

            難得的解碼文章。。不錯。我轉(zhuǎn)載哈。  回復  更多評論   

            # re: eSNACC對BIT STRING的編碼和解碼 2012-04-23 14:05 Tim

            @嵌入式培訓
            恩,歡迎轉(zhuǎn)載。請標明http://www.shnenglu.com/Tim哦。呵呵  回復  更多評論   

            # re: eSNACC對BIT STRING的編碼和解碼 [未登錄] 2012-04-27 09:41 Tina

            確實很難得的,支持支持!  回復  更多評論   

            <2007年12月>
            2526272829301
            2345678
            9101112131415
            16171819202122
            23242526272829
            303112345

            導航

            統(tǒng)計

            公告

            本博客原創(chuàng)文章,歡迎轉(zhuǎn)載和交流。不過請注明以下信息:
            作者:TimWu
            郵箱:timfly@yeah.net
            來源:www.shnenglu.com/Tim
            感謝您對我的支持!

            留言簿(9)

            隨筆分類(173)

            IT

            Life

            搜索

            積分與排名

            最新隨筆

            最新評論

            閱讀排行榜

            久久亚洲av无码精品浪潮| 久久综合九色综合网站| 亚洲v国产v天堂a无码久久| 久久精品国产99久久香蕉| 欧美成人免费观看久久| 91精品国产乱码久久久久久| 久久久久久久国产免费看| 国产精品对白刺激久久久| 久久久久女教师免费一区| 成人妇女免费播放久久久| 无码乱码观看精品久久| 日本免费久久久久久久网站| 久久人妻无码中文字幕| 久久精品成人免费观看97| 精品国产一区二区三区久久久狼 | 久久亚洲sm情趣捆绑调教| 乱亲女H秽乱长久久久| 久久久青草青青国产亚洲免观| 99久久精品费精品国产一区二区| 久久不见久久见免费影院www日本| 久久无码高潮喷水| 国内精品欧美久久精品| 久久精品水蜜桃av综合天堂 | 国产精品美女久久久久| 日韩中文久久| 青青热久久综合网伊人| 日韩精品无码久久久久久| 久久久久久国产精品无码下载| 久久天天躁狠狠躁夜夜2020一| 一本伊大人香蕉久久网手机| 久久精品国产亚洲AV香蕉| 国产精品丝袜久久久久久不卡| 91亚洲国产成人久久精品| 九九99精品久久久久久| 亚洲中文久久精品无码| 2020国产成人久久精品 | 精品国产91久久久久久久 | 久久亚洲国产成人影院网站| 26uuu久久五月天| 996久久国产精品线观看| 国产亚洲欧美精品久久久|