3

我已经读过,如果您想使用一种编程语言加密字符串并使用另一种编程语言解密该字符串,那么为了确保兼容性,最好在进行加密之前进行一些转换。我已经读过加密字符串的字节数组而不是字符串本身是最佳实践。另外,我读过某些加密算法期望每个加密数据包的大小是固定的。如果要加密的最后一个数据包不是所需的大小,则加密将失败。因此,对首先转换为固定长度(例如十六进制)的数据进行加密似乎是个好主意。

无论使用何种加密算法,我都试图找出通常有用的最佳实践。为了在跨不同语言和平台加密和解密数据时最大限度地提高兼容性,我想对以下步骤作为一个过程进行批评:

加密:

  • 以纯文本字符串开头
  • 将纯文本字符串转换为字节数组
  • 将字节数组转换为十六进制
  • 将十六进制加密为加密字符串
  • 以加密字符串结尾

解密:

  • 以加密字符串开头
  • 将加密字符串解密为十六进制
  • 将十六进制转换为字节数组
  • 将字节数组转换为纯文本字符串
  • 以纯文本字符串结尾
4

4 回答 4

2

你的前提是正确的,但在某些方面它比这更容易一些。现代加密算法旨在与语言无关,如果您有相同的输入和相同的密钥,您应该得到相同的结果。

确实,对于大多数密码和某些模式,数据需要是固定长度的。转换为十六进制不会这样做,因为数据需要在固定边界上结束。以 AES 为例,如果要加密 4 个字节,则需要将其填充到 16 个字节,而十六进制表示则无法做到这一点。幸运的是,这很可能发生在您最终使用的加密 API 中,其中一种是标准填充方案。由于您没有标记语言,因此这里列出了 .NET 中的 AesManaged 类支持的填充模式。

另一方面,正确加密数据需要的不仅仅是字节编码。您需要选择正确的操作模式(首选 CBC 或 CTR),然后提供某种类型的消息完整性。单独的加密并不能防止数据被篡改。如果你想稍微简化一下,那么看看像GCM这样的模式,它同时处理机密性和完整性。

您的方案应如下所示:

  • 将纯文本转换为字符串到字节数组。有关字符编码的重要说明,请参阅@rossum 的评论。
  • 生成随机对称密钥或使用PBKDF2将密码转换为密钥
  • 生成用于 GCM 的随机 IV/nonce
  • 加密字节数组并将其与身份验证标签一起存储
  • 您可能希望将字节数组存储为Base64 字符串

对于解密:

  • 如果您将字节数组存储为 Base64 字符串,请转换回字节数组。
  • 将加密的字节数组解密为明文
  • 验证生成的身份验证标签与存储的身份验证标签匹配
  • 将字节数组转换为纯文本字符串。
于 2013-01-09T21:13:53.757 回答
2

实际上,加密的最佳实践是使用高级加密框架,使用原语可能会做很多错误的事情。如果您不使用高级加密框架,mfanto 可以很好地提及您需要知道的重要事项。我猜如果你想最大化跨编程语言的兼容性,那是因为你需要其他开发人员与加密进行互操作,然后他们也需要学习使用加密的低级细节。

所以我对高级框架的建议是使用 Google Keyczar框架,因为它为您处理算法、密钥管理、填充、iv、身份验证标签、有线格式的所有细节。它存在于许多不同的编程Java、Python、C++C#Go中。一探究竟。

我编写了 C# 版本,所以我可以告诉你它在幕后使用的原语在大多数其他编程语言中也广泛使用,并且它使用 json 等标准进行密钥管理和存储。

于 2013-01-10T14:16:33.250 回答
1

我为此目的使用HashIds 。它很简单并且支持广泛的编程语言。每当我们需要解密目标中的数据时,我们都会使用它在我们的 PHP、Node.js 和 Golang 微服务之间传递加密数据。

于 2019-02-12T16:42:21.630 回答
0

我已经读过加密字符串的字节数组而不是字符串本身是最佳实践。

加密算法通常适用于字节数组或字节流,所以是的。您不直接加密对象(字符串),而是加密它们的字节表示。

另外,我读过某些加密算法期望每个加密数据包的大小是固定的。如果要加密的最后一个数据包不是所需的大小,则加密将失败。

这是您选择的特定加密算法的实现细节。这实际上取决于算法的 API 接口是什么。

一般来说,是的,加密算法会将输入分解为固定大小的块。如果最后一个块未满,那么他们可能会用任意字节填充末尾以获得完整块。为了区分填充数据和恰好在末尾具有看起来像填充字节的数据,它们会将纯文本的长度预先或附加到字节流中。

这是不应该留给用户的那种细节,一个好的加密库会为你处理这些细节。理想情况下,您只想输入纯文本字节并在另一端获取加密字节。

因此,对首先转换为固定长度(例如十六进制)的数据进行加密似乎是个好主意。

将字节转换为十六进制不会使其长度固定。它的大小加倍,但这不是固定的。它使它成为 ASCII 安全的,因此它可以很容易地嵌入到文本文件和电子邮件中,但这与这里无关。(而且 Base64 是比十六进制更好的二进制→ASCII 编码。)

为了确定确保与跨不同语言和平台加密和解密数据的兼容性的最佳实践,我想对以下步骤作为一个过程进行批评:

加密:

  • 纯文本字符串
  • 将纯文本字符串转换为字节数组
  • 将字节数组转换为十六进制
  • 将十六进制加密为加密字符串
  • 加密字符串
  • 纯文本字节数组到加密字节数组

解密:

  • 加密字符串
  • 将加密字符串解密为十六进制
  • 将十六进制转换为字节数组
  • 加密字节数组
  • 将加密字节数组解密为纯文本字节数组
  • 将字节数组转换为纯文本字符串
  • 纯文本字符串

要加密,请将纯文本字符串转换为其字节表示,然后加密这些字节。结果将是一个加密的字节数组。

以您选择的方式将字节数组传输到其他程序。

要解密,请将加密的字节数组解密为纯文本字节数组。从这个字节数组构造你的字符串。完毕。

于 2013-01-09T21:10:38.397 回答