Exemplo n.º 1
0
/*
* PSSR Encode Operation
*/
secure_vector<byte> PSSR::encoding_of(const secure_vector<byte>& msg,
                                      size_t output_bits,
                                      RandomNumberGenerator& rng)
{
    const size_t HASH_SIZE = m_hash->output_length();

    if(msg.size() != HASH_SIZE)
        throw Encoding_Error("PSSR::encoding_of: Bad input length");
    if(output_bits < 8*HASH_SIZE + 8*m_SALT_SIZE + 9)
        throw Encoding_Error("PSSR::encoding_of: Output length is too small");

    const size_t output_length = (output_bits + 7) / 8;

    secure_vector<byte> salt = rng.random_vec(m_SALT_SIZE);

    for(size_t j = 0; j != 8; ++j)
        m_hash->update(0);
    m_hash->update(msg);
    m_hash->update(salt);
    secure_vector<byte> H = m_hash->final();

    secure_vector<byte> EM(output_length);

    EM[output_length - HASH_SIZE - m_SALT_SIZE - 2] = 0x01;
    buffer_insert(EM, output_length - 1 - HASH_SIZE - m_SALT_SIZE, salt);
    mgf1_mask(*m_hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - 1);
    EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
    buffer_insert(EM, output_length - 1 - HASH_SIZE, H);
    EM[output_length-1] = 0xBC;

    return EM;
}
Exemplo n.º 2
0
/*************************************************
* Do basic sanity checks                         *
*************************************************/
void X509_Cert_Options::sanity_check() const
   {
   if(common_name == "" || country == "")
      throw Encoding_Error("X.509 certificate: name and country MUST be set");
   if(country.size() != 2)
      throw Encoding_Error("Invalid ISO country code: " + country);
   if(start >= end)
      throw Encoding_Error("X509_Cert_Options: invalid time constraints");
   }
Exemplo n.º 3
0
/*
* EMSA1 BSI Encode Operation
*/
SecureVector<byte> EMSA1_BSI::encoding_of(const MemoryRegion<byte>& msg,
                                          u32bit output_bits,
                                          RandomNumberGenerator&)
   {
   if(msg.size() != hash_ptr()->OUTPUT_LENGTH)
      throw Encoding_Error("EMSA1_BSI::encoding_of: Invalid size for input");

   if(8*msg.size() <= output_bits)
      return msg;

   throw Encoding_Error("EMSA1_BSI::encoding_of: max key input size exceeded");
   }
Exemplo n.º 4
0
/*
* EMSA1 BSI Encode Operation
*/
secure_vector<byte> EMSA1_BSI::encoding_of(const secure_vector<byte>& msg,
                                          size_t output_bits,
                                          RandomNumberGenerator&)
   {
   if(msg.size() != hash_output_length())
      throw Encoding_Error("EMSA1_BSI::encoding_of: Invalid size for input");

   if(8*msg.size() <= output_bits)
      return msg;

   throw Encoding_Error("EMSA1_BSI::encoding_of: max key input size exceeded");
   }
Exemplo n.º 5
0
/*************************************************
* Convert this number to a u32bit, if possible   *
*************************************************/
u32bit BigInt::to_u32bit() const
   {
   if(is_negative())
      throw Encoding_Error("BigInt::to_u32bit: Number is negative");
   if(bits() >= 32)
      throw Encoding_Error("BigInt::to_u32bit: Number is too big to convert");

   u32bit out = 0;
   for(u32bit j = 0; j != 4; ++j)
      out = (out << 8) | byte_at(3-j);
   return out;
   }
Exemplo n.º 6
0
const std::vector<uint8_t>& X509_Certificate::subject_public_key_bitstring_sha1() const
   {
   if(data().m_subject_public_key_bitstring_sha1.empty())
      throw Encoding_Error("X509_Certificate::subject_public_key_bitstring_sha1 called but SHA-1 disabled in build");

   return data().m_subject_public_key_bitstring_sha1;
   }
Exemplo n.º 7
0
/*
* BER encode a PKCS #8 private key, encrypted
*/
std::vector<uint8_t> BER_encode_encrypted_pbkdf_msec(const Private_Key& key,
                                                     RandomNumberGenerator& rng,
                                                     const std::string& pass,
                                                     std::chrono::milliseconds pbkdf_msec,
                                                     size_t* pbkdf_iterations,
                                                     const std::string& cipher,
                                                     const std::string& pbkdf_hash)
   {
#if defined(BOTAN_HAS_PKCS5_PBES2)
   const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info =
      pbes2_encrypt_msec(key.private_key_info(), pass,
                         pbkdf_msec, pbkdf_iterations,
                         cipher.empty() ? "AES-256/CBC" : cipher,
                         pbkdf_hash.empty() ? "SHA-256" : pbkdf_hash,
                         rng);

   std::vector<uint8_t> output;
   DER_Encoder(output)
      .start_cons(SEQUENCE)
         .encode(pbe_info.first)
         .encode(pbe_info.second, OCTET_STRING)
      .end_cons();

   return output;
#else
   BOTAN_UNUSED(key, rng, pass, pbkdf_msec, pbkdf_iterations, cipher, pbkdf_hash);
   throw Encoding_Error("BER_encode_encrypted_pbkdf_msec cannot encrypt because PBES2 disabled in build");
#endif
   }
Exemplo n.º 8
0
/*
* Return the code of the effective key bits
*/
byte RC2::EKB_code(u32bit ekb)
   {
   const byte EKB[256] = {
      0xBD, 0x56, 0xEA, 0xF2, 0xA2, 0xF1, 0xAC, 0x2A, 0xB0, 0x93, 0xD1, 0x9C,
      0x1B, 0x33, 0xFD, 0xD0, 0x30, 0x04, 0xB6, 0xDC, 0x7D, 0xDF, 0x32, 0x4B,
      0xF7, 0xCB, 0x45, 0x9B, 0x31, 0xBB, 0x21, 0x5A, 0x41, 0x9F, 0xE1, 0xD9,
      0x4A, 0x4D, 0x9E, 0xDA, 0xA0, 0x68, 0x2C, 0xC3, 0x27, 0x5F, 0x80, 0x36,
      0x3E, 0xEE, 0xFB, 0x95, 0x1A, 0xFE, 0xCE, 0xA8, 0x34, 0xA9, 0x13, 0xF0,
      0xA6, 0x3F, 0xD8, 0x0C, 0x78, 0x24, 0xAF, 0x23, 0x52, 0xC1, 0x67, 0x17,
      0xF5, 0x66, 0x90, 0xE7, 0xE8, 0x07, 0xB8, 0x60, 0x48, 0xE6, 0x1E, 0x53,
      0xF3, 0x92, 0xA4, 0x72, 0x8C, 0x08, 0x15, 0x6E, 0x86, 0x00, 0x84, 0xFA,
      0xF4, 0x7F, 0x8A, 0x42, 0x19, 0xF6, 0xDB, 0xCD, 0x14, 0x8D, 0x50, 0x12,
      0xBA, 0x3C, 0x06, 0x4E, 0xEC, 0xB3, 0x35, 0x11, 0xA1, 0x88, 0x8E, 0x2B,
      0x94, 0x99, 0xB7, 0x71, 0x74, 0xD3, 0xE4, 0xBF, 0x3A, 0xDE, 0x96, 0x0E,
      0xBC, 0x0A, 0xED, 0x77, 0xFC, 0x37, 0x6B, 0x03, 0x79, 0x89, 0x62, 0xC6,
      0xD7, 0xC0, 0xD2, 0x7C, 0x6A, 0x8B, 0x22, 0xA3, 0x5B, 0x05, 0x5D, 0x02,
      0x75, 0xD5, 0x61, 0xE3, 0x18, 0x8F, 0x55, 0x51, 0xAD, 0x1F, 0x0B, 0x5E,
      0x85, 0xE5, 0xC2, 0x57, 0x63, 0xCA, 0x3D, 0x6C, 0xB4, 0xC5, 0xCC, 0x70,
      0xB2, 0x91, 0x59, 0x0D, 0x47, 0x20, 0xC8, 0x4F, 0x58, 0xE0, 0x01, 0xE2,
      0x16, 0x38, 0xC4, 0x6F, 0x3B, 0x0F, 0x65, 0x46, 0xBE, 0x7E, 0x2D, 0x7B,
      0x82, 0xF9, 0x40, 0xB5, 0x1D, 0x73, 0xF8, 0xEB, 0x26, 0xC7, 0x87, 0x97,
      0x25, 0x54, 0xB1, 0x28, 0xAA, 0x98, 0x9D, 0xA5, 0x64, 0x6D, 0x7A, 0xD4,
      0x10, 0x81, 0x44, 0xEF, 0x49, 0xD6, 0xAE, 0x2E, 0xDD, 0x76, 0x5C, 0x2F,
      0xA7, 0x1C, 0xC9, 0x09, 0x69, 0x9A, 0x83, 0xCF, 0x29, 0x39, 0xB9, 0xE9,
      0x4C, 0xFF, 0x43, 0xAB };

   if(ekb < 256)
      return EKB[ekb];
   else
      throw Encoding_Error("RC2::EKB_code: EKB is too large");
   }
Exemplo n.º 9
0
//static
void BigInt::encode_1363(uint8_t output[], size_t bytes, const BigInt& n)
   {
   if(n.bytes() > bytes)
      throw Encoding_Error("encode_1363: n is too large to encode properly");

   n.binary_encode(output, bytes);
   }
Exemplo n.º 10
0
bool EMSA1::verify(const secure_vector<uint8_t>& input,
                   const secure_vector<uint8_t>& raw,
                   size_t key_bits)
   {
   try {
      if(raw.size() != m_hash->output_length())
         throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");

      // Call emsa1_encoding to handle any required bit shifting
      const secure_vector<uint8_t> our_coding = emsa1_encoding(raw, key_bits);

      if(our_coding.size() < input.size())
         return false;

      const size_t offset = our_coding.size() - input.size(); // must be >= 0 per check above

      // If our encoding is longer, all the bytes in it must be zero
      for(size_t i = 0; i != offset; ++i)
         if(our_coding[i] != 0)
            return false;

      return same_mem(input.data(), &our_coding[offset], input.size());
      }
   catch(Invalid_Argument)
      {
      return false;
      }
   }
Exemplo n.º 11
0
/*
* BER encode a PKCS #8 private key, encrypted
*/
std::vector<uint8_t> BER_encode(const Private_Key& key,
                             RandomNumberGenerator& rng,
                             const std::string& pass,
                             std::chrono::milliseconds msec,
                             const std::string& pbe_algo)
   {
#if defined(BOTAN_HAS_PKCS5_PBES2)
   const auto pbe_params = choose_pbe_params(pbe_algo, key.algo_name());

   const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info =
      pbes2_encrypt_msec(PKCS8::BER_encode(key), pass, msec, nullptr,
                         pbe_params.first, pbe_params.second, rng);

   std::vector<uint8_t> output;
   DER_Encoder der(output);
   der.start_cons(SEQUENCE)
         .encode(pbe_info.first)
         .encode(pbe_info.second, OCTET_STRING)
      .end_cons();

   return output;
#else
   BOTAN_UNUSED(key, rng, pass, msec, pbe_algo);
   throw Encoding_Error("PKCS8::BER_encode cannot encrypt because PBES2 was disabled in build");
#endif
   }
Exemplo n.º 12
0
bool EMSA1::verify(const secure_vector<byte>& coded,
                   const secure_vector<byte>& raw, size_t key_bits)
   {
   try {
      if(raw.size() != m_hash->output_length())
         throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");

      secure_vector<byte> our_coding = emsa1_encoding(raw, key_bits);

      if(our_coding == coded) return true;
      if(our_coding.empty() || our_coding[0] != 0) return false;
      if(our_coding.size() <= coded.size()) return false;

      size_t offset = 0;
      while(offset < our_coding.size() && our_coding[offset] == 0)
         ++offset;
      if(our_coding.size() - offset != coded.size())
         return false;

      for(size_t j = 0; j != coded.size(); ++j)
         if(coded[j] != our_coding[j+offset])
            return false;

      return true;
      }
   catch(Invalid_Argument)
      {
      return false;
      }
   }
Exemplo n.º 13
0
secure_vector<uint8_t> EMSA1::encoding_of(const secure_vector<uint8_t>& msg,
                                       size_t output_bits,
                                       RandomNumberGenerator&)
   {
   if(msg.size() != hash_output_length())
      throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");
   return emsa1_encoding(msg, output_bits);
   }
Exemplo n.º 14
0
/*
* Finish encrypting in ECB mode
*/
void ECB_Encryption::end_msg()
   {
   SecureVector<byte> padding(BLOCK_SIZE);
   padder->pad(padding, padding.size(), position);
   write(padding, padder->pad_bytes(BLOCK_SIZE, position));
   if(position != 0)
      throw Encoding_Error(name() + ": Did not pad to full blocksize");
   }
Exemplo n.º 15
0
/*
* Encode two BigInt, with leading 0s if needed, and concatenate
*/
secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes)
   {
   if(n1.bytes() > bytes || n2.bytes() > bytes)
      throw Encoding_Error("encode_fixed_length_int_pair: values too large to encode properly");
   secure_vector<uint8_t> output(2 * bytes);
   n1.binary_encode(output.data()        , bytes);
   n2.binary_encode(output.data() + bytes, bytes);
   return output;
   }
Exemplo n.º 16
0
/*
* Encode a BigInt, with leading 0s if needed
*/
secure_vector<uint8_t> BigInt::encode_1363(const BigInt& n, size_t bytes)
   {
   if(n.bytes() > bytes)
      throw Encoding_Error("encode_1363: n is too large to encode properly");

   secure_vector<uint8_t> output(bytes);
   n.binary_encode(output.data(), output.size());
   return output;
   }
Exemplo n.º 17
0
/*
* Return the raw (unencoded) data
*/
secure_vector<uint8_t> PSSR_Raw::raw_data()
   {
   secure_vector<uint8_t> ret;
   std::swap(ret, m_msg);

   if(ret.size() != m_hash->output_length())
      throw Encoding_Error("PSSR_Raw Bad input length, did not match hash");

   return ret;
   }
Exemplo n.º 18
0
Arquivo: tss.cpp Projeto: louiz/botan
std::vector<RTSS_Share>
RTSS_Share::split(byte M, byte N,
                  const byte S[], u16bit S_len,
                  const byte identifier[16],
                  RandomNumberGenerator& rng)
   {
   if(M == 0 || N == 0 || M > N)
      throw Encoding_Error("RTSS_Share::split: M == 0 or N == 0 or M > N");

   SHA_256 hash; // always use SHA-256 when generating shares

   std::vector<RTSS_Share> shares(N);

   // Create RTSS header in each share
   for(byte i = 0; i != N; ++i)
      {
      shares[i].m_contents += std::make_pair(identifier, 16);
      shares[i].m_contents += rtss_hash_id(hash.name());
      shares[i].m_contents += M;
      shares[i].m_contents += get_byte(0, S_len);
      shares[i].m_contents += get_byte(1, S_len);
      }

   // Choose sequential values for X starting from 1
   for(byte i = 0; i != N; ++i)
      shares[i].m_contents.push_back(i+1);

   // secret = S || H(S)
   secure_vector<byte> secret(S, S + S_len);
   secret += hash.process(S, S_len);

   for(size_t i = 0; i != secret.size(); ++i)
      {
      std::vector<byte> coefficients(M-1);
      rng.randomize(coefficients.data(), coefficients.size());

      for(byte j = 0; j != N; ++j)
         {
         const byte X = j + 1;

         byte sum = secret[i];
         byte X_i = X;

         for(size_t k = 0; k != coefficients.size(); ++k)
            {
            sum ^= gfp_mul(X_i, coefficients[k]);
            X_i  = gfp_mul(X_i, X);
            }

         shares[j].m_contents.push_back(sum);
         }
      }

   return shares;
   }
Exemplo n.º 19
0
/*************************************************
* Encode a BigInt, with leading 0s if needed     *
*************************************************/
SecureVector<byte> BigInt::encode_1363(const BigInt& n, u32bit bytes)
   {
   const u32bit n_bytes = n.bytes();
   if(n_bytes > bytes)
      throw Encoding_Error("encode_1363: n is too large to encode properly");

   const u32bit leading_0s = bytes - n_bytes;

   SecureVector<byte> output(bytes);
   encode(output + leading_0s, n, Binary);
   return output;
   }
Exemplo n.º 20
0
/*
* PKCS1 Pad Operation
*/
secure_vector<byte> EME_PKCS1v15::pad(const byte in[], size_t inlen,
                                     size_t olen,
                                     RandomNumberGenerator& rng) const
   {
   olen /= 8;

   if(olen < 10)
      throw Encoding_Error("PKCS1: Output space too small");
   if(inlen > olen - 10)
      throw Encoding_Error("PKCS1: Input is too large");

   secure_vector<byte> out(olen);

   out[0] = 0x02;
   for(size_t j = 1; j != olen - inlen - 1; ++j)
      while(out[j] == 0)
         out[j] = rng.next_byte();
   buffer_insert(out, olen - inlen, in, inlen);

   return out;
   }
Exemplo n.º 21
0
std::vector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
   {
   const std::vector<byte> plain_sig = unlock(m_op->sign(rng));
   const size_t parts = m_op->message_parts();

   if(parts == 1 || m_sig_format == IEEE_1363)
      return plain_sig;
   else if(m_sig_format == DER_SEQUENCE)
      return der_encode_signature(plain_sig, parts);
   else
      throw Encoding_Error("PK_Signer: Unknown signature format " +
                           std::to_string(m_sig_format));
   }
Exemplo n.º 22
0
std::vector<uint8_t> Certificate_Status::serialize() const
   {
   if(m_response.size() > 0xFFFFFF) // unlikely
      throw Encoding_Error("OCSP response too long to encode in TLS");

   const uint32_t response_len = static_cast<uint32_t>(m_response.size());

   std::vector<uint8_t> buf;
   buf.push_back(1); // type OCSP
   for(size_t i = 1; i < 4; ++i)
      buf.push_back(get_byte(i, response_len));

   buf += m_response;
   return buf;
   }
Exemplo n.º 23
0
void CTS_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
   {
   BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
   const size_t sz = buffer.size() - offset;
   uint8_t* buf = buffer.data() + offset;

   const size_t BS = cipher().block_size();

   if(sz < BS + 1)
      throw Encoding_Error(name() + ": insufficient data to decrypt");

   if(sz % BS == 0)
      {
      // swap last two blocks

      for(size_t i = 0; i != BS; ++i)
         std::swap(buffer[buffer.size()-BS+i], buffer[buffer.size()-2*BS+i]);

      update(buffer, offset);
      }
   else
      {
      const size_t full_blocks = ((sz / BS) - 1) * BS;
      const size_t final_bytes = sz - full_blocks;
      BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range");

      secure_vector<uint8_t> last(buf + full_blocks, buf + full_blocks + final_bytes);
      buffer.resize(full_blocks + offset);
      update(buffer, offset);

      cipher().decrypt(last.data());

      xor_buf(last.data(), &last[BS], final_bytes - BS);

      for(size_t i = 0; i != final_bytes - BS; ++i)
         std::swap(last[i], last[i + BS]);

      cipher().decrypt(last.data());
      xor_buf(last.data(), state_ptr(), BS);

      buffer += last;
      }
   }
Exemplo n.º 24
0
/*
* Serialize a Certificate Verify message
*/
std::vector<uint8_t> Certificate_Verify::serialize() const
   {
   std::vector<uint8_t> buf;

   if(m_scheme != Signature_Scheme::NONE)
      {
      const uint16_t scheme_code = static_cast<uint16_t>(m_scheme);
      buf.push_back(get_byte(0, scheme_code));
      buf.push_back(get_byte(1, scheme_code));
      }

   if(m_signature.size() > 0xFFFF)
      throw Encoding_Error("Certificate_Verify signature too long to encode");

   const uint16_t sig_len = static_cast<uint16_t>(m_signature.size());
   buf.push_back(get_byte(0, sig_len));
   buf.push_back(get_byte(1, sig_len));
   buf += m_signature;

   return buf;
   }
Exemplo n.º 25
0
std::string X509_Time::to_string() const
   {
   if(time_is_set() == false)
      throw Invalid_State("X509_Time::as_string: No time set");

   uint32_t full_year = m_year;

   if(m_tag == UTC_TIME)
      {
      if(m_year < 1950 || m_year >= 2050)
         throw Encoding_Error("X509_Time: The time " + readable_string() +
                              " cannot be encoded as a UTCTime");

      full_year = (m_year >= 2000) ? (m_year - 2000) : (m_year - 1900);
      }

   const uint64_t YEAR_FACTOR = 10000000000ULL;
   const uint64_t MON_FACTOR  = 100000000;
   const uint64_t DAY_FACTOR  = 1000000;
   const uint64_t HOUR_FACTOR = 10000;
   const uint64_t MIN_FACTOR  = 100;

   const uint64_t int_repr =
      YEAR_FACTOR * full_year +
      MON_FACTOR * m_month +
      DAY_FACTOR * m_day +
      HOUR_FACTOR * m_hour +
      MIN_FACTOR * m_minute +
      m_second;

   std::string repr = std::to_string(int_repr) + "Z";

   uint32_t desired_size = (m_tag == UTC_TIME) ? 13 : 15;

   while(repr.size() < desired_size)
      repr = "0" + repr;

   return repr;
   }
Exemplo n.º 26
0
/*
* DER encode the parameters
*/
std::vector<byte> DL_Group::DER_encode(Format format) const
   {
   init_check();

   if((m_q == 0) && (format != PKCS_3))
      throw Encoding_Error("The ANSI DL parameter formats require a subgroup");

   if(format == ANSI_X9_57)
      {
      return DER_Encoder()
         .start_cons(SEQUENCE)
            .encode(m_p)
            .encode(m_q)
            .encode(m_g)
         .end_cons()
      .get_contents_unlocked();
      }
   else if(format == ANSI_X9_42)
      {
      return DER_Encoder()
         .start_cons(SEQUENCE)
            .encode(m_p)
            .encode(m_g)
            .encode(m_q)
         .end_cons()
      .get_contents_unlocked();
      }
   else if(format == PKCS_3)
      {
      return DER_Encoder()
         .start_cons(SEQUENCE)
            .encode(m_p)
            .encode(m_g)
         .end_cons()
      .get_contents_unlocked();
      }

   throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format));
   }
Exemplo n.º 27
0
std::vector<RTSS_Share>
RTSS_Share::split(uint8_t M, uint8_t N,
                  const uint8_t S[], uint16_t S_len,
                  const std::vector<uint8_t>& identifier,
                  const std::string& hash_fn,
                  RandomNumberGenerator& rng)
   {
   if(M <= 1 || N <= 1 || M > N || N >= 255)
      throw Invalid_Argument("RTSS_Share::split: Invalid N or M");

   if(identifier.size() > 16)
      throw Invalid_Argument("RTSS_Share::split Invalid identifier size");

   const uint8_t hash_id = rtss_hash_id(hash_fn);

   std::unique_ptr<HashFunction> hash;
   if(hash_id > 0)
      hash = HashFunction::create_or_throw(hash_fn);

   // secret = S || H(S)
   secure_vector<uint8_t> secret(S, S + S_len);
   if(hash)
      secret += hash->process(S, S_len);

   if(secret.size() >= 0xFFFE)
      throw Encoding_Error("RTSS_Share::split secret too large for TSS format");

   // +1 byte for the share ID
   const uint16_t share_len = static_cast<uint16_t>(secret.size() + 1);

   secure_vector<uint8_t> share_header(RTSS_HEADER_SIZE);
   copy_mem(&share_header[0], identifier.data(), identifier.size());
   share_header[16] = hash_id;
   share_header[17] = M;
   share_header[18] = get_byte(0, share_len);
   share_header[19] = get_byte(1, share_len);

   // Create RTSS header in each share
   std::vector<RTSS_Share> shares(N);

   for(uint8_t i = 0; i != N; ++i)
      {
      shares[i].m_contents.reserve(share_header.size() + share_len);
      shares[i].m_contents = share_header;
      }

   // Choose sequential values for X starting from 1
   for(uint8_t i = 0; i != N; ++i)
      shares[i].m_contents.push_back(i+1);

   for(size_t i = 0; i != secret.size(); ++i)
      {
      std::vector<uint8_t> coefficients(M-1);
      rng.randomize(coefficients.data(), coefficients.size());

      for(uint8_t j = 0; j != N; ++j)
         {
         const uint8_t X = j + 1;

         uint8_t sum = secret[i];
         uint8_t X_i = X;

         for(size_t k = 0; k != coefficients.size(); ++k)
            {
            sum ^= gfp_mul(X_i, coefficients[k]);
            X_i  = gfp_mul(X_i, X);
            }

         shares[j].m_contents.push_back(sum);
         }
      }

   return shares;
   }