RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1294635
Accepted
User12351259599491
User12351259599491
Asked:2022-06-13 05:50:11 +0000 UTC2022-06-13 05:50:11 +0000 UTC 2022-06-13 05:50:11 +0000 UTC

为什么需要 byte[] 数组?

  • 772

主题。
我经常在示例中看到如何使用 byte[],例如,在发送 POST 请求时。
我不明白为什么需要这样做,它是低级编程的雏形吗?
据我所知,String 是一个 Char 数组,每个字符在内存中由其 ASCII 码表示,当这个字符串转换为 byte[] 时会发生什么?
例如,这用于发送 POST 请求,但另一方面,控制器接受开箱即用的模型并立即创建对象。Microsoft 建议在新开发中使用 TPL 而不是 Thread,因为 Thread 级别较低。
TPL 将线程外包给 CLI,为什么不对 byte[] 做同样的事情呢?
基本上,我很困惑。

使用字节数组对我来说似乎很奇怪的示例
https://docs.microsoft.com/ru-ru/dotnet/standard/security/encrypting-data

class Class1
{
    static void Main()
    {
        //Initialize the byte arrays to the public key information.
        byte[] modulus =
        {
            214,46,220,83,160,73,40,39,201,155,19,202,3,11,191,178,56,
            74,90,36,248,103,18,144,170,163,145,87,54,61,34,220,222,
            207,137,149,173,14,92,120,206,222,158,28,40,24,30,16,175,
            108,128,35,230,118,40,121,113,125,216,130,11,24,90,48,194,
            240,105,44,76,34,57,249,228,125,80,38,9,136,29,117,207,139,
            168,181,85,137,126,10,126,242,120,247,121,8,100,12,201,171,
            38,226,193,180,190,117,177,87,143,242,213,11,44,180,113,93,
            106,99,179,68,175,211,164,116,64,148,226,254,172,147
        };

        byte[] exponent = { 1, 0, 1 };

        //Create values to store encrypted symmetric keys.
        byte[] encryptedSymmetricKey;
        byte[] encryptedSymmetricIV;

        //Create a new instance of the RSA class.
        RSA rsa = RSA.Create();

        //Create a new instance of the RSAParameters structure.
        RSAParameters rsaKeyInfo = new RSAParameters();

        //Set rsaKeyInfo to the public key values.
        rsaKeyInfo.Modulus = modulus;
        rsaKeyInfo.Exponent = exponent;

        //Import key parameters into rsa.
        rsa.ImportParameters(rsaKeyInfo);

        //Create a new instance of the default Aes implementation class.
        Aes aes = Aes.Create();

        //Encrypt the symmetric key and IV.
        encryptedSymmetricKey = rsa.Encrypt(aes.Key, RSAEncryptionPadding.Pkcs1);
        encryptedSymmetricIV = rsa.Encrypt(aes.IV, RSAEncryptionPadding.Pkcs1);
    }
}

公钥只是一个数字,为​​什么是字节?

这是一个来自 metanit 的示例,发送 POST 请求,为什么我在这里将字符串转换为字节?不好,我知道该方法接受一个字节数组,但为什么它不能只接受一个字符串并用它做所有需要的事情呢?

            WebRequest request = WebRequest.Create("https://localhost:44391/api/Order/");
            request.Method = "POST"; // для отправки используется метод Post
                                     // данные для отправки
            string data = _data;
            // преобразуем данные в массив байтов
            byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(data);
            // устанавливаем тип содержимого - параметр ContentType
            request.ContentType = "application/json";
            // Устанавливаем заголовок Content-Length запроса - свойство ContentLength
            request.ContentLength = byteArray.Length;

            //записываем данные в поток запроса
            using (Stream dataStream = request.GetRequestStream())
            {
                dataStream.Write(byteArray, 0, byteArray.Length);
            }

            WebResponse response = await request.GetResponseAsync();
            using (Stream stream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(stream))
                {
                    d = reader.ReadToEnd();
                }
            }
            response.Close();
c#
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. Best Answer
    aepot
    2022-06-13T07:08:13Z2022-06-13T07:08:13Z

    String 是一个 Char 数组,每个字符在内存中用自己的 ASCII 码表示

    不正确,string作为双字节char编码的 UTF-16 序列而不是 ASCII 存储在内存中。

    没有人强迫您手动转码为字节数组,尤其是在您使用现代网络 API 的情况下。WebRequest过时了,更是如此。

    private static readonly HttpClient client = new HttpClient();
    
    public async Task<string> PostJsonAsync(string url, string json)
    {
        using HttpContent content = new StringContent(json, Encoding.UTF8, "application/json");
        using var response = await client.PostAsync(url, content);
        return await response.Content.ReadAsStringAsync();
    }
    

    看 - 我没有重新编码任何东西。但这并不意味着不会发生重新编码。它只是隐藏在 .NET 代码中的某个地方。

    该字符串以 UTF-16 格式存储在内存中,并以 UTF-8 格式发送。在什么地方,字符串以字节的形式存储在内存中,并以字节的形式发送。我们都知道只有字节,内存中只能有字节。与通信通道一样,只能发送或接收字节。只是.NET很方便,不需要手动转码。

    是否可以在string不“按原样”重新编码的情况下发送?这很容易,但您需要 .NET Core 或 .NET 5,因为在较旧的框架中,您必须在不安全的代码周围摇摆不定才能使其正确。

    您当然可以通过Encoding.Unicode.GetBytes(text),但为了清楚起见,我不会使用它,尽管字节数组中的结果是相同的。

    string text = "Hello World";
    ReadOnlySpan<byte> bytes = MemoryMarshal.Cast<char, byte>(text);
    using HttpContent content = new ByteArrayContent(bytes.ToArray());
    // и далее то же самое как выше
    

    如果构造函数ByteArrayContent将其作为参数ReadOnlySpan,则可以将字符串内存的内容直接发送到网络,不仅无需转换,甚至无需“按原样”复制数据。当然,您可以通过StreamContent创建自己的Stream直接从 读取内存的方法来绕过这个限制string,但这会变成很多代码,只是为了证明这是可能的,我不会写它。


    关于为什么要将数字转换为字节,它是类型和字节。好吧,例如,有Int32- 4 个字节。由于它Socket只能发送字节,为了通过网络发送这个数字,您需要将其转换为字节。如果你真的变态,你可以像使用字符串一样,通过读取这个 Int32 所在的那个 RAM 单元的内容来发送这些字节。的确,有一个问题,在某些情况下,某个具有相同int的局部变量可能根本不在内存中,例如,存储在处理器寄存器中,并且只能通过网络发送内存,因此,作为通过网络发送的数据源,并使用字节数组作为指向 .NET 中包含数据的一块内存的最原始指针。


    至于密码学。.NET 中作为原语的最长整数Int64是 8 个字节。而代表密钥和其他加密数据的 8 个字节甚至都不好笑。即使是古老的 MD5 哈希也是 16 个字节。然后可以轻松清除字节数组,及时从内存中清除秘密数据。顺便说一句,正是因为字符串string不能被清除(它不是可变的)——不建议在其中存储用于加密的密钥或密码。因此,在密码学中,数组无处不在。顺便说一句,我最近为Apache MD5密码加密算法写了代码,所以我很痛苦以尽量减少来回复制内存中的字节,至少为了性能,相同的跨度Span<T>/在这方面帮助了我很多ReadOnlySpan<T>.

    • 7
  2. VladD
    2022-06-13T07:05:52Z2022-06-13T07:05:52Z

    你的问题分为两部分。

    首先,关于密码学。这里将键表示为数字,虽然可能,但不会给出任何东西。对于我们这些密码学用户来说,所有的工作都是关于转换字节集。我们不使用加法/乘法功能,也不使用加密密钥或加密消息的十进制表示。事实上,密码学适用于字节集,数字允许我们进行的额外操作只会导致“如果我们添加两个密钥会发生什么”的问题。等等

    尽管键可以表示为容量足够大的数字,但这没有意义,就像将文件表示为数字没有意义一样。

    关于第二部分,你是对的,你引用的 API 有点过时了。现在习惯上这样写:

    var client = new HttpClient() { BaseAddress = new Uri("http://httpbin.org") };
    var request = new RequestObject(...);
    var result = await client.PostAsJsonAsync("/post", request);
    var reply = await result.Content.ReadFromJsonAsync<Response>();
    

    如您所见,将对象序列化为 JSON 和编写正确HttpContent的 'a 等细节隐藏在方便的扩展方法后面,这些方法为您做所有事情。

    但是,如果您愿意,没有人会剥夺您的低级能力和完全控制权,您可以HttpContent自己编写。

    • 6
  3. Roman-Stop RU aggression in UA
    2022-06-13T07:29:55Z2022-06-13T07:29:55Z

    让我们先考虑一个更简单的例子。您想通过网络发送 Int32 或将其写入文件。当您使用抽象数据类型 Int32 时,作为程序员的您并不关心它在内存中的精确表示方式。这是一个可能因平台而异的实现细节。它可以采用什么值以及它支持什么操作对你来说很重要。

    历史上发生过这种情况(稍后会详细介绍),只能通过网络发送字节。简单地从内存中以字节为单位复制 Int32 表示并通过网络发送它会导致接收端出现问题。但是如果接收方有不同的表示 Int32 的方式呢?可能根本没有 .NET 应用程序,而是只能使用字节的 8 位微控制器。这是通过网络发送字节的原因之一——为了互操作性,即 不同系统的兼容性。字节被用作所有操作系统都能理解的最小元素。

    也就是说,问题在于可以用 4 个字节的形式表示一个 32 位 int,而不是用一种方式,而是至少用两种方式,它们的字节顺序不同。并且您需要指定要选择哪种方法。在这里,您将抽象类型 Int32 编码为字节。接收方和发送方必须就如何解释通过网络传输或存储在文件中的字节流达成一致。

    使用字符串,完全相同的问题,只是更糟。首先,字符串本身是一个比数字还要抽象的东西(一定范围内的数字至少可以直接存入内存)。字符串由字符组成,字符不能直接存储在内存中,可以用一些字节序列对其进行编码。再一次,你编码的方式是一个实现细节。

    就像 Int32 一样,您不能简单地通过网络发送字符串,您只能发送使用某种编码方法转换为字节的字符串。在这里,编程语言和/或库可以提供一种手段,如其他答案中所示,使生活更轻松而不进行手动转码,但指定编码(显式或隐式)将是必要的。

    • 3

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5