I am using Bouncy Castle to decode BER X.690 ASN.1 files.
Here is part of ASN.1 mapping file:
CallEventRecord ::= CHOICE
{
sgsnPDPRecord [20] SGSNPDPRecord,
}
SGSNPDPRecord ::= SET
{
recordType [0] CallEventRecordType,
networkInitiation [1] NetworkInitiatedPDPContext OPTIONAL,
servedIMSI [3] IMSI,
servedIMEI [4] IMEI OPTIONAL
}
I am able to successfully read object from input file. And calling toString
method on BERTaggedObject
berObj
gives:
[20][[0]#12, [3]#12191031148270f3, [4]#5302816004686062,]
You can see SGSNPDPRecord
's tag [20]
, [0]#12
is recordType and it's content, everything is done well here I checked it with ASN1 Dump Utility.
I am stuck with extracting SGSNPDPRecord
member fields (recordType
, networkInititation
, etc).
I am not sure how should I extract fields and their berTags from 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;
}
}
I'm using BouncyCastle 1.56. If you're using a version <= 1.46, the code might not be the same, because in version 1.47 there were lots of significant changes in the API.
First I've got the data you provided in the comments and built the tagged object corresponding to CallEventRecord
:
String s = "B480800112830812191031925895F0840853344080218389200000";
ASN1InputStream in = new ASN1InputStream(Hex.decode(s));
BERTaggedObject callEventRecord = (BERTaggedObject) in.readObject();
in.close();
I've just printed the tag and the content, just to make sure it's the same as yours:
System.out.println(callEventRecord.getTagNo()); // 20
System.out.println(callEventRecord.getObject()); // [[0]#12, [3]#12191031925895f0, [4]#5334408021838920]
The output:
20
[[0]#12, [3]#12191031925895f0, [4]#5334408021838920]
So, the tag is correct (20), and the content matches the same structure. Let's move on.
I've just checked the value of callEventRecord.getObject().getClass()
and it's a org.bouncycastle.asn1.BERSequence
, which (according to the ASN.1 definition above) corresponds to SGSNPDPRecord
. Then I looped through its elements, just to check their types:
// get the SGSNPDPRecord
BERSequence sgsnPDPRecord = (BERSequence) callEventRecord.getObject();
for (int i = 0; i < sgsnPDPRecord.size(); i++) {
System.out.println(sgsnPDPRecord.getObjectAt(i).getClass());
}
The result was 3 elements, all with the type org.bouncycastle.asn1.DERTaggedObject
. Then I modified the loop to check the contents of each one:
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;
}
}
Inside the loop, you just call obj.getObject()
to get the corresponding value for each tag. In my test, all elements were instances of org.bouncycastle.asn1.DEROctetString
, but only with the ASN.1 definition above I can't tell how each field should be handled.
So, you should get the corresponding value with obj.getObject()
and treat this value according to each field's definition.