Exemple #1
0
void mceliece_decrypt(
   secure_vector<byte>& plaintext,
   secure_vector<byte> & error_mask,
   const byte ciphertext[],
   size_t ciphertext_len,
   const McEliece_PrivateKey & key)
   {
   secure_vector<gf2m> error_pos;
   plaintext = mceliece_decrypt(error_pos, ciphertext, ciphertext_len, key);

   const size_t code_length = key.get_code_length();
   secure_vector<byte> result((code_length+7)/8);
   for(auto&& pos : error_pos)
      {
      if(pos > code_length)
         {
         throw Invalid_Argument("error position larger than code size");
         }
      result[pos / 8] |= (1 << (pos % 8));
      }

   error_mask = result;
   }
Exemple #2
0
secure_vector<byte>
mceies_decrypt(const McEliece_PrivateKey& privkey,
               const byte ct[], size_t ct_len,
               const byte ad[], size_t ad_len,
               const std::string& algo)
   {
   try
      {
      McEliece_KEM_Decryptor kem_op(privkey);

      const size_t mce_code_bytes = (privkey.get_code_length() + 7) / 8;

      std::unique_ptr<AEAD_Mode> aead(get_aead(algo, DECRYPTION));
      if(!aead)
         throw std::runtime_error("Unable to create AEAD instance '" + algo + "'");

      const size_t nonce_len = aead->default_nonce_length();

      if(ct_len < mce_code_bytes + nonce_len + aead->tag_size())
         throw std::runtime_error("Input message too small to be valid");

      const secure_vector<byte> mce_key = kem_op.decrypt(ct, mce_code_bytes);

      aead->set_key(aead_key(mce_key, *aead));
      aead->set_associated_data(ad, ad_len);

      secure_vector<byte> pt(ct + mce_code_bytes + nonce_len, ct + ct_len);

      aead->start(&ct[mce_code_bytes], nonce_len);
      aead->finish(pt, 0);
      return pt;
      }
   catch(std::exception& e)
      {
      throw std::runtime_error("mce_decrypt failed: " + std::string(e.what()));
      }
   }
Exemple #3
0
/**
* @param p_err_pos_len must point to the available length of err_pos on input, the
* function will set it to the actual number of errors returned in the err_pos
* array */
secure_vector<byte> mceliece_decrypt(
   secure_vector<gf2m> & error_pos,
   const byte *ciphertext, u32bit ciphertext_len,
   const McEliece_PrivateKey & key)
   {

   u32bit dimension = key.get_dimension();
   u32bit codimension = key.get_codimension();
   u32bit t = key.get_goppa_polyn().get_degree();
   polyn_gf2m syndrome_polyn(key.get_goppa_polyn().get_sp_field()); // init as zero polyn
   const unsigned unused_pt_bits = dimension % 8;
   const byte unused_pt_bits_mask = (1 << unused_pt_bits) - 1;

   if(ciphertext_len != (key.get_code_length()+7)/8)
      {
      throw Invalid_Argument("wrong size of McEliece ciphertext");
      }
   u32bit cleartext_len = (key.get_message_word_bit_length()+7)/8;

   if(cleartext_len != bit_size_to_byte_size(dimension))
      {
      throw Invalid_Argument("mce-decryption: wrong length of cleartext buffer");
      }

   secure_vector<u32bit> syndrome_vec(bit_size_to_32bit_size(codimension));
   matrix_arr_mul(key.get_H_coeffs(),
                  key.get_code_length(),
                  bit_size_to_32bit_size(codimension),
                  ciphertext,
                  syndrome_vec.data(), syndrome_vec.size());

   secure_vector<byte> syndrome_byte_vec(bit_size_to_byte_size(codimension));
   u32bit syndrome_byte_vec_size = syndrome_byte_vec.size();
   for(u32bit i = 0; i < syndrome_byte_vec_size; i++)
      {
      syndrome_byte_vec[i] = syndrome_vec[i/4] >> (8* (i % 4));
      }

   syndrome_polyn = polyn_gf2m(t-1, syndrome_byte_vec.data(), bit_size_to_byte_size(codimension), key.get_goppa_polyn().get_sp_field());

   syndrome_polyn.get_degree();
   error_pos = goppa_decode(syndrome_polyn, key.get_goppa_polyn(), key.get_sqrtmod(), key.get_Linv());

   u32bit nb_err = error_pos.size();

   secure_vector<byte> cleartext(cleartext_len);
   copy_mem(cleartext.data(), ciphertext, cleartext_len);

   for(u32bit i = 0; i < nb_err; i++)
      {
      gf2m current = error_pos[i];

      if(current >= cleartext_len * 8)
         {
         // an invalid position, this shouldn't happen
         continue;
         }
      cleartext[current / 8] ^= (1 << (current % 8));
      }

   if(unused_pt_bits)
      {
      cleartext[cleartext_len - 1] &= unused_pt_bits_mask;
      }

   return cleartext;
   }