Bouncy Castle ASN1从BERTaggedObject中检索对象

时间:2017-09-26 20:49:35

标签: java bouncycastle asn.1

我正在使用Bouncy Castle来解码BER X.690 ASN.1文件。

以下是ASN.1映射文件的一部分:

CallEventRecord ::= CHOICE
{
    sgsnPDPRecord [20] SGSNPDPRecord,
}

SGSNPDPRecord ::= SET
{
    recordType [0] CallEventRecordType,
    networkInitiation [1] NetworkInitiatedPDPContext OPTIONAL,
    servedIMSI [3] IMSI,
    servedIMEI [4] IMEI OPTIONAL
}

我能够从输入文件中成功读取对象。在toString BERTaggedObject上调用berObj方法会给出:

  

[20] [[0]#12,[3]#12191031148270f3,[4]#5302816004686062,]

您可以看到SGSNPDPRecord的标记[20][0]#12是recordType及其内容,所有内容都已完成,我使用ASN1转储实用程序进行了检查。 我很难提取SGSNPDPRecord个成员字段(recordTypenetworkInititation等)。

我不确定如何从BERTaggedObject berObj中提取字段及其标记。

public class SGSNPDPRecord extends ASN1Object
{
Integer recordType;
Boolean networkInitiation;
String servedIMSI;
String servedIMEI;

private static int SGSNPDP_RECORD_BER_TAG = 20;

public SGSNPDPRecord(BERTaggedObject berObj) throws IOException {

        int tagNo = berObj.getTagNo();

        // Returns tag number 20, this one is OK
        if (tagNo != SGSNPDP_RECORD_BER_TAG )
        {
            System.out.println("Invalid Tag Number!");
            return;
        }

        // How to get here someObject that will check BER Tags of primitive fields recordType, networkInitiation ... and read content from the specific ber tag
        switch ( someObj.getApplicationTag() ) 
        {
            case 0: 
                this.recordType = new Integer( someObj.getContents()[0] );
                break;
            case 1:
                this.networkInitiation = new Boolean(new String( someObj.getContents()[0], "UTF-8"));
                break;
            case 3: 
                this.servedIMSI = new String(someObj.getContents(), "UTF-8");
                break;
            case 4: 
                this.servedIMEI = new String(someObj.getContents(), "UTF-8");
                break;
            default:
                break;
        }
}

@Override
public ASN1Primitive toASN1Primitive()
{
    return null;
}

}

1 个答案:

答案 0 :(得分:0)

我正在使用BouncyCastle 1.56。如果您使用的版本< = 1.46,则代码可能不同,因为版本1.47中有lots of significant changes in the API

首先,我获得了您在评论中提供的数据,并构建了与CallEventRecord对应的标记对象:

String s = "B480800112830812191031925895F0840853344080218389200000";
ASN1InputStream in = new ASN1InputStream(Hex.decode(s));
BERTaggedObject callEventRecord = (BERTaggedObject) in.readObject();
in.close();

我只是打印了标签和内容,只是为了确保它与您的相同:

System.out.println(callEventRecord.getTagNo()); // 20
System.out.println(callEventRecord.getObject()); // [[0]#12, [3]#12191031925895f0, [4]#5334408021838920]

输出:

  

20
  [[0]#12,[3]#12191031925895f0,[4]#5334408021838920]

因此,标签是正确的(20),并且内容匹配相同的结构。让我们继续前进。

我刚检查了callEventRecord.getObject().getClass()的值,它是org.bouncycastle.asn1.BERSequence,它(根据上面的ASN.1定义)对应SGSNPDPRecord。然后我浏览了它的元素,只是为了检查它们的类型:

// get the SGSNPDPRecord
BERSequence sgsnPDPRecord = (BERSequence) callEventRecord.getObject();
for (int i = 0; i < sgsnPDPRecord.size(); i++) {
    System.out.println(sgsnPDPRecord.getObjectAt(i).getClass());
}

结果是3个元素,都是org.bouncycastle.asn1.DERTaggedObject类型。然后我修改了循环以检查每个循环的内容:

for (int i = 0; i < sgsnPDPRecord.size(); i++) {
    DERTaggedObject obj = (DERTaggedObject) sgsnPDPRecord.getObjectAt(i);
    // get the value with obj.getObject()
    switch (obj.getTagNo()) {
        case 0: // CallEventRecordType
            break;
        case 1: // NetworkInitiatedPDPContext
            break;
        case 3: // IMSI
            break;
        case 4: // IMEI
            break;
        default:
            break;
    }
}

在循环内部,您只需调用obj.getObject()即可获取每个标记的相应值。在我的测试中,所有元素都是org.bouncycastle.asn1.DEROctetString的实例,但只有上面的ASN.1定义,我才能告诉每个字段应该如何处理。

因此,您应该使用obj.getObject()获取相应的值,并根据每个字段的定义处理此值。