15

我打算将一堆记录存储在一个文件中,然后用libsodium对每个记录进行签名。但是,我希望我的程序的未来版本能够检查当前版本所做的签名,反之亦然。

对于当前版本的 Sodium,使用 Ed25519 算法进行签名。我想默认原语可以在新版本的 Sodium 中发生变化(否则我认为 libsodium 不会公开选择特定原语的方法)。

我是不是该...

  1. 始终使用默认原语(即crypto_sign
  2. 使用特定的原语(即crypto_sign_ed25519
  3. 执行 (1),但将 的值存储sodium_library_version_major()在文件中(在专用的“钠版本”字段或通用“文件格式修订”字段中)并在当前运行的版本较低时退出
  4. 做(3),还要存储crypto_sign_primitive()
  5. 做(4),还要店crypto_sign_bytes()和朋友

...或者我应该完全做其他事情吗?

我的程序将用 C 语言编写。

4

2 回答 2

4

让我们首先确定一组可能的问题,然后尝试解决它。我们有一些数据(一条记录)和一个签名。可以使用不同的算法计算签名。程序可以进化和改变它的行为,libsodium 也可以(独立地)进化和改变它的行为。在签名生成方面,我们有:

  • crypto_sign(),它使用一些默认算法来产生签名(在写作的时候只是调用crypto_sign_ed25519()
  • crypto_sign_ed25519(),它根据特定ed25519算法生成签名

我假设对于一个给定相同输入数据和相同键的特定算法,我们将始终得到相同的结果,因为它是数学,并且任何与此规则的偏差都会使库完全无法使用。

让我们看一下两个主要选项:

  1. 一直在使用crypto_sign_ed25519(),从不改变这一点。一个不错的选择,因为它很简单,只要crypto_sign_ed25519()存在于 libsodium 中并且输出稳定,您就无需担心稳定的固定大小签名和零管理开销。当然,将来有人可能会发现该算法存在一些可怕的问题,如果您不准备更改可能对您来说意味着可怕问题的算法。
  2. 使用crypto_sign(). 有了这个我们突然有很多问题,因为算法可以改变,所以你必须存储一些元数据以及签名,这引发了一系列问题:
    • 要存储什么?
    • 这个元数据应该是记录级还是文件级?

对于第二种方法,我们在提到的功能中有什么?

  • sodium_library_version_major()是一个告诉我们库 API 版本的函数。它与支持/默认算法的更改没有直接关系,因此对我们的问题几乎没有用处。
  • crypto_sign_primitive()是一个函数,它返回一个字符串,用于标识crypto_sign(). 这是我们需要的完美匹配,因为据说它的输出会在算法发生变化的时候发生变化。
  • crypto_sign_bytes()是一个crypto_sign()以字节为单位返回签名大小的函数。这对于确定签名所需的存储量很有用,但如果算法发生变化,它很容易保持不变,所以它不是我们需要显式存储的元数据。

既然我们知道要存储什么,就有一个处理存储数据的问题。您需要获取算法名称并使用它来调用匹配验证功能。不幸的是,据我所见,libsodium 本身并没有提供任何简单的方法来获取给定算法名称(如EVP_get_cipherbyname()EVP_get_digestbyname()在 openssl 中)的正确函数,因此您需要自己制作一个(对于未知名称当然应该失败)。而且,如果您必须自己制作一个,则存储一些数字标识符而不是库中的名称可能会更容易(尽管有更多代码)。

现在让我们回到文件级与记录级。为了解决这个问题,还有两个问题要问——您能否在任何给定时间为旧记录生成新签名(这在技术上是否可行,政策是否允许)以及您是否需要将新记录附加到旧文件中?

如果您无法为旧记录生成新签名,或者您需要追加新记录并且不希望签名重新生成的性能损失,那么您没有太多选择,您需要:

  • 为您的签名提供动态大小字段
  • 存储用于生成签名的算法(动态字符串字段或内部(用于您的应用程序)ID)以及签名本身

如果您可以生成新签名,或者特别是如果您不需要附加新记录,那么当您将使用的算法存储在特殊文件级字段中时,如果签名算法发生变化,则可以使用更简单的文件级方法,在保存文件时重新生成所有签名(或在附加新记录时使用旧签名,这也是一个兼容性策略问题)。

其他选择?那么,有什么特别之处crypto_sign()呢?这是它的行为不受您的控制,libsodium 开发人员为您选择算法(毫无疑问他们选择了好的算法),但是如果您的文件结构中有任何版本控制信息(不是特定于签名的,我的意思是)没有什么能阻止您做出自己的特定选择,并在一个文件版本中使用一种算法,而在另一种文件版本中使用另一种算法(当然,在需要时使用转换代码)。同样,这也是基于您可以生成新签名并且策略允许的假设。

这让我们回到了最初的两个选择,问题是与仅使用crypto_sign_ed25519(). 这主要取决于您的程序寿命,我可能会说(只是作为一种观点)如果不到 5 年,那么只使用一种特定的算法会更容易。如果它很容易超过 10 年,那么不,你真的需要能够承受算法(甚至可能是整个加密库)的变化。

于 2016-08-08T15:14:11.123 回答
2

只需使用高级 API。

高级 API 中的函数不会使用不同的算法而不会影响库的主要版本。

在 libsodium 1.xy 中唯一可以期待的重大变化是删除了已弃用/未记录的函数(在使用--enable-minimalswitch 编译的当前版本中甚至不存在)。其他一切都将保持向后兼容。

新算法可能会在没有高级包装器的 1.xy 版本中引入,并将通过 libsodium 2 中的新高级 API 稳定和公开。

因此,不要打扰打电话crypto_sign_ed25519()。只需使用crypto_sign().

于 2016-10-16T17:34:20.227 回答