亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

ASN1編解碼實現方法

2019-11-10 17:15:51
字體:
來源:轉載
供稿:網友

目 錄版本記錄 1目 錄 1第1章 概述 31.1 背景 31.2 ASN.1概念 31.3 TAG 4第2章 開發工具 42.1 開發庫 42.2 輔助工具 5第3章 javaAsn1Compiler 63.1 定義ASN.1描述文件 63.2 生成java代碼 63.2.1 代碼生成 63.2.2 代碼案例 63.2.3 編解碼 73.3 總結 8第4章 bouncycastle 84.1 編碼 84.1.1 確定編碼的文件格式 84.1.2 構造ASN1映射類 94.2 解碼 114.2.1 定義實體結構 114.2.2 定義實體解析類 114.2.3 外部調用接口 12第1章 概述1.1 背景系統與充值平臺的接口是文件的方式,充值平臺將文件內容以ASN.1方式進行編碼,系統需要根據ASN.1協議進行解碼。關于ASN.1開發的資料,網上資料非常少,特別是涉及到具體的語言,如java,資料、案例及第三方庫更是少之又少。從無到有是很困難的,為了防止后期其他系統還需要做類似接口,將其記錄為文章以便后查,文章會以充值接口作為案例進行介紹。1.2 ASN.1概念在電信和計算機網絡領域,ASN.1(Abstract Syntax Notation one) 是一套標準,是描述數據的表示、編碼、傳輸、解碼的靈活的記法。它提供了一套正式、無歧義和精確的規則以描述獨立于特定計算機硬件的對象結構。ASN.1 包括幾個標準化編碼規則,如基本編碼規則(BER) -X.209 、規范編碼規則(CER)、識別名編碼規則(DER)、壓縮編碼規則(PER)和 xml編碼規則(XER)。這些編碼規則描述了如何對 ASN.1 中定義的數值進行編碼,以便用于傳輸,而不管計算機、編程語言或它在應用程序中如何表示等因素。ASN.1 的編碼方法比許多與之相競爭的標記系統更先進,它支持可擴展信息快速可靠的傳輸 — 在無線寬帶中,這是一種優勢。1984年,ASN.1 就已經成為了一種國際標準,它的編碼規則已經成熟并在可靠性和兼容性方面擁有更豐富的歷程?! 『啙嵉亩M制編碼規則(BER、CER、DER、PER,但不包括 XER)可當作更現代 XML 的替代。然而,ASN.1 支持對數據的語義進行描述,所以它是比 XML 更為高級的語言?! SN.1 的描述可以容易地被映射成 C 或 C++ 或 Java 的數據結構,并可以被應用程序代碼使用,并得到運行時程序庫的支持,進而能夠對編碼和解碼 XML 或 TLV 格式的,或一種非常緊湊的壓縮編碼格式的描述。同時,ASN.1也是一種用于描述結構化實體的結構和內容的語言。如:使用ASN.1語法可以這樣定義一個類:Report ::= SEQUENCE {author OCTET STRING,  title OCTET STRING,   body OCTET STRING,  biblio INTEGER  } 詳見《ASN.1編碼規則詳解》:http://wenku.baidu.com/view/33ba22d276eeaeaad1f3304c.html 注:在進行ASN1開發前,需要先閱讀上述文章,了解其中的一些基本概念。1.3 TAG由于TAG在ASN1中非常之重要,而且在對文件進行解析時就是因為TAG的問題導致浪費了很多時間,因此這里對其單獨介紹,不過只是提出概念,詳細描述還需參見相關規范。TAG是對ASN1協議中每個數據域的標識,通過2.2的截圖可以看到,每個結點名稱后面都有一個數字,這個就TAG值。TAG有可分為四大類:UNIVERSAL、Context、PRivate、application。詳見:http://wenku.baidu.com/view/33ba22d276eeaeaad1f3304c.html第2章 開發工具通常情況下,如果使用該協議進行交互,雙方應該規定出一個以ASN.1語法描述的協議文件,類似webservice開發中的wsdl,然后各自系統使用相關工具進行編解碼。2.1 開發庫目前網上能查到的第三方免費工具,主要有JavaAsn1Comiler和bouncycastle子庫:l JavaAsn1Comiler(JAC.jar):n 該工具可根據ASN.1協議描述文件,生成對應的java類,同時提供的API接口非常友好,命名概念同理論基本一致,使用非常方便,但是前提是必須要有完整的ASN.1描述文件,而且非常重要的一點使用限制是,該庫目前支持TAG值在0-127之間,即:如果協議中的數據使用了超過127的TAG值,則該庫無法支持,不可使用(否則會出現編碼錯誤,無法解析)。n 該庫提供了相當豐富的使用案例,可參考其工程下的test目錄。l bouncycastle(bcprov-jdk16-1.46.jar)n 該工具沒有提供自動生成java代碼的能力,如果要進行編解碼,則需要手動對協議中的類進行定義,并且自己調用相應的API實現編解碼。使用起來較JAC復雜,但是該庫對TAG值沒有限制,適合用在TAG值大于127的場景。n 在使用該類進行解析時,由于沒有提供方便的API進行自動解析,因此需要手工編寫解析代碼,比較郁悶的是其幫助文檔也沒有比較詳細的案例,最后的解碼操作還是通過閱讀其ASN1Dump類的實現方才完成。2.2 輔助工具由于經ASN.1編碼后的文件是二進制格式,無法直接閱讀,因此在開發過程中,為了能夠比較直觀的閱讀到其編碼后的記錄,需要借助第三方工具來查看編碼后的文件內容。網上有幾個查看工具,但是最方便、最直觀的工具則是ASN1VE 2.1(未注冊版有功能限制,只能查看編碼后的文件),通過該軟件可以很輕松的查看到文件內容,截圖如下:l 二進制視圖:l XML視圖第3章 JavaAsn1Compiler3.1 定義ASN.1描述文件通過通信雙方約定的數據格式,使用ASN.1語法對其進行定義(參見1.2百度文庫),形成.asn文件,如vc.asn。3.2 生成java代碼3.2.1 代碼生成將編寫好的.asn文件放到JAC.jar目錄,執行:java -jar JAC.jar -d c:/jac_test -p vc vc.asn參數描述:-d:生成java代碼文件的保存目錄;-p:生成java代碼的package;3.2.2 代碼案例以下代碼可從JavaAsn1Compiler工程的test目錄下獲取,ASN1文件內容:MiddleSeq ::= SEQUENCE{status [22] INTEGER,location [APPLICATION 11] INTEGER}生成的java代碼如下:import com.turkcelltech.jac.*;import com.chaosinmotion.asn1.Tag;public class MiddleSeq extends Sequence{public ASN1Integer status = new ASN1Integer("status");public ASN1Integer location = new ASN1Integer("location");publicMiddleSeq(){super();setUpElements();}publicMiddleSeq(String name){super(name);setUpElements();}protected voidsetUpElements(){super.addElement(status);status.setTagClass(Tag.CONTEXT);status.setTagNumber(22);super.addElement(location);location.setTagClass(Tag.APPLICATION);location.setTagNumber(11);/* end of element setup */}}3.2.3 編解碼// 編碼ByteArrayOutputStream outStream = new ByteArrayOutputStream();BerOutputStream out = new BerOutputStream(outStream);MiddleSeq ms = new MiddleSeq();ms.status.setValue(2);ms.location.setValue(314);ms.encode(out);// 解碼ByteArrayInputStream inputStream;BerInputStream in;inputStream = new ByteArrayInputStream(outStream.toByteArray());in = new BerInputStream(inputStream);MiddleSeq decode_ms = new MiddleSeq("decode_ms");decode_ms.decode(in);System.out.println("ms.status=" + decode_ms.status.getValue());可見編解碼非常簡單,如果是嵌套結構,只要對最外層對象執行encode/decode操作即可。3.3 總結使用該庫在有ASN1協議描述文件時,開發ASN1編解碼非常容易,缺點就是不支持超過127的TAG值。第4章 bouncycastlebouncycastle(簡稱bc)包含了一系列的java編解碼工具,ASN1只是其中的一類。在沒有ASN1協議描述文件的情況下,結合ASN1VE工具,可以進行相關的編解碼開發,云南服務質量管理系統與VC充值平臺正是使用這種方式開發的。4.1 編碼在云南服務質量管理系統中,實際上并沒用用到ASN1編碼的知識,但是在從零開始的背景下,為了更好的學習和理解ASN1的編碼格式,這里便開發了一個編碼模型。4.1.1 確定編碼的文件格式由于沒有ASN1文件,只有編碼后的文件,因此需要通過ASN1VE來查看編碼后是什么格式,如圖所示:通過上圖可以看出整個文件的組織結構、每個數據域對應的TAG值以及TAG的類型(Application)。但是ASN1的編碼有多種方式,如:BER/DER/PER等,bc庫提供的API就包含了BER和DER兩種類型,為了確定具體的編碼格式,利用bc庫自帶的ASN1Dump工具,可以將該文件通過文本的方式輸出出來(略),最后獲取的方式為DER,下面就利用bc庫提供的API來構造上述的結構。4.1.2 構造ASN1映射類有了上面分析出的結構再結合對方提供的Word文檔,即可以定義出大概結構,這里只給出其中Header的定義,其他可參考具體代碼:import java.io.IOException;import org.bouncycastle.asn1.ASN1EncodableVector;import org.bouncycastle.asn1.DERApplicationSpecific;import org.bouncycastle.asn1.DEREncodable;import org.bouncycastle.asn1.DERIA5String;import org.bouncycastle.asn1.DERInteger;public class RecordHeader extends DERApplicationSpecific{public RecordHeader(boolean explicit, int tag, DEREncodable object) throws IOException {super(explicit, tag, object);// TODO Auto-generated constructor stub}public RecordHeader(int tagNo, ASN1EncodableVector vec) {super(tagNo, vec);}public RecordHeader(int tag, byte[] octets) {super(tag, octets);// TODO Auto-generated constructor stub}public RecordHeader(int tag, DEREncodable object) throws IOException {super(tag, object);// TODO Auto-generated constructor stub}public static RecordHeader createHeader(int recodeType, String senderCode, String accepterCode,String fileSerialNo, String fileCreateTime, int fileVersionNo){DERInteger d_recodeType = new DERInteger(recodeType);DERIA5String d_senderCode = new DERIA5String(senderCode);DERIA5String d_accepterCode = new DERIA5String(accepterCode);DERIA5String d_fileSerialNo = new DERIA5String(fileSerialNo);DERIA5String d_fileCreateTime = new DERIA5String(fileCreateTime);DERInteger d_fileVersionNo = new DERInteger(fileVersionNo);ASN1EncodableVector vec = new ASN1EncodableVector();try{vec.add(new DERApplicationSpecific(false, 50, d_recodeType));vec.add(new DERApplicationSpecific(false, 51, d_senderCode));vec.add(new DERApplicationSpecific(false, 52, d_accepterCode));vec.add(new DERApplicationSpecific(false, 53, d_fileSerialNo));vec.add(new DERApplicationSpecific(false, 54, d_fileCreateTime));vec.add(new DERApplicationSpecific(false, 55, d_fileVersionNo));}catch(IOException e){e.printStackTrace();}RecordHeader header = new RecordHeader(33, vec);return header;}}代碼中幾個重要概念l 類定義:理論上一個類的定義應該是一個SEQUENCE,但是通過ASN1Dump出來的數據顯示其并不是一個Sequence,而只是一個普通的結點,因此這里不能繼承DERSequence,否則編碼出的文件將會在Application的上或者下多出一個Sequence結點。l DERApplicationSpecific:這個是表示構造Application類型Tag的類,如果協議中沒有規定Tag類型,默認的可以使用DERTaggedObject來定義節點。(說明:而在JAC庫中,如果要定義TAG的類型,實際上只要調用一個set方法即可,這里定義了一個單獨的類,在沒有說明的情況下是很難找到的)l 結構的模擬:為了實現ASN1VE中查看出的結構(一個結點下面的多個App子結點),可以通過bc庫提供的ASN1EncodableVector來進行模擬(見代碼)。4.2 解碼由于bc庫沒有提供直接解析成對象的API(也可能是我沒找到),因此需要自行定義業務實體以及解碼代碼。4.2.1 定義實體結構根據文檔(word)提供的協議的業務描述結合ASN1VE查看出的結構,定義出業務對象,其實就是普通的javabean,如:Root、Header、Tail和Body等,Root結構如下:public class Root {private Header header;private List<Body> bodys;private Tail tail;}4.2.2 定義實體解析類為了將數據解析出一個復合對象,需要針對每個實體定義一個解析類,將二進制數據解析成類對象,如:RootDecoder、HeaderDecoder、BodyDecoder和TailDecoder等,其中HeaderDecoder代碼如下:public class HeaderDecoder {private Header header = new Header();/*** 按Sequence順序解析包頭* @param nodeHeader* @throws IOException*/public HeaderDecoder(DERApplicationSpecific derHeader) throws IOException{ASN1Sequence s = ASN1Sequence.getInstance(derHeader.getObject(DERTags.SEQUENCE));for (Enumeration e = s.getObjects(); e.hasMoreElements();){DERApplicationSpecific derObj = (DERApplicationSpecific)e.nextElement();System.out.println(derObj.getApplicationTag());if (derObj.getApplicationTag() == 50) {DERInteger recodeType = new DERInteger(derObj.getContents());header.setRecodeType(recodeType.getValue().intValue());}else if (derObj.getApplicationTag() == 51){DERIA5String senderCode = new DERIA5String(derObj.getContents()); header.setSenderCode(senderCode.getString());}else if (derObj.getApplicationTag() == 52){DERIA5String accepterCode = new DERIA5String(derObj.getContents());header.setAccepterCode(accepterCode.getString());}else if (derObj.getApplicationTag() == 53){DERIA5String fileSerialNo = new DERIA5String(derObj.getContents());header.setFileSerialNo(fileSerialNo.getString());}else if (derObj.getApplicationTag() == 54){DERIA5String fileCreateTime = new DERIA5String(derObj.getContents());header.setFileCreateTime(fileCreateTime.getString());}else if (derObj.getApplicationTag() == 55){DERInteger fileVersionNo = new DERInteger(derObj.getContents());header.setFileVersionNo(fileVersionNo.getValue().intValue());}}}/*** @return the header*/public Header getHeader() {return header;}}代碼簡介:該Decoder在構造函數中讀取外部傳來的DERApplicationSpecific 對象(該對象使其上層root解析子節點獲取得到的),在利用bc庫的API根據TAG值將其所有的子節點的二進制數據讀出來,最后通過bc庫內置的基本類型將二進制數據再解碼成原始數據。4.2.3 外部調用接口為了方便的實現文件解析,單獨提供一個類(DecodeMan):輸入為需要解碼的ASN1二進制文件,輸出為定義的復合類型Root,最后相關人員再通過對Root的數據進行格式化轉換成項目需要用的數據格式。public class DecodeMan {public static void main(String[] args) throws IOException {Root root = decode("c:/IVCRECORD_20110324871.0058");System.out.println(root.toString());}/*** 文件解碼* @param encodeFile 文件絕對路徑* @return 填充數據的Root實例* @throws IOException*/public static Root decode(String encodeFile) throws IOException{System.out.println("Starting decode file: [" + encodeFile + "]");File file = new File(encodeFile);byte[] byteContents = FileUtils.readFileToByteArray(file);ByteArrayInputStream inputStream = null;try{inputStream = new ByteArrayInputStream(byteContents);ASN1StreamParser asn1Parser = new ASN1StreamParser(inputStream);DERApplicationSpecific derRoot = (DERApplicationSpecific)asn1Parser.readObject();RootDecoder rootDecoder = new RootDecoder(derRoot);System.out.println("Decode file succ: [" + encodeFile + "]");return rootDecoder.getRoot();}finally{IOUtils.closeQuietly(inputStream);}}}


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情日韩图片| 久久久电影免费观看完整版| 欧美成人免费小视频| 国产亚洲激情在线| 日韩美女在线看| 国产97人人超碰caoprom| 国产精品第10页| 国产亚洲精品高潮| 国产999精品久久久影片官网| 欧美日产国产成人免费图片| 91禁外国网站| 久久色免费在线视频| 亚洲性生活视频在线观看| 日韩在线观看成人| 久久精品99久久香蕉国产色戒| 91在线免费观看网站| 久久久日本电影| 午夜精品在线观看| 国产精品96久久久久久| 久久久久久久激情视频| 美女精品视频一区| 国产精品www色诱视频| 久久天天躁狠狠躁老女人| 成人av在线网址| 欧美日韩中文字幕综合视频| 伊人久久男人天堂| 欧美精品在线免费播放| 亚洲综合社区网| 青青草一区二区| 欧美精品做受xxx性少妇| 欧美—级高清免费播放| 精品国产一区二区三区四区在线观看| 九九精品在线播放| 日韩av三级在线观看| 国语对白做受69| 精品国产一区二区三区久久狼黑人| 欧美亚洲视频在线看网址| 久久久久这里只有精品| 中文字幕精品久久| 久久影视三级福利片| 国产精品扒开腿爽爽爽视频| 伊人久久久久久久久久久久久| 97超碰蝌蚪网人人做人人爽| 日韩人体视频一二区| 91系列在线播放| 中文在线资源观看视频网站免费不卡| 91黑丝高跟在线| 国产激情综合五月久久| 亚洲精品电影网| 国产一区二区三区在线看| 高清欧美性猛交xxxx黑人猛交| 国产成人亚洲综合青青| 久久亚洲综合国产精品99麻豆精品福利| 最近2019中文字幕第三页视频| 亚洲视频精品在线| 福利视频一区二区| 91精品国产综合久久久久久久久| 色偷偷综合社区| 亚洲人av在线影院| 亚洲精品国产综合区久久久久久久| 久青草国产97香蕉在线视频| 国产日韩视频在线观看| 国产日本欧美一区二区三区在线| 性欧美长视频免费观看不卡| 8090理伦午夜在线电影| 久久久黄色av| 久久久国产精品x99av| 色悠悠久久88| 国产精品色午夜在线观看| 亚洲一区二区久久久| 久久久久久久久久亚洲| 日韩电影在线观看中文字幕| 欧美怡春院一区二区三区| 在线视频欧美日韩精品| 欧美激情一区二区三区久久久| 日韩精品有码在线观看| 夜色77av精品影院| 国产精品国产自产拍高清av水多| 国产91色在线免费| 国产精品视频一区二区三区四| 国产亚洲人成网站在线观看| 国产91在线播放| 欧美黑人狂野猛交老妇| 91老司机在线| 欧美午夜美女看片| 亚洲视频999| 亚洲福利在线看| 久久999免费视频| 久久综合久久88| 92裸体在线视频网站| 日韩美女视频中文字幕| 伊人av综合网| 精品欧美aⅴ在线网站| 日韩欧美在线国产| 国产美女被下药99| 欧美日韩国产黄| 亚洲高清福利视频| 久久免费精品日本久久中文字幕| 美女久久久久久久久久久| 日韩黄色av网站| 久久久久成人精品| 久久综合网hezyo| 国产精品久久久久久av下载红粉| 在线看片第一页欧美| 疯狂蹂躏欧美一区二区精品| 国产男女猛烈无遮挡91| 亚洲欧洲中文天堂| 亚洲精品免费一区二区三区| 精品免费在线观看| 精品欧美激情精品一区| 色婷婷久久一区二区| 欧美大尺度电影在线观看| 欧美限制级电影在线观看| 国产精品扒开腿做爽爽爽视频| www.久久久久| 成人久久久久爱| 亚洲裸体xxxx| 日韩精品在线电影| 亚洲社区在线观看| 亚洲欧美成人一区二区在线电影| 亚洲黄色有码视频| 亚洲第一页自拍| 亚洲伊人久久大香线蕉av| 亚洲欧美在线看| 久久久伊人日本| 久久影院免费观看| 亚洲精品国产精品乱码不99按摩| 欧美老女人性视频| 精品久久久久久久久久久久久| 久久免费国产视频| 亚洲另类图片色| 国产主播欧美精品| 日韩中文字幕精品| 欧美性少妇18aaaa视频| 亚洲一级片在线看| 国产亚洲美女精品久久久| 欧美激情a在线| 成人在线激情视频| 91在线高清视频| 韩国视频理论视频久久| 亚洲iv一区二区三区| 欧美一级在线亚洲天堂| 国产福利精品视频| 亚洲电影免费观看高清完整版| 日韩电影中文字幕在线观看| 久久精品视频一| 国产精品视频99| 精品一区二区三区四区| 日韩亚洲欧美中文高清在线| 亚洲深夜福利在线| 亚洲午夜激情免费视频| 国产视频久久久久| 色噜噜狠狠色综合网图区| 欧美大片免费观看在线观看网站推荐| 国内精品模特av私拍在线观看| 欧美另类xxx| 狠狠做深爱婷婷久久综合一区| 国产一区二区三区视频在线观看| 91高清免费视频| 欧美黑人极品猛少妇色xxxxx| 亚洲加勒比久久88色综合| 好吊成人免视频| 亚洲欧美国产一区二区三区| 日韩电影在线观看永久视频免费网站|