【问题标题】:Bouncy Castle ASN1 retrieving objects from BERTaggedObjectBouncy Castle ASN1 从 BERTaggedObject 检索对象
【发布时间】:2017-09-26 20:49:35
【问题描述】:

我正在使用 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
}

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

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

你可以看到SGSNPDPRecord的标签[20][0]#12是recordType和它的内容,这里一切都做得很好我用ASN1 Dump Utility检查了它。 我一直在提取SGSNPDPRecord 成员字段(recordTypenetworkInititation 等)。

我不确定如何从BERTaggedObjectberObj 中提取字段及其 berTag。

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;
}

}

【问题讨论】:

  • 能否提供输入文件?
  • 很遗憾,我不能给你整个文件,因为它有私人数据编码。我可以给它一个开始。 B4 80 80 01 12 83 08 12 19 10 31 92 58 95 F0 84 08 53 34 40 80 21 83 89 20 00 00 ,此序列将等于 berTags 0、3 和 4(recordType、servedIMSI、servedIMEI)。用于编码未定义的长度。内容结尾八位字节出现在普通的 00 和 00 分别作为标识符和长度八位字节出现的地方。长度八位字节。一个八位字节,80。

标签: java bouncycastle asn.1


【解决方案1】:

我正在使用 BouncyCastle 1.56。如果您使用的是 lots of significant changes in the API。

首先我得到了你在 cmets 中提供的数据,并构建了对应于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()对应的值,并根据每个字段的定义来处理这个值。

【讨论】:

  • 谢谢,这正是我想要的。似乎我使用了来自网络的旧代码示例,难怪他们都没有工作,因为我使用的是 1.57 BouncyCastle。
  • @SimpleThings 不客气,很高兴为您提供帮助!如果您发现这个答案有用并且它解决了您的问题,请考虑接受它:stackoverflow.com/help/someone-answers (当您有足够的代表可以这样做时,也许可以投票 - 但只有当您发现它有用时,您没有义务这样做它)
  • 我在没有完成整个帖子的情况下不小心按了 ENTER 键,我仍然没有代表来支持你的答案。我还想问的是,是否可以像上面对对象所做的那样在 BERSequence sgsnPDPRecord 上调用 getTagNo 方法(在这种情况下, sgsnPDPRecord 的 ber 标记为 20)。还有应该使用什么数据类型来处理 ASN.1 序列。例如,如果我有 ASN.1 文件:textuploader.com/djvdp,其中字段 listOfTrafficVolumes 是 ChangeOfCharCondition 的序列。很抱歉没有在这里发布整个代码,我没有足够的字符在这里发布它。
  • @SimpleThings 你不能投票,但你可以接受它(如果你觉得有帮助并且它解决了你的问题)。无论如何,sgsnPDPRecord 是一个序列,所以它没有标签(这个序列内的元素有标签)。要处理 ASN.1 序列,您可以使用 BERSequenceDERSequence(两者都扩展了 ASN1Sequence,因此您也可以使用它 - 有些实现也使用 DLSequence,但我相信所有它们适用于序列,我真的不知道彼此不同的所有细节)
  • 雨果再次感谢您的帮助。如果我有更多问题,我将发布另一个主题。万事如意!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-09
  • 1970-01-01
相关资源
最近更新 更多