用bouncycastle解析asn.1

时间:2016-03-05 00:54:46

标签: decode bouncycastle asn.1

我有一些asn.1编码数据。我用bouncycastle解码它有一些成功,但是我用相当复杂的例子碰到了它。它必须是可行的,但不能进一步,希望你能帮助我,这是示例数据:

A1 81 A9 02 02 1C 1F 02 01 15 30 81 9F 55 02 01 14 A0 81 98 A4 81 95 6B 10 30 0E 80 04 00 00 01 1F A1 06 30 04 80 02 33 32 63 06 30 04 80 02 33 32 61 0E 30 0C 80 0A 30 32 32 33 37 38 33 36 31 30 62 06 30 04 80 02 33 32 64 02 87 00 6B 13 30 11 80 04 00 00 01 1F A1 09 30 07 80 05 23 23 37 30 30 4E 01 02 0A 01 16 67 12 30 10 A3 0E 81 0C 2B 34 38 32 32 33 37 38 33 36 31 30 68 0F 30 0D A3 0B 82 09 32 32 38 36 35 33 33 39 38 65 09 30 07 80 05 23 23 37 30 30 7E 12 A0 10 18 0E 32 30 31 36 30 33 30 32 32 32 30 31 33 36

CSTA Browser decoded:

rOSE.roiv-apdu
{ -- SEQUENCE -- 
    invokeID = 7199,
    operation-value = 21 (cSTAEventReport),
    argument
    { -- SEQUENCE -- 
        crossRefIdentifier = '01 14'H,
        eventSpecificInfo.callControlEvents.delivered
        { -- SEQUENCE -- 
            connection.both
            { -- SEQUENCE -- 
                callID = '00 00 01 1F'H,
                deviceID.staticID
                { -- SEQUENCE -- 
                    deviceIdentifier.dialingNumber = "32" '33 32'H
                }
            },
            alertingDevice.deviceIdentifier
            { -- SEQUENCE -- 
                deviceIdentifier.dialingNumber = "32" '33 32'H
            },
            callingDevice.deviceIdentifier
            { -- SEQUENCE -- 
                deviceIdentifier.dialingNumber = "0223783610" '30 32 32 33 37 38 33 36 31 30'H
            },
            calledDevice.deviceIdentifier
            { -- SEQUENCE -- 
                deviceIdentifier.dialingNumber = "32" '33 32'H
            },
            lastRedirectionDevice.notKnown NULL,
            originatingNIDConnection.both
            { -- SEQUENCE -- 
                callID = '00 00 01 1F'H,
                deviceID.staticID
                { -- SEQUENCE -- 
                    deviceIdentifier.dialingNumber = "##700" '23 23 37 30 30'H
                }
            },
            localConnectionInfo = 2 (alerting),
            cause = 22 (newCall),
            networkCallingDevice.deviceIdentifier
            { -- SEQUENCE -- 
                deviceIdentifier.explicitPublic.international = "+48223783610" '2B 34 38 32 32 33 37 38 33 36 31 30'H
            },
            networkCalledDevice.deviceIdentifier
            { -- SEQUENCE -- 
                deviceIdentifier.explicitPublic.national = "228653398" '32 32 38 36 35 33 33 39 38'H
            },
            associatedCallingDevice.deviceIdentifier
            { -- SEQUENCE -- 
                deviceIdentifier.dialingNumber = "##700" '23 23 37 30 30'H
            },
            extensions
            { -- SEQUENCE -- 
                security
                { -- SEQUENCE -- 
                    timestamp = "20160302220136" '32 30 31 36 30 33 30 32 32 32 30 31 33 36'H
                }
            }
        }
    }
}

bouncycastle的转储产生类似的东西:

00 AC A1 81 A9 02 02 5F B9 02 01 15 30 81 9F 55 02 01 91 A0 81 98 A4 81 95 6B 10 30 0E 80 04 00 00 03 98 A1 06 30 04 80 02 33 32 63 06 30 04 80 02 33 32 61 0E 30 0C 80 0A 30 32 32 33 37 38 33 36 31 30 62 06 30 04 80 02 33 32 64 02 87 00 6B 13 30 11 80 04 00 00 03 98 A1 09 30 07 80 05 23 23 37 30 30 4E 01 02 0A 01 16 67 12 30 10 A3 0E 81 0C 2B 34 38 32 32 33 37 38 33 36 31 30 68 0F 30 0D A3 0B 82 09 32 32 38 36 35 33 33 39 38 65 09 30 07 80 05 23 23 37 30 30 7E 12 A0 10 18 0E 32 30 31 36 30 33 30 34 31 35 32 32 34 30 
buf:Tagged [1] IMPLICIT 
    Sequence
        Integer(24505)
        Integer(21)
        DER Sequence
            DER ApplicationSpecific[21] (0191)
            Tagged [0]
                Tagged [4] IMPLICIT 
                    Sequence
                        DER ApplicationSpecific[11]
                            Sequence
                                Tagged [0] IMPLICIT 
                                    DER Octet String[4] 
                                Tagged [1]
                                    DER Sequence
                                        Tagged [0] IMPLICIT 
                                            DER Octet String[2] 
                        DER ApplicationSpecific[3]
                            Sequence
                                Tagged [0] IMPLICIT 
                                    DER Octet String[2] 
                        DER ApplicationSpecific[1]
                            Sequence
                                Tagged [0] IMPLICIT 
                                    DER Octet String[10] 
                        DER ApplicationSpecific[2]
                            Sequence
                                Tagged [0] IMPLICIT 
                                    DER Octet String[2] 
                        DER ApplicationSpecific[4]
                            Tagged [7] IMPLICIT 
                                DER Octet String[0] 
                        DER ApplicationSpecific[11]
                            Sequence
                                Tagged [0] IMPLICIT 
                                    DER Octet String[4] 
                                Tagged [1]
                                    DER Sequence
                                        Tagged [0] IMPLICIT 
                                            DER Octet String[5] 
                        DER ApplicationSpecific[14] (02)
                        DER Enumerated(22)
                        DER ApplicationSpecific[7]
                            Sequence
                                Tagged [3]
                                    Tagged [1] IMPLICIT 
                                        DER Octet String[12] 
                        DER ApplicationSpecific[8]
                            Sequence
                                Tagged [3]
                                    Tagged [2] IMPLICIT 
                                        DER Octet String[9] 
                        DER ApplicationSpecific[5]
                            Sequence
                                Tagged [0] IMPLICIT 
                                    DER Octet String[5] 
                        DER ApplicationSpecific[30]
                            Tagged [0]
                                GeneralizedTime(20160304152240GMT+01:00) 

我试图解析它:

protected void parse() {
    logger.trace("Executing parse()");

    try {

        ASN1InputStream input = new ASN1InputStream(asn1Data);
        ASN1Primitive p;

        if ((p = input.readObject()) != null) {
            ASN1TaggedObject o1 = ASN1TaggedObject.getInstance(p);
            ASN1Sequence s1 = ASN1Sequence.getInstance(o1.getObject());
            invokeID = Integer.parseInt(s1.getObjectAt(0).toString());
            operationValue = Integer.parseInt(s1.getObjectAt(1).toString());

            DERSequence ders = (DERSequence) DERSequence.getInstance(s1.getObjectAt(2));
            DERApplicationSpecific das = (DERApplicationSpecific) ders.getObjectAt(0);
            crossRefIdentifier = das.getContents();



     //here are some experiments, but can't get the right objects I could parse / walk through

            ASN1TaggedObject o2 = ASN1TaggedObject.getInstance(ders.getObjectAt(1));
            DERTaggedObject dto = (DERTaggedObject) o2.getObject();

            ASN1Sequence s2 = ASN1Sequence.getInstance(dto.getObject());
            DERApplicationSpecific das1 = (DERApplicationSpecific) s2.getObjectAt(0);
            ASN1Sequence s3 = (ASN1Sequence) das1.getObject();

            }
    } catch (Exception ex) {
        logger.warn("exception while parsing ASN1 data", ex);
    }

}

正如您所看到的,我已经能够解码一些基本标签(即invokeID,operation-value和crossRefIdentifier),但不能在树中更深入(callId,callingNumber ...)。 如果您有相关经验,我将非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

这是一个非常复杂的ASN.1对象。由于结构差异,有几个地方可能会出现另一个样本出错的地方。这是一个例子。

using System;
using System.Collections;
using System.IO;
using Org.BouncyCastle.Asn1;

namespace Asn1ParseBouncy
{
    class Program
    {
        static void Main(string[] args)
        {
            var bytes2Parse = File.ReadAllBytes(@"c:\a.req");

            // (0,169) CONTEXT SPECIFIC(1)
            DerTaggedObject rootObj = (DerTaggedObject)Asn1Object.FromByteArray(bytes2Parse);

            if (rootObj.TagNo == 1)
            {
                ParseAtRootLevel(rootObj);
            }
            else
            {
                throw new Exception("Expected Tag number to be 1");
            }
        }

        private static void ParseAtRootLevel(DerTaggedObject rootObj)
        {
            // SEQUENCE under CONTEXT SPECIFIC(1)
            var seq = (Asn1Sequence)rootObj.GetObject();

            IEnumerator e = seq.GetEnumerator();
            bool hasNext;
            hasNext = e.MoveNext();

            // (3,2) INTEGER -> invokeID 
            {
                Asn1Encodable obj;

                if (!hasNext)
                {
                    throw new Exception("more entries expected in sequence");
                }
                obj = (Asn1Encodable)e.Current;

                // TODO: put in a property of class that represents whole ASN.1 message
                var invokeID = DerInteger.GetInstance(obj);

                hasNext = e.MoveNext();

            }

            // (7,1) INTEGER -> operation-value
            {
                Asn1Encodable obj;

                if (!hasNext)
                {
                    throw new Exception("more entries expected in sequence");
                }
                obj = (Asn1Encodable)e.Current;

                // TODO: put in a property of class that represents whole ASN.1 message
                var operationValue = DerInteger.GetInstance(obj);

                hasNext = e.MoveNext();

            }

            // (10,159) SEQUENCE -> argument
            {
                Asn1Encodable obj;

                if (!hasNext)
                {
                    throw new Exception("more entries expected in sequence");
                }
                obj = (Asn1Encodable)e.Current;

                var argumentSeq = Asn1Sequence.GetInstance(obj);

                // argumentData is parsed asn.1 object - argument 
                var argumentData = ParseArgumentData(argumentSeq);

                hasNext = e.MoveNext();
            }

            if (hasNext)
            {
                throw new Exception("no more entries expected in sequence");
            }
        }

        private static object ParseArgumentData(Asn1Sequence argumentSeq)
        {
            IEnumerator e = argumentSeq.GetEnumerator();
            bool hasNext;
            hasNext = e.MoveNext();

            // (13,2) APPLICATION (21) -> crossRefIdentifier  
            {
                Asn1Encodable obj;

                if (!hasNext)
                {
                    throw new Exception("more entries expected in sequence");
                }
                obj = (Asn1Encodable)e.Current;

                var crossRefIdentifierAppSpecific = (DerApplicationSpecific)obj;
                if (crossRefIdentifierAppSpecific.ApplicationTag != 21)
                    throw new Exception("Expected application tag 21");

                // TODO: put in a property of class that represents whole ASN.1 message
                var crossRefIdentifier = crossRefIdentifierAppSpecific.GetContents();

                hasNext = e.MoveNext();

            }

            // (17,152) CONTEXT SPECIFIC (0) -> eventSpecificInfo.callControlEvents.delivered  
            {
                Asn1Encodable obj;

                if (!hasNext)
                {
                    throw new Exception("more entries expected in sequence");
                }
                obj = (Asn1Encodable)e.Current;

                var eventSpecificInfo = ((DerTaggedObject)obj);

                if (eventSpecificInfo.TagNo != 0)
                    throw new Exception("Expected Context specific tag number to be 0");

                // TODO: put in a property of class that represents whole ASN.1 message
                var eventSpecificInfoData = ParseEventSpecificInfo(eventSpecificInfo);

                hasNext = e.MoveNext();

            }

            if (hasNext)
            {
                throw new Exception("no more entries expected in sequence");
            }

            // TODO: return parsed values in some class
            return null;
        }

        private static object ParseEventSpecificInfo(DerTaggedObject obj)
        {
            // still (17,152) CONTEXT SPECIFIC (0)
            var connectionBothData = ParseConnectionBoth(obj);

            return connectionBothData;
        }

        private static object ParseConnectionBoth(DerTaggedObject connectionBoth)
        {
            // (20,149) CONTEXT SPECIFIC (4)->connection.both
            var connectionBothTagged = (DerTaggedObject)connectionBoth.GetObject();

            if (connectionBothTagged.TagNo != 4)
                throw new Exception("Expected Context specific tag number to be 4");

            // Sequence under (20,149) CONTEXT SPECIFIC (4) -> connection.both
            var connectionBothSeq = (DerSequence)connectionBothTagged.GetObject();

            IEnumerator e = connectionBothSeq.GetEnumerator();
            bool hasNext;
            hasNext = e.MoveNext();

            // callID   
            {
                Asn1Encodable obj;

                if (!hasNext)
                {
                    throw new Exception("more entries expected in sequence");
                }
                obj = (Asn1Encodable)e.Current;

                // (23,16) APPLICATION (11)
                // TODO: put in a property of class that represents whole ASN.1 message
                var callIDTagged = (DerApplicationSpecific)obj;
                if (callIDTagged.ApplicationTag != 11)
                    throw new Exception("Expected tag number 11");

                // (25,14) SEQUENCE
                var callIdSeq = callIDTagged.GetObject().GetDerEncoded();

                // TODO: parse CallIdSeq -> (27,4) ContextSpecific(0), (33,6) ContextSpecific(1)

                hasNext = e.MoveNext();

            }

            // TODO: continue with (41,6) Application (3)
            // TODO: continue with (49,14) Application (1)
            // TODO: continue with (65,6) Application (2)
            // etc.

            // TOOD: return something useful
            throw new NotImplementedException();
        }
    }
}

我根据来自ASN.1 Editor的转储在代码示例中放置了注释 dump of your sample

如果你有对象的ASN.1定义,你可以让你的生活更轻松。在Binary Notes的帮助下,您可以生成用于解析ASN.1数据对象的类。