青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

無我

讓內心永遠燃燒著偉大的光明的精神之火!
靈活的思考,嚴謹的實現
豪邁的氣魄、頑強的意志和周全的思考

eSNACC對BIT STRING的編碼和解碼

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

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

 

eSNACC用一個結構體來表示BIT STRING,定義如下:

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

這兩個參數分別是:

bitlen代表這個比特串的bit位的總長度,注意是bit位,不是字節數!

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

 

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

 

來研究一下主要實現:

先看最外層編碼和解碼函數:

/*
 * 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 */

 我們發現在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是對應多個原生或者連接型比特串構造而成的比特串(嵌套)。這種數據是在什么時候編碼形成的就留到以后的文章來研究了。反正在當前這對文件的編碼中肯定不會產生。

 

我們看一下真正編碼比特串內容的函數:

/*
 * 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) {
          
//此處為什么只在字節長度為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;//如果未用的位的數目為7,并且長度大于1,或者第一字節不為0,就不在填充了,這是為什么呢?這不就和解碼時相沖突了嗎?

}
 /* BEncAsnBitsContent */

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

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

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

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

 

我們來看看解碼函數

/*
 * 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
--;//減去代表未用位的那個字節
        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 */

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

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

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

  

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

 

文件中其他的一些幫助函數理解起來都比較簡單,但是似乎發現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;//字節長度減一
    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就是函數最后這句話,原來那句我就是被注釋的那句,他目的是比較:1、兩個比特串長度要相等;2、有效bit位長度字節數減1的串要相同(也就是不考慮后面可能需要補齊的字節);3、檢查可能需要被補齊的那個字節的對應有效位是否相等。很明顯,應該是b1和b2的,所以修正在注釋下面。

 

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

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

評論

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

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

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

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

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

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

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

導航

統計

公告

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

留言簿(9)

隨筆分類(173)

IT

Life

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美国产日韩a欧美在线观看| 免费毛片一区二区三区久久久| 亚洲一区三区视频在线观看| 在线日韩av| 亚洲精品欧洲精品| 亚洲精品一区二区三区99| 亚洲一二三区精品| 国产精品乱码一区二三区小蝌蚪| 欧美主播一区二区三区| 欧美日韩亚洲综合一区| 一本大道久久a久久精品综合| 国产视频一区在线| 亚洲素人一区二区| 久久不射2019中文字幕| 欧美日韩国产高清视频| 久久av一区二区三区漫画| 宅男精品视频| 最新国产の精品合集bt伙计| 午夜激情一区| 亚洲欧美在线aaa| 国产一区二区精品久久| 国产精品视频xxxx| 一区二区三区精品久久久| 久久久精品一区二区三区| 在线电影国产精品| 欧美日韩在线观看一区二区三区 | 国产九九精品视频| 欧美久久99| 国产在线精品自拍| 一区二区在线观看视频| 欧美三级精品| 亚洲人成网在线播放| 欧美视频在线观看 亚洲欧| 久久国产婷婷国产香蕉| 国内精品久久久久久久影视麻豆 | 欧美国产成人在线| 久久久久久久久蜜桃| 久久精彩视频| 亚洲精品在线观看免费| 亚洲人成人99网站| 一区二区日韩| 午夜精品久久久久久久久| 亚洲天堂激情| 精品99一区二区三区| 最新国产乱人伦偷精品免费网站 | 亚洲精选在线| 精品成人一区二区| 亚洲国产日韩在线一区模特| 亚洲欧美日韩精品综合在线观看| 欧美h视频在线| 亚洲精品一级| 欧美高清在线| 999在线观看精品免费不卡网站| 欧美劲爆第一页| 亚洲高清资源| 性做久久久久久久久| 久久精品91久久久久久再现| 最新日韩欧美| 久久一日本道色综合久久| 欧美日韩p片| 日韩视频在线你懂得| 久久麻豆一区二区| 亚洲欧洲另类国产综合| 亚洲欧洲精品一区二区三区不卡| 欧美日韩在线精品| 激情五月综合色婷婷一区二区| 亚洲无线视频| 亚洲黄色在线视频| 欧美不卡在线视频| 国内精品久久久久影院薰衣草| 夜夜嗨网站十八久久| 亚洲国产另类精品专区| 美女脱光内衣内裤视频久久网站| 黄色成人免费观看| 麻豆久久婷婷| 久久久夜夜夜| 亚洲第一页在线| 欧美成人午夜激情视频| 免费在线亚洲| 亚洲日本视频| 99成人免费视频| 国产精品久久久久影院色老大 | 亚洲深爱激情| 国产精品网站在线观看| 欧美一区二区三区在线| 午夜精品久久久久久99热软件 | 亚洲美女毛片| 99亚洲精品| 国产精品日韩欧美一区二区三区 | 欧美一区二区三区久久精品茉莉花| 亚洲人成在线观看一区二区| 欧美日韩精品久久| 亚洲自拍电影| 久久成人综合网| 亚洲精品国产精品久久清纯直播| 欧美激情第一页xxx| 欧美精品久久久久久久免费观看 | 欧美在线视频一区二区三区| 国产视频精品va久久久久久| 久久精品国产69国产精品亚洲| 午夜在线不卡| 一区二区三区在线视频免费观看| 久久亚洲综合网| 久久久亚洲影院你懂的| 一区二区高清在线| 亚洲欧美日韩天堂一区二区| …久久精品99久久香蕉国产| 亚洲黄色片网站| 国产精品久久久久影院色老大| 久久亚洲综合| 国产精品久久久久久久午夜片| 美日韩精品免费观看视频| 欧美激情久久久| 久久精品亚洲乱码伦伦中文| 欧美极品在线观看| 六月婷婷一区| 国产精品毛片在线看| 亚洲国产视频一区二区| 国产欧美一区二区白浆黑人| 亚洲日本国产| 在线看无码的免费网站| 国产精品99久久久久久久久久久久 | 欧美成人免费播放| 国产精品一区二区黑丝| 亚洲国产专区| 极品少妇一区二区三区精品视频| 99ri日韩精品视频| 91久久久国产精品| 久久精品成人| 久久国产色av| 欧美亚洲三区| 欧美亚洲自偷自偷| 欧美三级免费| 亚洲人线精品午夜| 亚洲大片一区二区三区| 午夜视频在线观看一区二区三区| 99亚洲一区二区| 欧美成人黄色小视频| 免费成人毛片| 韩日欧美一区二区| 午夜久久福利| 欧美专区在线观看一区| 国产精品久久久久久亚洲调教 | 日韩视频一区二区三区在线播放免费观看 | 亚洲承认在线| 久久不射网站| 久久爱www| 国产精品视频999| 亚洲无毛电影| 亚洲欧美偷拍卡通变态| 欧美视频在线观看免费网址| 亚洲欧洲另类| 亚洲香蕉成视频在线观看| 欧美日韩高清在线一区| 亚洲欧洲精品一区二区三区不卡 | 欧美精品国产一区二区| 欧美成人一品| 亚洲区中文字幕| 免费成人av在线看| 亚洲高清精品中出| 一区二区三区久久精品| 国产精品久久久久7777婷婷| 亚洲一二三四区| 久久精品国产亚洲5555| 精品动漫一区| 欧美二区在线| 一级成人国产| 久久久久久网| 亚洲精品欧洲| 国产精品久久久999| 久久久精品国产99久久精品芒果| 日韩天堂av| 国产精品任我爽爆在线播放 | 欧美日本一区二区高清播放视频| 亚洲欧洲日韩综合二区| 亚洲午夜一区二区三区| 久久久噜噜噜久久| 欧美福利视频一区| 亚洲一区二区久久| 狠狠爱综合网| 欧美日韩在线一区| 久久精品最新地址| 日韩小视频在线观看| 久久久精品网| 日韩一区二区高清| 国一区二区在线观看| 欧美日韩一区二区免费在线观看 | 欧美激情在线观看| 在线一区亚洲| 极品尤物久久久av免费看| 欧美日韩福利在线观看| 久久久91精品国产一区二区三区| 亚洲人成网站999久久久综合| 欧美一区二区三区另类| 亚洲免费观看高清在线观看| 国产一区香蕉久久| 欧美日韩在线播放一区| 久久男人av资源网站| 亚洲视频欧美视频| 亚洲欧洲一区二区在线观看|