ASN1編解碼實現方法
阿新 • • 發佈:2019-01-25
目 錄
版本記錄 1
目 錄 1
第1章 概述 3
1.1 背景 3
1.2 ASN.1概念 3
1.3 TAG 4
第2章 開發工具 4
2.1 開發庫 4
2.2 輔助工具 5
第3章 JavaAsn1Compiler 6
3.1 定義ASN.1描述檔案 6
3.2 生成java程式碼 6
3.2.1 程式碼生成 6
3.2.2 程式碼案例 6
3.2.3 編解碼 7
3.3 總結 8
第4章 bouncycastle 8
4.1 編碼 8
4.1.1 確定編碼的檔案格式 8
4.1.2 構造ASN1對映類 9
4.2 解碼 11
4.2.1 定義實體結構 11
4.2.2 定義實體解析類 11
4.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 就已經成為了一種國際標準,它的編碼規則已經成熟並在可靠性和相容性方面擁有更豐富的歷程。
簡潔的二進位制編碼規則(BER、CER、DER、PER,但不包括 XER)可當作更現代 XML 的替代。然而,ASN.1 支援對資料的語義進行描述,所以它是比 XML 更為高階的語言。
ASN.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章 JavaAsn1Compiler
3.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");
public
MiddleSeq()
{
super();
setUpElements();
}
public
MiddleSeq(String name)
{
super(name);
setUpElements();
}
protected void
setUpElements()
{
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章 bouncycastle
bouncycastle(簡稱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兩種型別,為了確定具體的編碼格式,利用b
版本記錄 1
目 錄 1
第1章 概述 3
1.1 背景 3
1.2 ASN.1概念 3
1.3 TAG 4
第2章 開發工具 4
2.1 開發庫 4
2.2 輔助工具 5
第3章 JavaAsn1Compiler 6
3.1 定義ASN.1描述檔案 6
3.2 生成java程式碼 6
3.2.1 程式碼生成 6
3.2.2 程式碼案例 6
3.2.3 編解碼 7
3.3 總結 8
第4章 bouncycastle 8
4.1 編碼 8
4.1.1 確定編碼的檔案格式 8
4.1.2 構造ASN1對映類 9
4.2 解碼 11
4.2.1 定義實體結構 11
4.2.2 定義實體解析類 11
4.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 就已經成為了一種國際標準,它的編碼規則已經成熟並在可靠性和相容性方面擁有更豐富的歷程。
簡潔的二進位制編碼規則(BER、CER、DER、PER,但不包括 XER)可當作更現代 XML 的替代。然而,ASN.1 支援對資料的語義進行描述,所以它是比 XML 更為高階的語言。
ASN.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章 JavaAsn1Compiler
3.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");
public
MiddleSeq()
{
super();
setUpElements();
}
public
MiddleSeq(String name)
{
super(name);
setUpElements();
}
protected void
setUpElements()
{
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章 bouncycastle
bouncycastle(簡稱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兩種型別,為了確定具體的編碼格式,利用b