在不同编程语言之间传递加密数据的最佳实践

时间:2013-01-09 20:55:50

标签: encryption language-agnostic

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

我正在尝试确定一般有用的最佳做法,无论使用何种加密算法。为了在跨不同语言和平台加密和解密数据时最大限度地提高兼容性,我想对以下步骤进行批评:

加密

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

解密:

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

4 个答案:

答案 0 :(得分:2)

你的前提是正确的,但在某些方面它比这更容易。现代加密算法意味着与语言无关,如果您使用相同的键具有相同的输入,则应获得相同的结果。

对于大多数密码和some modes,数据确实需要固定长度。转换为十六进制不会这样做,因为数据需要以固定边界结束。例如,对于AES,如果要加密4个字节,则需要将其填充为16个字节,这是十六进制表示不能执行的。幸运的是,这很可能发生在您最终使用的加密API中,使用标准padding schemes之一。由于您没有标记语言,因此.NET支持的AesManaged类的填充模式为here's a list

另一方面,正确加密数据需要的不仅仅是字节编码。您需要选择正确的操作模式(首选CBC或CTR),然后提供某种类型的message integrity。仅加密并不能防止篡改数据。如果您想简化一些事情,那么请查看类似GCM的模式,它可以处理机密性和完整性。

您的方案应该类似于:

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

解密:

  • 如果将字节数组存储为Base64字符串convert back到字节数组。
  • 将加密的字节数组解密为纯文本
  • 验证生成的身份验证标记是否与存储的身份验证标记匹配
  • 将字节数组转换为纯文本字符串。

答案 1 :(得分:0)

  

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

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

  

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

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

一般来说,是的,隐喻算法会将输入分解为固定大小的块。如果最后一个块未满,那么它们可以用任意字节填充结尾以获得完整的块。为了区分填充数据和最后恰好具有类似填充字节的数据,它们将前缀或附加纯文本的长度添加到字节流中。

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

  

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

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

  

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

     

<强>加密

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

<强>解密:

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

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

以您选择的方式将字节数组传输到另一个程序。

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

答案 2 :(得分:0)

加密的最佳做法是使用高级加密框架,使用基元时,你可以做很多事情。如果您不使用高级加密框架,mfanto可以很好地提及您需要知道的重要事项。而且我猜测,如果你试图最大化编程语言的兼容性,那是因为你需要其他开发人员与加密互操作,然后他们需要学习使用加密的低级细节。

所以我对高级框架的建议是使用Google Keyczar框架,因为它会为您处理细节,算法,密钥管理,填充,iv,身份验证标记,有线格式。它适用于许多不同的节目Java, Python, C++C#Go。看看吧。

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

答案 3 :(得分:0)

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