如何使用对象System.DirectoryServices.Protocols.BerConverter.Encode(“???”,myData)的BER编码 [英] How do I use BER encoding with object System.DirectoryServices.Protocols.BerConverter.Encode("???", myData)

查看:423
本文介绍了如何使用对象System.DirectoryServices.Protocols.BerConverter.Encode(“???”,myData)的BER编码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要对BER数据进行编码和解码。 .NET有类 System.DirectoryServices.Protocols.BerConverter



静态方法要求我输入一个字符串第一个参数如下所示

  byte [] oid = {0x30,0xD,0x6,0x9,0x2A,0x86,0x48, 0x86,0xF7,0xD,0x1,0x1,0x1,0x5,0x0}; //对象ID为RSA 

var result2 = System.DirectoryServices.Protocols.BerConverter.Decoding(?what goes here?,oid);

BER编码用于LDAP,证书,在其他许多格式中都是常见的。



我会很高兴有信息告诉我如何编码或解码这个类。堆栈溢出或Google(或Bing)的前几页没有任何内容。



问题




  • 如何使用BER解码将上面的字节数组转换为相应的OID?


  • 如何解析(或尝试解析)SubjectPublicKeyInfo ASN.1数据以DER或BER格式?


  • 似乎DER编码\decoding类是.NET框架的内部。如果是,他们在哪里? (我想请求connect.microsoft.com将这些成员公开)



解决方案


如何使用BER解码将上面的字节数组转换为相应的OID?


提取OID字节数组后,可以使用 OidByteArrayToString()将其转换为OID字符串。我已经包含下面的代码,因为我在.NET库中找不到类似的功能。


我如何解析(或尝试解析)DER或BER格式的SubjectPublicKeyInfo ASN.1数据?


我无法在中找到TLV解析器。 NET SDK。以下是BER TLV解析器的实现, BerTlv 。由于DER是BER的子集,因此解析将以相同的方式工作。给定BER-TLV byte [] 数组,它将返回支持子TLV访问的 BerTlv 对象的列表。


似乎DER编码\decoding类是.NET框架的内部。如果是,他们在哪里? (我想请求connect.microsoft.com让这些成员公开)


也许别人可以回答这个问题。 / p>

摘要



以下是使用以下提供的代码的示例。我使用您之前的帖子中提供的公开密钥数据。 BerTlv应该被扩充以支持像 BerTlv.getValue(rootTlvs,'/ 30/30/06');

 公共静态无效的主要(字符串[]参数)
{
串PUBKEY =MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz + QfiWYui / E9UGSXau / 2P8LjnTD8V4Unn + 2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP + sBK0VKeTATL2Yr / S3bT / XHY + 1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj / + XcwIDAQAB;
byte [] pubkeyByteArray = Convert.FromBase64String(pubkey);
列表< BerTlv> rootTlvs = BerTlv.parseTlv(pubkeyByteArray);

BerTlv firstTlv = rootTlvs.Where(tlv => tlv.Tag == 0x30).First(); //第一个序列(标签30)
BerTlv secondTlv = firstTlv.SubTlv。其中(tlv => tlv.Tag == 0x30).First(); //第二个序列(标签30)
BerTlv oid = secondTlv.SubTlv.Where(tlv => tlv.Tag == 0x06) .First(); // OID标签(标签30)

string strOid = OidByteArrayToString(oid.Value);
Console.WriteLine(strOid);
}

输出:


1.2.840.113549.1.1.1


OID编码/解码 / p>

  public static byte [] OidStringToByteArray(string oid)
{
string [] split = oid.Split ( '');
列表< byte> retVal = new List< byte>();

// root arc
if(split.Length> 0)
retVal.Add((byte)(Convert.ToInt32(split [0])* 40)) ;

// first arc
if(split.Length> 1)
retVal [0] + = Convert.ToByte(split [1]); (int i = 2; i< split.Length; i ++)
{
int arc_value = Convert.ToInt32(split [一世]);
堆栈< byte> bytes = new Stack< byte>();
while(arc_value!= 0)
{
字节val =(byte)((arc_value& 0x7F)|(bytes.Count == 0?0x0:0x80));
arc_value>> = 7;
bytes.Push(val);
}
retVal.AddRange(bytes);
}
return retVal.ToArray();
}

public static string OidByteArrayToString(byte [] oid)
{
StringBuilder retVal = new StringBuilder();

//第一个字节
if(oid.Length> 0)
retVal.Append(String.Format({0}。{1},oid [0 ] / 40,oid [0]%40));

//后续字节
int current_arc = 0; (int i = 1; i {
current_arc =(current_arc <= 7)|
oid [i]& 0x7F的;

//检查弧值的最后一个字节值
if((oid [i]& 0x80)== 0)
{
retVal.Append(' 。');
retVal.Append(Convert.ToString(current_arc));
current_arc = 0;
}
}

return retVal.ToString();
}

BER-TLV解析器

  class BerTlv 
{
private int tag;
private int length;
private int valueOffset;
private byte [] rawData;
私人列表< BerTlv> subTlv;

private BerTlv(int tag,int length,int valueOffset,byte [] rawData)
{
this.tag = tag;
this.length = length;
this.valueOffset = valueOffset;
this.rawData = rawData;
this.subTlv = new List< BerTlv>();
}
public int Tag
{
get {return tag; }
}
public byte [] RawData
{
get {return rawData; }
}
public byte [] Value
{
get
{
byte [] result = new byte [length];
Array.Copy(rawData,valueOffset,result,0,length);
返回结果;
}
}
public List< BerTlv> SubTlv
{
get {return subTlv; }
}
public static List< BerTlv> parseTlv(byte [] rawTlv)
{
列表< BerTlv> result = new List< BerTlv>();
parseTlv(rawTlv,result);
返回结果;
}
private static void parseTlv(byte [] rawTlv,List< BerTlv> result)
{
for(int i = 0,start = 0; i< rawTlv。 Length; start = i)
{
//解析标签
bool built_tlv =(rawTlv [i]& 0x20)!= 0;
bool more_bytes =(rawTlv [i]& 0x1F)== 0x1F;
while(more_bytes&&(rawTlv [++ i]& 0x80)!= 0);
i ++;

int tag = Util.getInt(rawTlv,start,i-start);

// parse Length
bool multiByte_Length =(rawTlv [i]& 0x80)!= 0;

int length = multiByte_Length? Util.getInt(rawTlv,i + 1,rawTlv [i]& 0x1F):rawTlv [i];
i = multiByte_Length? i +(rawTlv [i]& 0x1F)+ 1:i + 1;

i + = length;

byte [] rawData = new byte [i - start];
Array.Copy(rawTlv,start,rawData,0,i - start);
BerTlv tlv = new BerTlv(tag,length,i-length,rawData);
result.Add(tlv);

if(structured_tlv)
parseTlv(tlv.Value,tlv.subTlv);

}
}
}

一个包含上面类中使用的一些函数的实用程序类。为了清楚起见,它被包括在内。

  class Util 
{
public static string getHexString(byte [] arr)
{
StringBuilder sb = new StringBuilder(arr.Length * 2);
foreach(arr中的字节b)
{
sb.AppendFormat({0:X2},b);
}
return sb.ToString();
}
public static byte [] getBytes(String str)
{
byte [] result = new byte [str.Length>> 1]; (int i = 0; i< result.Length; i ++)
{
result [i] =(byte)Convert.ToInt32(str.Substring(i * 2,2 ),16);
}
返回结果;
}
public static int getInt(byte [] data,int offset,int length)
{
int result = 0; (int i = 0; i< length; i ++)
{
result =(result<< 8)|
数据[offset + i];
}
返回结果;
}
}


I need to encode and decode BER data. .NET has the class System.DirectoryServices.Protocols.BerConverter

The static method requires me to enter a string in the first parameter as shown below

        byte[] oid = { 0x30, 0xD, 0x6, 0x9, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0xD, 0x1, 0x1, 0x1, 0x5, 0x0 }; // Object ID for RSA

        var result2 = System.DirectoryServices.Protocols.BerConverter.Decoding("?what goes here?", oid);

BER encoding is used in LDAP, Certificates, and is commonplace in many other formats.

I'll be happy with information telling me how to Encode or Decode on this class. There is nothing on Stack Overflow or the first few pages of Google (or Bing) regarding this.

Question

  • How do I convert the byte array above to the corresponding OID using BER decoding?

  • How can I parse (or attempt to parse) SubjectPublicKeyInfo ASN.1 data in DER or BER format?

  • It seems the DER encoding\decoding classes are internal to the .NET framework. If so, where are they? (I'd like to ask connect.microsoft.com to make these members public)

解决方案

How do I convert the byte array above to the corresponding OID using BER decoding?

After you have extracted the OID byte array, you can convert it to an OID string using OidByteArrayToString(). I have included the code below, since I couldn't find a similar function in the .NET libraries.

How can I parse (or attempt to parse) SubjectPublicKeyInfo ASN.1 data in DER or BER format?

I was not able to find a TLV parser in the .NET SDK either. Below is an implementation of a BER TLV parser, BerTlv. Since DER is a subset of BER, parsing will work the same way. Given a BER-TLV byte[] array, it will return a list of BerTlv objects that support access of sub TLVs.

It seems the DER encoding\decoding classes are internal to the .NET framework. If so, where are they? (I'd like to ask connect.microsoft.com to make these members public)

Maybe somebody else can answer this question.

Summary

Here is an example of how you can use the code provided below. I have used the public key data you provided in your previous post. The BerTlv should probably be augmented to support querying like BerTlv.getValue(rootTlvs, '/30/30/06');.

public static void Main(string[] args)
{
    string pubkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB";
    byte[] pubkeyByteArray = Convert.FromBase64String(pubkey);
    List<BerTlv> rootTlvs = BerTlv.parseTlv(pubkeyByteArray);

    BerTlv firstTlv = rootTlvs.Where(tlv => tlv.Tag == 0x30).First();//first sequence (tag 30)
    BerTlv secondTlv = firstTlv.SubTlv.Where(tlv => tlv.Tag == 0x30).First();//second sequence (tag 30)
    BerTlv oid = secondTlv.SubTlv.Where(tlv => tlv.Tag == 0x06).First();//OID tag (tag 30)

    string strOid = OidByteArrayToString(oid.Value);
    Console.WriteLine(strOid);
}

Output:

1.2.840.113549.1.1.1

OID Encode/Decode

public static byte[] OidStringToByteArray(string oid)
{
    string[] split = oid.Split('.');
    List<byte> retVal = new List<byte>();

    //root arc
    if (split.Length > 0)
        retVal.Add((byte)(Convert.ToInt32(split[0])*40));

    //first arc
    if (split.Length > 1)
        retVal[0] += Convert.ToByte(split[1]);

    //subsequent arcs
    for (int i = 2; i < split.Length; i++)
    {
        int arc_value = Convert.ToInt32(split[i]);
        Stack<byte> bytes = new Stack<byte>();
        while (arc_value != 0)
        {
            byte val = (byte) ((arc_value & 0x7F) | (bytes.Count == 0 ? 0x0:0x80));
            arc_value >>= 7;
            bytes.Push(val);
        }
        retVal.AddRange(bytes);
    }
    return retVal.ToArray();
}

public static string OidByteArrayToString(byte[] oid)
{
    StringBuilder retVal = new StringBuilder();

    //first byte
    if (oid.Length > 0)
        retVal.Append(String.Format("{0}.{1}", oid[0] / 40, oid[0] % 40));

    // subsequent bytes
    int current_arc = 0;
    for (int i = 1; i < oid.Length; i++)
    {
        current_arc = (current_arc <<= 7) | oid[i] & 0x7F;

        //check if last byte of arc value
        if ((oid[i] & 0x80) == 0)
        {
            retVal.Append('.');
            retVal.Append(Convert.ToString(current_arc));
            current_arc = 0;
        }
    }

    return retVal.ToString();
}

BER-TLV Parser

class BerTlv
{
    private int tag;
    private int length;
    private int valueOffset;
    private byte[] rawData;
    private List<BerTlv> subTlv;

    private BerTlv(int tag, int length, int valueOffset, byte[] rawData)
    {
        this.tag = tag;
        this.length = length;
        this.valueOffset = valueOffset;
        this.rawData = rawData;
        this.subTlv = new List<BerTlv>();
    }
    public int Tag
    {
        get { return tag; }
    }
    public byte[] RawData
    {
        get { return rawData; }
    }
    public byte[] Value
    {
        get
        {
            byte[] result = new byte[length];
            Array.Copy(rawData, valueOffset, result, 0, length);
            return result;
        }
    }
    public List<BerTlv> SubTlv
    {
        get { return subTlv; }
    }
    public static List<BerTlv> parseTlv(byte[] rawTlv)
    {
        List<BerTlv> result = new List<BerTlv>();
        parseTlv(rawTlv, result);
        return result;
    }
    private static void parseTlv(byte[] rawTlv, List<BerTlv> result)
    {
        for (int i = 0, start=0; i < rawTlv.Length; start=i)
        {
            //parse Tag
            bool constructed_tlv = (rawTlv[i] & 0x20) != 0;
            bool more_bytes = (rawTlv[i] & 0x1F) == 0x1F;
            while (more_bytes && (rawTlv[++i] & 0x80) != 0) ;
            i++;

            int tag = Util.getInt(rawTlv, start, i-start);

            //parse Length
            bool multiByte_Length = (rawTlv[i] & 0x80) != 0;

            int length = multiByte_Length ? Util.getInt(rawTlv, i+1, rawTlv[i] & 0x1F) : rawTlv[i];
            i = multiByte_Length ? i + (rawTlv[i] & 0x1F) + 1: i + 1;

            i += length;

            byte[] rawData = new byte[i - start];
            Array.Copy(rawTlv, start, rawData, 0, i - start);
            BerTlv tlv = new BerTlv(tag, length, i - length, rawData);
            result.Add(tlv);

            if (constructed_tlv)
                parseTlv(tlv.Value, tlv.subTlv);

        }
    }
}

Here is a utility class that contains some functions used in the class above. It is included for the sake of clarity how it works.

class Util
{
    public static string getHexString(byte[] arr)
    {
        StringBuilder sb = new StringBuilder(arr.Length * 2);
        foreach (byte b in arr)
        {
            sb.AppendFormat("{0:X2}", b);
        }
        return sb.ToString();
    }
    public static byte[] getBytes(String str)
    {
        byte[] result = new byte[str.Length >> 1];
        for (int i = 0; i < result.Length; i++)
        {
            result[i] = (byte)Convert.ToInt32(str.Substring(i * 2, 2), 16);
        }
        return result;
    }
    public static int getInt(byte[] data, int offset, int length)
    {
        int result = 0;
        for (int i = 0; i < length; i++)
        {
            result = (result << 8) | data[offset + i];
        }
        return result;
    }
}

这篇关于如何使用对象System.DirectoryServices.Protocols.BerConverter.Encode(“???”,myData)的BER编码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆