【问题标题】:Given the object identifier, how do we read the corresponding value from a ASN.1 DER encoded binary file?给定对象标识符,我们如何从 ASN.1 DER 编码的二进制文件中读取相应的值?
【发布时间】:2015-11-26 08:48:47
【问题描述】:

我正在尝试从 Microsoft 安全目录 (*.cat) 文件中读取与对象标识符对应的值,该文件实际上是一个 DER 编码的 ASN.1 对象。我正在使用充气城堡来创建 Asn1Object。当我执行 .ToString() 时,我可以在转储文本中看到我的 ASCII 数据,针对对象标识符“1.3.6.1.4.1.311.12.2.1”,但是有没有办法通过传递这个 OID 来专门检索数据?

我看到一个类 Org.BouncyCastle.Asn1.Microsoft,但我不知道如何使用这个类。任何帮助表示赞赏!到目前为止,我只有这个,我调用 File.ReadAllBytes 并传递给我在下面编写的函数,在此我可以调用 ToString() 并查看 .cat 中的所有数据

private Asn1Object asn1Object(byte[] data)
        {                
                Asn1InputStream asn1InputStream = new Asn1InputStream(data);

                if(asn1InputStream != null)
                {
                    return asn1InputStream.ReadObject().;
                }
                else
                {
                    return null;
                }

        }

【问题讨论】:

    标签: c# x509certificate bouncycastle asn.1 der


    【解决方案1】:

    简短的回答:您需要递归地遍历树以找到包含 DerObjectIdentifier 的 DerSequence,然后返回 DerObjectIdentifiers 的下一个兄弟。

    长答案:查看 ASN1/DER 结构,对象图中似乎没有一个条目具有 OID 和值。似乎对于特定的 OID,它将是 DerSequence 中的第一个子对象,而值将是第二个子对象。

    一种递归方法,它将找到包含与您的 OID 匹配的 DerObjectIdentifier 的 DerSequence 并返回下一个兄弟:

    public static Asn1Object FindAsn1Value(string oid, Asn1Object obj)
    {
        Asn1Object result = null;
        if (obj is Asn1Sequence)
        {
            bool foundOID = false;
            foreach (Asn1Object entry in (Asn1Sequence)obj)
            {
                var derOID = entry as DerObjectIdentifier;
                if (derOID != null && derOID.Id == oid)
                {
                    foundOID = true;
                }
                else if (foundOID)
                {
                    return entry;
                } 
                else
                {
                    result = FindAsn1Value(oid, entry);
                    if (result != null)
                    {
                        return result;
                    }
                }
            }
        }
        else if (obj is DerTaggedObject)
        {
            result = FindAsn1Value(oid, ((DerTaggedObject)obj).GetObject());
            if (result != null)
            {
                return result;
            }
        }
        else
        {
            if (obj is DerSet)
            {
                foreach (Asn1Object entry in (DerSet)obj)
                {
                    result = FindAsn1Value(oid, entry);
                    if (result != null)
                    {
                        return result;
                    }
                }
            }
        }
        return null;
    }
    

    要调用它,您将使用您提供的方法加载 Asn1Object,然后调用上面显示的 FindAsn1Value。这应该会返回您所追求的 Asn1Object(在我的测试 cat 文件的情况下,此值为 DerOctetString)。

    Asn1Object asn = asn1Object(File.ReadAllBytes(@"test_file.cat"));
    
    Asn1Object value = FindAsn1Value("1.3.6.1.4.1.311.12.2.1", asn);
    if (value is DerOctetString)
    {
        UnicodeEncoding unicode = new UnicodeEncoding(true, true);
        Console.WriteLine("DerOctetString = {0}", unicode.GetString(((DerOctetString)value).GetOctets()));
    }
    

    我不确定该 OID 的值是否始终为 DerOctetString,也不确定我的解码选择是否一定正确,但它为我提供了我的测试正在使用的值的最易读版本。

    更新

    如果相同的 OID 在层次结构中出现多次,并且您需要返回所有可能的值,则可以使用另一种方法:

    public static List<Asn1Object> FindAsn1Values(string oid, Asn1Object obj)
    {
        Asn1Object result = null;
        List<Asn1Object> results = new List<Asn1Object>();
        if (obj is Asn1Sequence)
        {
            bool foundOID = false;
            foreach (Asn1Object entry in (Asn1Sequence)obj)
            {
                var derOID = entry as DerObjectIdentifier;
                if (derOID != null && derOID.Id == oid)
                {
                    foundOID = true;
                }
                else if (foundOID)
                {
                    results.Add(entry);
                } 
                else
                {
                    result = FindAsn1Values(oid, entry);
                    if (result.Count > 0)
                    {
                        results.AddRange(result);
                    }
                }
            }
        }
        else if (obj is DerTaggedObject)
        {
            result = FindAsn1Values(oid, ((DerTaggedObject)obj).GetObject());
            if (result.Count > 0)
            {
                results.AddRange(result);
            }
        }
        else
        {
            if (obj is DerSet)
            {
                foreach (Asn1Object entry in (DerSet)obj)
                {
                    result = FindAsn1Values(oid, entry);
                    if (result.Count > 0)
                    {
                        results.AddRange(result);
                    }
                }
            }
        }
        return results;
    }
    

    【讨论】:

    • 返回的对象是一个 DerSet 对象。另外,有没有办法读取具有相同 OID 的下一个字段?我在 cat 中看到 6 个具有相同 OID 的字段,而我恰好需要第三个。
    • 此外,DerSet 对象没有实现 GetOctets 方法。 :(
    • 如果有多个相同的 OID,则与其返回单个结果,不如返回一个 List 以获取该 OID 的可能值。我将使用该替代方法更新我的答案。至于结果是 DerSet,这是 Asn1Object 的集合,您必须遍历它们以了解它们包含的内容。
    猜你喜欢
    • 2011-08-21
    • 2010-11-19
    • 2022-01-22
    • 2015-12-10
    • 1970-01-01
    • 2013-11-17
    • 2019-01-06
    • 2013-10-14
    • 2011-04-07
    相关资源
    最近更新 更多