微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Botan MC-Eliece实施由于不推荐的实施示例而失败

如何解决Botan MC-Eliece实施由于不推荐的实施示例而失败

我在Botan加密库中的c ++ mc-eliece实现中遇到问题。在整个互联网中,实际上似乎只有一个例子,并带有链接

https://www.cryptosource.de/docs/mceliece_in_botan.pdf

但是这个示例已有6年历史了,因此它已经完全过时了,Botan文档没有提供其他任何内容

问题基本上是,不幸的是,函数名和规范随时间而改变,因此在尝试使用它们时遇到了一些编译器错误。通过查看标头实现,我设法使其中的一些神秘化。但坦率地说,现在我在墙前。

任何熟悉Botan MC-Eliece实现的人都可以给我一个提示,即如何调用当前函数

这是我的带有标记代码。我删除了许多不必要的代码和其他实现,以使其更具可读性。如果没有必要的模块,您也将无法使它运行,但是我将尝试以某种方式将其写下来,使得拥有Botan库的人应该能够运行它。

//to compile: g++ -o mc_eliece mc_eliece.cpp -Wall -I/usr/local/include/botan-2/ -I/home/pi/projects/RNG_final/ -ltss2-esys -ltss2-rc -lbotan-2

#include <iostream>
#include <botan/rng.h>
#include <botan/system_rng.h>
#include <botan/mceies.h>
#include <botan/mceliece.h>

int main() {

   Botan::size_t n = 1632; // Parameters for key generation
   Botan::size_t t = 33;


   // initialize  RNG type
   Botan::System_RNG rng; // is a standard Botan RNG


   // create a new MCEliece private key with code length n and error weigth t  
   Botan::McEliece_PrivateKey sk1(rng,n,t);  // actually works!


   // derive the corresponding public key
   Botan::McEliece_PublicKey pk1(*dynamic_cast<Botan::McEliece_PublicKey*>(&sk1)); // actually works!


   // encode the public key
   std::vector<uint8_t> pk_enc = pk1.subject_public_key(); // actually works!


   // encode the private key
   Botan::secure_vector<uint8_t> sk_enc = sk1.private_key_bits(); // had to replace sk1.pkcs8_private_key()


   // encryption side: decode a serialized public key
   Botan::McEliece_PublicKey pk(pk_enc);
   McEliece_KEM_Encryptor enc(pk); // does not work,can't find a working corresponding function in the header


   // perform encryption -> will find out if it works after upper case had been solved
   std::pair<secure_vector<Botan::byte>,secure_vector<Botan::byte> > ciphertext__sym_key = enc.encrypt(rng);
   secure_vector<Botan::byte> sym_key_encr = ciphertext__sym_key.second;
   secure_vector<Botan::byte> ciphertext = ciphertext__sym_key.first;


   // code used at the decrypting side: -> will find out if it works after upper case had been solved
   // decode a serialized private key
   McEliece_PrivateKey sk(sk_enc);
   McEliece_KEM_Decryptor dec(sk);
   
   
   // perform decryption -> will find out if it works after upper case had been solved
   secure_vector<Botan::byte> sym_key_decr = dec.decrypt(&ciphertext[0],ciphertext.size() );

   // both sides Now have the same 64-byte symmetric key.
   // use this key to instantiate an authenticated encryption scheme.
   // in case shorter keys are needed,they can simple be cut off.

   return 0;
}

请提前寻求帮助。

解决方法

McEliece单元测试可以作为参考(link)。

基于该代码,您的示例可以按以下方式重写:

#include <botan/auto_rng.h>
#include <botan/data_src.h>
#include <botan/hex.h>
#include <botan/mceies.h>
#include <botan/mceliece.h>
#include <botan/pkcs8.h>
#include <botan/pubkey.h>
#include <botan/x509_key.h>

#include <cassert>
#include <iostream>

int main() {

  // Parameters for McEliece key
  // Reference: https://en.wikipedia.org/wiki/McEliece_cryptosystem#Key_sizes
  Botan::size_t n = 1632;
  Botan::size_t t = 33;

  // Size of the symmetric key in bytes
  Botan::size_t shared_key_size = 64;

  // Key-derivation function to be used for key encapsulation
  // Reference: https://botan.randombit.net/handbook/api_ref/kdf.html
  std::string kdf{"KDF1(SHA-512)"};

  // Salt to be used for key derivation
  // NOTE: Pick salt dynamically,Botan recommds for example using a session ID.
  std::vector<Botan::byte> salt{0x01,0x02,0x03};

  Botan::AutoSeeded_RNG rng{};

  // Generate private key
  Botan::McEliece_PrivateKey priv{rng,n,t};

  std::vector<Botan::byte> pub_enc{priv.subject_public_key()};
  Botan::secure_vector<Botan::byte> priv_enc{Botan::PKCS8::BER_encode(priv)};

  // Encrypting side: Create encapsulated symmetric key
  std::unique_ptr<Botan::Public_Key> pub{Botan::X509::load_key(pub_enc)};
  Botan::PK_KEM_Encryptor encryptor{*pub,rng,kdf};

  Botan::secure_vector<Botan::byte> encapsulated_key{};
  Botan::secure_vector<Botan::byte> shared_key1{};

  encryptor.encrypt(encapsulated_key,shared_key1,shared_key_size,salt);

  std::cout << "Shared key 1: " << Botan::hex_encode(shared_key1) << std::endl;

  // Decrypting side: Unpack encapsulated symmetric key
  Botan::DataSource_Memory priv_enc_src{priv_enc};
  std::unique_ptr<Botan::Private_Key> priv2{
      Botan::PKCS8::load_key(priv_enc_src)};
  Botan::PK_KEM_Decryptor decryptor{*priv2,kdf};

  Botan::secure_vector<Botan::byte> shared_key2{
      decryptor.decrypt(encapsulated_key,salt)};

  std::cout << "Shared key 2: " << Botan::hex_encode(shared_key2) << std::endl;

  assert(shared_key1 == shared_key2);

  return 0;
}

我针对2.15.0测试了此代码。输出示例:

$ g++ -g $(pkg-config --cflags --libs botan-2) test.cpp
$ ./a.out
Shared key 1: 32177925CE5F3D607BA45575195F13B9E0123BD739580DFCF9AE53D417C530DB115867E5E377735CB405CDA6DF7866C647F85FDAC5C407BB2E2C3A8E7D41A5CC
Shared key 2: 32177925CE5F3D607BA45575195F13B9E0123BD739580DFCF9AE53D417C530DB115867E5E377735CB405CDA6DF7866C647F85FDAC5C407BB2E2C3A8E7D41A5CC

与您提供的代码相比,我做了些更改:

  • 每个Botan::Private_Key也是Botan::Public_Keyreference)。因此,我们不需要将生成的私钥转换为公钥。相反,我们可以直接在私钥上调用subject_public_key以获取公钥编码。

  • 使用private_key_bits获取用于序列化的原始私钥位,但是就互操作性而言,使用PKCS8可能更健壮。因此,出于这个原因,我将在私钥上使用Botan::PKCS8::BER_encode

  • 直接从公钥编码构造McEliece_PublicKey对我来说不起作用,因为构造函数期望原始的公钥位而不是x509公钥编码。因此,我不得不使用Botan::X509::load_key

  • McEliece_KEM_Encryptor已被删除(reference):

    为KEM(密钥封装)技术添加通用接口。转换McEliece KEM以使用它。先前的接口McEliece_KEM_Encryptor和McEliece_KEM_Decryptor已被删除。现在,新的KEM界面使用KDF哈希结果键;要获得与McEliece_KEM_Encryptor先前提供的输出相同的输出,请使用“ KDF1(SHA-512)”并精确请求64个字节。

    相反,您将使用Botan::PK_KEM_Encryptor,它将公共密钥作为参数并从公共密钥推断要使用的加密算法。您可以从代码中看到,这种方式变得更加灵活,在生成密钥之后,我们不必引用McEliece。如果要切换到其他算法,则只需更改密钥生成部分,而不必更改密钥封装部分。

  • McEliece_KEM_Decryptor也是如此。

  • 如以上引用中所述,新的KEM接口允许指定要用于KEM的密钥派生函数以及所需的对称密钥大小。另外,您可以传递将用于密钥派生的盐。对于盐,您将使用一些对于您的应用程序唯一的值,或者甚至更好地对于当前会话唯一的值(reference):

    通常,盐是标签或标识符,例如会话ID。

,

我现在更新了 https://www.cryptosource.de/docs/mceliece_in_botan.pdf 中的示例代码,以反映对 Botan 新 KEM API 的更改。

请注意,当在公钥方案(如 McEliece)的 KEM 上下文中使用时,没有必要为 KDF 提供盐值。 KDF 在这里可以接受盐值仅仅是 API 的人工制品,因为 KDF 也可以在其他上下文中使用。具体来说,只有在导出可能缺乏熵的秘密密钥(例如密码)时,才需要盐值。然后根据预先计算的表格缓解攻击。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。