Example #1
0
        private static void BuildKrbApReq(KrbApReq krbApReq, Asn1Node asn1Node)
        {
            Asn1Node childNode1 = asn1Node.GetChildNode(0);

            for (int index = 0; (long)index < childNode1.ChildNodeCount; ++index)
            {
                Asn1Node childNode2 = childNode1.GetChildNode(index);
                switch (KerberosAuthorizeMessageBuilder.GetContextNumber(childNode2))
                {
                case 0:
                    krbApReq.ProtocolVersionNumber = (int)Asn1Util.BytesToLong(childNode2.GetChildNode(0).Data);
                    break;

                case 1:
                    krbApReq.MessageType = (MessageType)Asn1Util.BytesToLong(childNode2.GetChildNode(0).Data);
                    break;

                case 2:
                    krbApReq.APOptions = (APOptions)Asn1Util.BytesToLong(childNode2.GetChildNode(0).Data);
                    break;

                case 3:
                    krbApReq.Ticket = new Ticket();
                    KerberosAuthorizeMessageBuilder.BuildTicket(krbApReq.Ticket, childNode2);
                    break;

                case 4:
                    krbApReq.Authenticator = new EncryptedData();
                    KerberosAuthorizeMessageBuilder.BuildEncryptedData(krbApReq.Authenticator, childNode2);
                    break;
                }
            }
        }
Example #2
0
        /**
         * Parses an DER encoded RSA public key:
         * It will only try to get the mod and the exponent
         */
        private RSACryptoServiceProvider ParseNode(Asn1Node n)
        {
            if ((n.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.SEQUENCE &&
                n.ChildNodeCount == 2 &&
                (n.GetChildNode(0).Tag & Asn1Tag.TAG_MASK) == Asn1Tag.SEQUENCE &&
                (n.GetChildNode(0).GetChildNode(0).Tag & Asn1Tag.TAG_MASK) == Asn1Tag.OBJECT_IDENTIFIER &&
                n.GetChildNode(0).GetChildNode(0).GetDataStr(false) == "1.2.840.113549.1.1.1" &&
                (n.GetChildNode(1).Tag & Asn1Tag.TAG_MASK) == Asn1Tag.BIT_STRING)
            {
                var seq = n.GetChildNode(1).GetChildNode(0);
                if (seq.ChildNodeCount == 2)
                {
                    byte[] data   = seq.GetChildNode(0).Data;
                    byte[] rawMod = new byte[data.Length - 1];
                    System.Array.Copy(data, 1, rawMod, 0, data.Length - 1);

                    var modulus  = System.Convert.ToBase64String(rawMod);
                    var exponent = System.Convert.ToBase64String(seq.GetChildNode(1).Data);
                    var result   = new RSACryptoServiceProvider();
                    result.FromXmlString(ToXML(modulus, exponent));

                    return(result);
                }
            }
            throw new InvalidRSAData();
        }
Example #3
0
        private static void BuildTicket(Ticket ticket, Asn1Node asn1Node)
        {
            Asn1Node childNode1 = asn1Node.GetChildNode(0).GetChildNode(0);

            for (int index = 0; (long)index < childNode1.ChildNodeCount; ++index)
            {
                Asn1Node childNode2 = childNode1.GetChildNode(index);
                switch (KerberosAuthorizeMessageBuilder.GetContextNumber(childNode2))
                {
                case 0:
                    ticket.TicketVersionNumber = (int)Asn1Util.BytesToLong(childNode2.GetChildNode(0).Data);
                    break;

                case 1:
                    ticket.Realm = childNode2.GetChildNode(0).GetDataStr(false);
                    break;

                case 2:
                    ticket.ServiceName = new PrincipalName();
                    KerberosAuthorizeMessageBuilder.BuildPrincipleName(ticket.ServiceName, childNode2);
                    break;

                case 3:
                    ticket.EncPart = new EncryptedData();
                    KerberosAuthorizeMessageBuilder.BuildEncryptedData(ticket.EncPart, childNode2);
                    break;
                }
            }
        }
        private void ParseNode(Asn1Node root)
        {
            if ((root.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.SEQUENCE || root.ChildNodeCount != 3)
            {
                throw new InvalidX509Data();
            }



            // TBS cert
            TbsCertificate = root.GetChildNode(0);
            if (TbsCertificate.ChildNodeCount < 7)
            {
                throw new InvalidX509Data();
            }

            rawTBSCertificate = new byte[TbsCertificate.DataLength + 4];
            Array.Copy(root.Data, 0, rawTBSCertificate, 0, rawTBSCertificate.Length);

            // get the serial number
            Asn1Node sn = TbsCertificate.GetChildNode(1);

            if ((sn.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.INTEGER)
            {
                throw new InvalidX509Data();
            }
            SerialNumber = Asn1Util.ToHexString(sn.Data);

            // get the issuer
            Issuer = new DistinguishedName(TbsCertificate.GetChildNode(3));

            // get the subject
            Subject = new DistinguishedName(TbsCertificate.GetChildNode(5));

            // get the dates
            Asn1Node validTimes = TbsCertificate.GetChildNode(4);

            if ((validTimes.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.SEQUENCE || validTimes.ChildNodeCount != 2)
            {
                throw new InvalidX509Data();
            }
            ValidAfter  = ParseTime(validTimes.GetChildNode(0));
            ValidBefore = ParseTime(validTimes.GetChildNode(1));

            // is this self signed?
            SelfSigned = Subject.Equals(Issuer);

            // get the pub key
            PubKey = new RSAKey(TbsCertificate.GetChildNode(6));

            // set the tbs cert & signature data for signature verification
            Signature = root.GetChildNode(2);
        }
 private Asn1Node GetSetNode(Asn1Node data)
 {
     if (data.IsIndefiniteLength && data.ChildNodeCount == 1)
     {
         // Explanation: Receipts received from the iOS StoreKit Testing encodes the receipt data one layer deeper than expected.
         // It also has nodes with "Indeterminate" or "Undefined" length, including the node in question.
         // Failing to go one node deeper will result in an unparsed receipt.
         var intermediateNode = data.GetChildNode(0);
         return(intermediateNode.GetChildNode(0));
     }
     else
     {
         return(data.GetChildNode(0));
     }
 }
    private static string getStringFromSubNode(Asn1Node nn)
    {
        string dataStr = null;

        if ((nn.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.OCTET_STRING && nn.ChildNodeCount > 0)
        {
            Asn1Node n = nn.GetChildNode(0);
            switch (n.Tag & Asn1Tag.TAG_MASK)
            {
            case Asn1Tag.PRINTABLE_STRING:
            case Asn1Tag.IA5_STRING:
            case Asn1Tag.UNIVERSAL_STRING:
            case Asn1Tag.VISIBLE_STRING:
            case Asn1Tag.NUMERIC_STRING:
            case Asn1Tag.UTC_TIME:
            case Asn1Tag.UTF8_STRING:
            case Asn1Tag.BMPSTRING:
            case Asn1Tag.GENERAL_STRING:
            case Asn1Tag.GENERALIZED_TIME:
            {
                if ((n.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.UTF8_STRING)
                {
                    UTF8Encoding unicode = new UTF8Encoding();
                    dataStr = unicode.GetString(n.Data);
                }
                else
                {
                    dataStr = Asn1Util.BytesToString(n.Data);
                }
            }
            break;
            }
        }
        return(dataStr);
    }
        private AppleReceipt ParseReceipt(Asn1Node data)
        {
            if (data == null || data.ChildNodeCount != 1)
            {
                throw new InvalidPKCS7Data();
            }

            Asn1Node set = GetSetNode(data);

            var result = new AppleReceipt();
            var inApps = new List <AppleInAppPurchaseReceipt> ();

            for (int t = 0; t < set.ChildNodeCount; t++)
            {
                var node = set.GetChildNode(t);
                // Each node should contain three children.

                if (node.ChildNodeCount == 3)
                {
                    var type  = Asn1Util.BytesToLong(node.GetChildNode(0).Data);
                    var value = node.GetChildNode(2);
                    // See https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1
                    switch (type)
                    {
                    case 2:
                        result.bundleID = Encoding.UTF8.GetString(value.GetChildNode(0).Data);
                        break;

                    case 3:
                        result.appVersion = Encoding.UTF8.GetString(value.GetChildNode(0).Data);
                        break;

                    case 4:
                        result.opaque = value.Data;
                        break;

                    case 5:
                        result.hash = value.Data;
                        break;

                    case 12:
                        var dateString = Encoding.UTF8.GetString(value.GetChildNode(0).Data);
                        result.receiptCreationDate = DateTime.Parse(dateString).ToUniversalTime();
                        break;

                    case 17:
                        inApps.Add(ParseInAppReceipt(value.GetChildNode(0)));
                        break;

                    case 19:
                        result.originalApplicationVersion = Encoding.UTF8.GetString(value.GetChildNode(0).Data);
                        break;
                    }
                }
            }

            result.inAppPurchaseReceipts = inApps.ToArray();
            return(result);
        }
Example #8
0
        private static void BuildNegotiateTokenInit(NegTokenInit negToken, Asn1Node sequence)
        {
            for (int index = 0; (long)index < sequence.ChildNodeCount; ++index)
            {
                switch (KerberosAuthorizeMessageBuilder.GetContextNumber(sequence.GetChildNode(index)))
                {
                case 0:
                    KerberosAuthorizeMessageBuilder.BuildMechTypes(negToken, sequence.GetChildNode(index));
                    break;

                case 2:
                    negToken.MechToken = new InitialContextToken();
                    KerberosAuthorizeMessageBuilder.BuildMechToken(negToken.MechToken, sequence.GetChildNode(index));
                    break;
                }
            }
        }
Example #9
0
        private static void BuildMechTypes(NegTokenInit negToken, Asn1Node asn1Node)
        {
            if (asn1Node.ChildNodeCount <= 0L)
            {
                return;
            }
            Asn1Node childNode = asn1Node.GetChildNode(0);

            negToken.MechTypes = new List <MechType>();
            for (int index = 0; (long)index < childNode.ChildNodeCount; ++index)
            {
                if (((int)childNode.GetChildNode(index).Tag & 31) == 6)
                {
                    negToken.MechTypes.Add(new MechType(childNode.GetChildNode(index).GetDataStr(false)));
                }
            }
        }
Example #10
0
        private static void BuildPrincipleNameList(List <string> list, Asn1Node asn1Node)
        {
            Asn1Node childNode = asn1Node.GetChildNode(0);

            for (int index = 0; (long)index < childNode.ChildNodeCount; ++index)
            {
                list.Add(childNode.GetChildNode(index).GetDataStr(false));
            }
        }
        /// <summary>
        /// Try and parse a DateTime, returning the minimum DateTime on failure.
        /// </summary>
        private static DateTime TryParseDateTimeNode(Asn1Node node)
        {
            var dateString = Encoding.UTF8.GetString(node.GetChildNode(0).Data);

            if (!string.IsNullOrEmpty(dateString))
            {
                return(DateTime.Parse(dateString).ToUniversalTime());
            }

            return(DateTime.MinValue);
        }
Example #12
0
        private static void BuildMechToken(InitialContextToken initialContextToken, Asn1Node asn1Node)
        {
            Asn1Node childNode = asn1Node.GetChildNode(0).GetChildNode(0);

            for (int index = 0; (long)index < childNode.ChildNodeCount; ++index)
            {
                if (((int)childNode.GetChildNode(index).Tag & 192) != 0)
                {
                    if (((int)childNode.GetChildNode(index).Tag & 192) == 64)
                    {
                        initialContextToken.InnerContextToken = new KrbApReq();
                        KerberosAuthorizeMessageBuilder.BuildKrbApReq(initialContextToken.InnerContextToken, childNode.GetChildNode(index));
                    }
                }
                else if (((int)childNode.GetChildNode(index).Tag & 31) == 6)
                {
                    initialContextToken.ThisMech = new MechType(childNode.GetChildNode(index).GetDataStr(false));
                }
            }
        }
Example #13
0
        public SignerInfo(Asn1Node n)
        {
            if (n.ChildNodeCount != 5)
            {
                throw new InvalidPKCS7Data();
            }
            Asn1Node tt;

            // version
            tt = n.GetChildNode(0);
            if ((tt.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.INTEGER)
            {
                throw new InvalidPKCS7Data();
            }
            Version = tt.Data[0];
            if (Version != 1 || tt.Data.Length != 1)
            {
                throw new UnsupportedSignerInfoVersion();
            }

            // get the issuer SN
            tt = n.GetChildNode(1);
            if ((tt.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.SEQUENCE || tt.ChildNodeCount != 2)
            {
                throw new InvalidPKCS7Data();
            }
            tt = tt.GetChildNode(1);
            if ((tt.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.INTEGER)
            {
                throw new InvalidPKCS7Data();
            }
            IssuerSerialNumber = Asn1Util.ToHexString(tt.Data);

            // get the data
            tt = n.GetChildNode(4);
            if ((tt.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.OCTET_STRING)
            {
                throw new InvalidPKCS7Data();
            }
            EncryptedDigest = tt.Data;
        }
        public int GetIntegerFromNode(Asn1Node nn)
        {
            int retval = -1;

            if ((nn.Tag & Asn1Type.Date) == Asn1Type.OctetString && nn.ChildNodeCount > 0)
            {
                Asn1Node n = nn.GetChildNode(0);
                if ((n.Tag & Asn1Type.Date) == Asn1Type.Integer)
                {
                    retval = (int)_utilities.BytesToLong(n.Data);
                }
            }
            return(retval);
        }
    private static int getIntegerFromSubNode(Asn1Node nn)
    {
        int retval = -1;

        if ((nn.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.OCTET_STRING && nn.ChildNodeCount > 0)
        {
            Asn1Node n = nn.GetChildNode(0);
            if ((n.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.INTEGER)
            {
                retval = (int)Asn1Util.BytesToLong(n.Data);
            }
        }
        return(retval);
    }
Example #16
0
        private static void BuildEncryptedData(EncryptedData encryptedData, Asn1Node asn1Node)
        {
            Asn1Node childNode1 = asn1Node.GetChildNode(0);

            for (int index = 0; (long)index < childNode1.ChildNodeCount; ++index)
            {
                Asn1Node childNode2 = childNode1.GetChildNode(index);
                switch (KerberosAuthorizeMessageBuilder.GetContextNumber(childNode2))
                {
                case 0:
                    encryptedData.EncryptionType = (EncryptionType)Asn1Util.BytesToLong(childNode2.GetChildNode(0).Data);
                    break;

                case 1:
                    encryptedData.KeyVersionNumber = new uint?((uint)Asn1Util.BytesToLong(childNode2.GetChildNode(0).Data));
                    break;

                case 2:
                    encryptedData.Cipher = new byte[childNode2.GetChildNode(0).DataLength];
                    Buffer.BlockCopy((Array)childNode2.GetChildNode(0).Data, 0, (Array)encryptedData.Cipher, 0, encryptedData.Cipher.Length);
                    break;
                }
            }
        }
Example #17
0
        private static void BuildPrincipleName(PrincipalName principalName, Asn1Node asn1Node)
        {
            Asn1Node childNode1 = asn1Node.GetChildNode(0);

            for (int index = 0; (long)index < childNode1.ChildNodeCount; ++index)
            {
                Asn1Node childNode2 = childNode1.GetChildNode(index);
                switch (KerberosAuthorizeMessageBuilder.GetContextNumber(childNode2))
                {
                case 0:
                    principalName.NameType = (PrincipalNameType)Asn1Util.BytesToLong(childNode2.GetChildNode(0).Data);
                    break;

                case 1:
                    principalName.NameString = new List <string>();
                    KerberosAuthorizeMessageBuilder.BuildPrincipleNameList(principalName.NameString, childNode2);
                    break;
                }
            }
        }
Example #18
0
 private static void BuildRoot(KerberosAuthorizeMessage msg, Asn1Node root)
 {
     if (root.ChildNodeCount == 2L)
     {
         Asn1Node childNode = root.GetChildNode(0);
         if (((int)childNode.Tag & 31) != 6)
         {
             throw new Exception("OBJECT_IDENTIFIER expected. (path: " + childNode.Path + ")");
         }
         msg.MechType         = new MechType(childNode.GetDataStr(false));
         msg.NegotiationToken = (NegotiationToken) new NegTokenInit();
         KerberosAuthorizeMessageBuilder.BuildNegotiateTokenInit((NegTokenInit)msg.NegotiationToken, root.GetChildNode(1).GetChildNode(0));
     }
     else
     {
         if (root.ChildNodeCount != 1L)
         {
             return;
         }
         msg.NegotiationToken = (NegotiationToken) new NegTokenInit();
         KerberosAuthorizeMessageBuilder.BuildNegotiateTokenInit((NegTokenInit)msg.NegotiationToken, root.GetChildNode(0));
     }
 }
Example #19
0
        public string?GetStringFromNode(Asn1Node nn)
        {
            string dataStr = null;

            if ((nn.Tag & Asn1Type.Date) == Asn1Type.OctetString && nn.ChildNodeCount > 0)
            {
                var n = nn.GetChildNode(0);

                switch (n.Tag & Asn1Type.Date)
                {
                case Asn1Type.PrintableString:
                case Asn1Type.Ia5String:
                case Asn1Type.UniversalString:
                case Asn1Type.VisibleString:
                case Asn1Type.NumericString:
                case Asn1Type.UtcTime:
                case Asn1Type.Utf8String:
                case Asn1Type.Bmpstring:
                case Asn1Type.GeneralString:
                case Asn1Type.GeneralizedTime:
                {
                    if ((n.Tag & Asn1Type.Date) == Asn1Type.Utf8String)
                    {
                        var unicode = new UTF8Encoding();
                        dataStr = unicode.GetString(n.Data);
                    }
                    else
                    {
                        dataStr = Encoding.ASCII.GetString(n.Data);
                    }
                }
                break;
                }
            }

            return(dataStr);
        }
Example #20
0
        private void CheckStructure()
        {
            validStructure = false;
            if ((root.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.SEQUENCE &&
                root.ChildNodeCount == 2)
            {
                Asn1Node tt = root.GetChildNode(0);
                if ((tt.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.OBJECT_IDENTIFIER ||
                    tt.GetDataStr(false) != "1.2.840.113549.1.7.2")
                {
                    throw new InvalidPKCS7Data();
                }

                tt = root.GetChildNode(1);                 // [0]
                if (tt.ChildNodeCount != 1)
                {
                    throw new InvalidPKCS7Data();
                }
                int curChild = 0;

                tt = tt.GetChildNode(curChild++);                 // Seq
                if (tt.ChildNodeCount < 4 || (tt.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.SEQUENCE)
                {
                    throw new InvalidPKCS7Data();
                }

                Asn1Node tt2 = tt.GetChildNode(0);                 // version
                if ((tt2.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.INTEGER)
                {
                    throw new InvalidPKCS7Data();
                }

                tt2 = tt.GetChildNode(curChild++);                 // digest algo
                // TODO: check algo
                if ((tt2.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.SET)
                {
                    throw new InvalidPKCS7Data();
                }

                tt2 = tt.GetChildNode(curChild++);                 // pkcs7 data
                if ((tt2.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.SEQUENCE && tt2.ChildNodeCount != 2)
                {
                    throw new InvalidPKCS7Data();
                }
                data = tt2.GetChildNode(1).GetChildNode(0);

                if (tt.ChildNodeCount == 5)
                {
                    // cert chain, this is optional
                    certChain = new List <X509Cert>();
                    tt2       = tt.GetChildNode(curChild++);
                    if (tt2.ChildNodeCount == 0)
                    {
                        throw new InvalidPKCS7Data();
                    }
                    for (int i = 0; i < tt2.ChildNodeCount; i++)
                    {
                        certChain.Add(new X509Cert(tt2.GetChildNode(i)));
                    }
                }

                tt2 = tt.GetChildNode(curChild++);                 // signer's info
                if ((tt2.Tag & Asn1Tag.TAG_MASK) != Asn1Tag.SET || tt2.ChildNodeCount == 0)
                {
                    throw new InvalidPKCS7Data();
                }

                sinfos = new List <SignerInfo>();
                for (int i = 0; i < tt2.ChildNodeCount; i++)
                {
                    sinfos.Add(new SignerInfo(tt2.GetChildNode(i)));
                }
                validStructure = true;
            }
        }
        public AppleAppReceipt GetAppleReceiptFromNode(Asn1Node tNode, AppleAppReceipt?receipt = null)
        {
            receipt ??= new AppleAppReceipt();

            var processedNode = false;

            if ((tNode.Tag & Asn1Type.Date) == Asn1Type.Sequence && tNode.ChildNodeCount == 3)
            {
                var node1 = tNode.GetChildNode(0);
                var node2 = tNode.GetChildNode(1);
                var node3 = tNode.GetChildNode(2);

                if ((node1.Tag & Asn1Type.Date) == Asn1Type.Integer &&
                    (node2.Tag & Asn1Type.Date) == Asn1Type.Integer &&
                    (node3.Tag & Asn1Type.Date) == Asn1Type.OctetString)
                {
                    processedNode = true;
                    var asnType = (ReceiptAsnType)_utilities.BytesToLong(node1.Data);
                    switch (asnType)
                    {
                    case ReceiptAsnType.ReceiptType:
                        receipt.ReceiptType = _nodesParser.GetStringFromNode(node3);
                        break;

                    case ReceiptAsnType.BundleIdentifier:
                        receipt.BundleId = _nodesParser.GetStringFromNode(node3);
                        break;

                    case ReceiptAsnType.AppVersion:
                        receipt.ApplicationVersion = _nodesParser.GetStringFromNode(node3);
                        break;

                    case ReceiptAsnType.OpaqueValue:
                        break;

                    case ReceiptAsnType.Hash:
                        break;

                    case ReceiptAsnType.OriginalAppVersion:
                        receipt.OriginalApplicationVersion = _nodesParser.GetStringFromNode(node3);
                        break;

                    case ReceiptAsnType.ReceiptExpirationDate:
                        break;

                    case ReceiptAsnType.ReceiptCreationDate:
                        receipt.ReceiptCreationDateMs = _nodesParser.GetDateTimeMsFromNode(node3);
                        break;

                    case ReceiptAsnType.OriginalPurchaseDate:
                        receipt.OriginalPurchaseDateMs = _nodesParser.GetDateTimeMsFromNode(node3);
                        break;

                    case ReceiptAsnType.InAppPurchaseReceipt:
                    {
                        if (node3.ChildNodeCount > 0)
                        {
                            var node31 = node3.GetChildNode(0);

                            if ((node31.Tag & Asn1Type.Date) == Asn1Type.Set && node31.ChildNodeCount > 0)
                            {
                                var purchaseReceipt = new AppleInAppPurchaseReceipt();

                                for (var i = 0; i < node31.ChildNodeCount; i++)
                                {
                                    var node311 = node31.GetChildNode(i);
                                    if ((node311.Tag & Asn1Type.Date) == Asn1Type.Sequence &&
                                        node311.ChildNodeCount == 3)
                                    {
                                        var node3111 = node311.GetChildNode(0);
                                        var node3112 = node311.GetChildNode(1);
                                        var node3113 = node311.GetChildNode(2);

                                        if ((node3111.Tag & Asn1Type.Date) == Asn1Type.Integer &&
                                            (node3112.Tag & Asn1Type.Date) == Asn1Type.Integer &&
                                            (node3113.Tag & Asn1Type.Date) == Asn1Type.OctetString)
                                        {
                                            var childAsnType = (InAppPurchaseAsnType)_utilities.BytesToLong(node3111.Data);
                                            switch (childAsnType)
                                            {
                                            case InAppPurchaseAsnType.Quantity:
                                                purchaseReceipt.Quantity = _nodesParser.GetIntegerFromNode(node3113).ToString();
                                                break;

                                            case InAppPurchaseAsnType.ProductIdentifier:
                                                purchaseReceipt.ProductId = _nodesParser.GetStringFromNode(node3113);
                                                break;

                                            case InAppPurchaseAsnType.TransactionIdentifier:
                                                purchaseReceipt.TransactionId = _nodesParser.GetStringFromNode(node3113);
                                                break;

                                            case InAppPurchaseAsnType.PurchaseDate:
                                                purchaseReceipt.PurchaseDateMs = _nodesParser.GetDateTimeMsFromNode(node3113);
                                                break;

                                            case InAppPurchaseAsnType.OriginalTransactionIdentifier:
                                                purchaseReceipt.OriginalTransactionId = _nodesParser.GetStringFromNode(node3113);
                                                break;

                                            case InAppPurchaseAsnType.OriginalPurchaseDate:
                                                purchaseReceipt.OriginalPurchaseDateMs = _nodesParser.GetDateTimeMsFromNode(node3113);
                                                break;

                                            case InAppPurchaseAsnType.SubscriptionExpirationDate:
                                                purchaseReceipt.ExpirationDateMs = _nodesParser.GetDateTimeMsFromNode(node3113);
                                                break;

                                            case InAppPurchaseAsnType.WebOrderLineItemId:
                                                purchaseReceipt.WebOrderLineItemId = _nodesParser.GetStringFromNode(node3113);
                                                break;

                                            case InAppPurchaseAsnType.CancellationDate:
                                                purchaseReceipt.CancellationDateMs = _nodesParser.GetDateTimeMsFromNode(node3113);
                                                break;

                                            case InAppPurchaseAsnType.SubscriptionIntroductoryPricePeriod:
                                                purchaseReceipt.IsInIntroOfferPeriod = _nodesParser.GetBoolFromNode(node3113);
                                                break;

                                            default:
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (!string.IsNullOrEmpty(purchaseReceipt.ProductId))
                                {
                                    receipt.PurchaseReceipts.Add(purchaseReceipt);
                                }
                            }
                        }
                    }
                    break;

                    default:
                        processedNode = false;
                        break;
                    }
                }
            }

            if (!processedNode)
            {
                for (var i = 0; i < tNode.ChildNodeCount; i++)
                {
                    var chld = tNode.GetChildNode(i);
                    if (chld != null)
                    {
                        var subReceipt = GetAppleReceiptFromNode(chld, receipt);
                        if (subReceipt.PurchaseReceipts != null)
                        {
                            foreach (var sr in subReceipt.PurchaseReceipts)
                            {
                                if (receipt.PurchaseReceipts.All(purchaseReceipt =>
                                                                 purchaseReceipt.ProductId != sr.ProductId))
                                {
                                    receipt.PurchaseReceipts.Add(sr);
                                }
                            }
                        }
                    }
                }
            }

            return(receipt);
        }
        private AppleInAppPurchaseReceipt ParseInAppReceipt(Asn1Node inApp)
        {
            var result = new AppleInAppPurchaseReceipt();

            for (int t = 0; t < inApp.ChildNodeCount; t++)
            {
                var node = inApp.GetChildNode(t);
                if (node.ChildNodeCount == 3)
                {
                    var type  = Asn1Util.BytesToLong(node.GetChildNode(0).Data);
                    var value = node.GetChildNode(2);
                    switch (type)
                    {
                    case 1701:
                        result.quantity = (int)Asn1Util.BytesToLong(value.GetChildNode(0).Data);
                        break;

                    case 1702:
                        result.productID = Encoding.UTF8.GetString(value.GetChildNode(0).Data);
                        break;

                    case 1703:
                        result.transactionID = Encoding.UTF8.GetString(value.GetChildNode(0).Data);
                        break;

                    case 1705:
                        result.originalTransactionIdentifier = Encoding.UTF8.GetString(value.GetChildNode(0).Data);
                        break;

                    case 1704:
                        result.purchaseDate = TryParseDateTimeNode(value);
                        break;

                    case 1706:
                        result.originalPurchaseDate = TryParseDateTimeNode(value);
                        break;

                    case 1708:
                        result.subscriptionExpirationDate = TryParseDateTimeNode(value);
                        break;

                    case 1712:
                        result.cancellationDate = TryParseDateTimeNode(value);
                        break;

                    case 1707:
                        // looks like possibly a type?
                        result.productType = (int)Asn1Util.BytesToLong(value.GetChildNode(0).Data);
                        break;

                    case 1713:
                        // looks like possibly is_trial?
                        result.isFreeTrial = (int)Asn1Util.BytesToLong(value.GetChildNode(0).Data);
                        break;

                    case 1719:
                        result.isIntroductoryPricePeriod = (int)Asn1Util.BytesToLong(value.GetChildNode(0).Data);
                        break;

                    default:
                        break;
                    }
                }
            }
            return(result);
        }
    private void parseNodeRecursive(Asn1Node tNode)
    {
        bool processed_node = false;

        if ((tNode.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.SEQUENCE && tNode.ChildNodeCount == 3)
        {
            Asn1Node node1 = tNode.GetChildNode(0);
            Asn1Node node2 = tNode.GetChildNode(1);
            Asn1Node node3 = tNode.GetChildNode(2);
            if ((node1.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.INTEGER && (node2.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.INTEGER &&
                (node3.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.OCTET_STRING)
            {
                processed_node = true;
                int type = (int)Asn1Util.BytesToLong(node1.Data);
                switch (type)
                {
                case AppReceiptASN1TypeBundleIdentifier:
                    BundleIdentifier = getStringFromSubNode(node3);
                    break;

                case AppReceiptASN1TypeAppVersion:
                    AppVersion = getStringFromSubNode(node3);
                    break;

                case AppReceiptASN1TypeOpaqueValue:
                    break;

                case AppReceiptASN1TypeHash:
                    break;

                case AppReceiptASN1TypeOriginalAppVersion:
                    OriginalAppVersion = getStringFromSubNode(node3);
                    break;

                case AppReceiptASN1TypeReceiptExpirationDate:
                    break;

                case AppReceiptASN1TypeReceiptCreationDate:
                    ReceiptCreationDate = getDateTimeFromSubNode(node3);
                    break;

                case AppReceiptASN1TypeInAppPurchaseReceipt:
                {
                    if (node3.ChildNodeCount > 0)
                    {
                        Asn1Node node31 = node3.GetChildNode(0);
                        if ((node31.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.SET && node31.ChildNodeCount > 0)
                        {
                            AppleInAppPurchaseReceipt receipt = new AppleInAppPurchaseReceipt();
                            for (int i = 0; i < node31.ChildNodeCount; i++)
                            {
                                Asn1Node node311 = node31.GetChildNode(i);
                                if ((node311.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.SEQUENCE && node311.ChildNodeCount == 3)
                                {
                                    Asn1Node node3111 = node311.GetChildNode(0);
                                    Asn1Node node3112 = node311.GetChildNode(1);
                                    Asn1Node node3113 = node311.GetChildNode(2);
                                    if ((node3111.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.INTEGER && (node3112.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.INTEGER &&
                                        (node3113.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.OCTET_STRING)
                                    {
                                        int type1 = (int)Asn1Util.BytesToLong(node3111.Data);
                                        switch (type1)
                                        {
                                        case AppReceiptASN1TypeQuantity:
                                            receipt.Quantity = getIntegerFromSubNode(node3113);
                                            break;

                                        case AppReceiptASN1TypeProductIdentifier:
                                            receipt.ProductIdentifier = getStringFromSubNode(node3113);
                                            break;

                                        case AppReceiptASN1TypeTransactionIdentifier:
                                            receipt.TransactionIdentifier = getStringFromSubNode(node3113);
                                            break;

                                        case AppReceiptASN1TypePurchaseDate:
                                            receipt.PurchaseDate = getDateTimeFromSubNode(node3113);
                                            break;

                                        case AppReceiptASN1TypeOriginalTransactionIdentifier:
                                            receipt.OriginalTransactionIdentifier = getStringFromSubNode(node3113);
                                            break;

                                        case AppReceiptASN1TypeOriginalPurchaseDate:
                                            receipt.OriginalPurchaseDate = getDateTimeFromSubNode(node3113);
                                            break;

                                        case AppReceiptASN1TypeSubscriptionExpirationDate:
                                            receipt.SubscriptionExpirationDate = getDateTimeFromSubNode(node3113);
                                            break;

                                        case AppReceiptASN1TypeWebOrderLineItemID:
                                            receipt.WebOrderLineItemID = getIntegerFromSubNode(node3113);
                                            break;

                                        case AppReceiptASN1TypeCancellationDate:
                                            receipt.CancellationDate = getDateTimeFromSubNode(node3113);
                                            break;
                                        }
                                    }
                                }
                            }
                            if (!string.IsNullOrEmpty(receipt.ProductIdentifier))
                            {
                                PurchaseReceipts.Add(receipt.ProductIdentifier, receipt);
                            }
                        }
                    }
                }
                break;

                default:
                    processed_node = false;
                    break;
                }
            }
        }
        if (!processed_node)
        {
            for (int i = 0; i < tNode.ChildNodeCount; i++)
            {
                Asn1Node chld = tNode.GetChildNode(i);
                if (chld != null)
                {
                    parseNodeRecursive(chld);
                }
            }
        }
    }
        public DistinguishedName(Asn1Node n)
        {
            /* Name:
             * SET
             *   SEQ (attr)
             *     Object Identifier
             *     Printable String || UTF8String
             */
            if (n.MaskedTag == Asn1Tag.SEQUENCE)
            {
                for (int i = 0; i < n.ChildNodeCount; i++)
                {
                    Asn1Node tt = n.GetChildNode(i);
                    if (tt.MaskedTag != Asn1Tag.SET || tt.ChildNodeCount != 1)
                    {
                        throw new InvalidX509Data();
                    }

                    tt = tt.GetChildNode(0);
                    if (tt.MaskedTag != Asn1Tag.SEQUENCE || tt.ChildNodeCount != 2)
                    {
                        throw new InvalidX509Data();
                    }

                    Asn1Node oi  = tt.GetChildNode(0);
                    Asn1Node txt = tt.GetChildNode(1);

                    if (oi.MaskedTag != Asn1Tag.OBJECT_IDENTIFIER ||
                        !(
                            (txt.MaskedTag == Asn1Tag.PRINTABLE_STRING) ||
                            (txt.MaskedTag == Asn1Tag.UTF8_STRING) ||
                            (txt.MaskedTag == Asn1Tag.IA5_STRING)))
                    {
                        throw new InvalidX509Data();
                    }
                    var    xoid   = new LipingShare.LCLib.Asn1Processor.Oid();
                    string oiName = xoid.Decode(oi.Data);
                    var    enc    = new System.Text.UTF8Encoding();

                    switch (oiName)
                    {
                    case "2.5.4.6":                     // countryName
                        Country = enc.GetString(txt.Data);
                        break;

                    case "2.5.4.10":                     // organizationName
                        Organization = enc.GetString(txt.Data);
                        break;

                    case "2.5.4.11":                     // organizationalUnit
                        OrganizationalUnit = enc.GetString(txt.Data);
                        break;

                    case "2.5.4.3":                     // commonName
                        CommonName = enc.GetString(txt.Data);
                        break;

                    case "2.5.4.5":                     // serial number
                        SerialNumber = Asn1Util.ToHexString(txt.Data);
                        break;

                    case "2.5.4.46":                     // dnq
                        Dnq = enc.GetString(txt.Data);
                        break;

                    case "2.5.4.8":                     // state
                        State = enc.GetString(txt.Data);
                        break;
                    }
                }
            }
        }