<commit_before>/*
* GOST 34.10-2012
* (C) 2007 <NAME>, FlexSecure GmbH
*          <NAME>, FlexSecure GmbH
* (C) 2008-2010,2015,2018 <NAME>
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/gost_3410.h>
#include <botan/internal/pk_ops_impl.h>
#include <botan/internal/point_mul.h>
#include <botan/reducer.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>

namespace Botan {

std::vector<uint8_t> GOST_3410_PublicKey::public_key_bits() const
   {
   const BigInt x = public_point().get_affine_x();
   const BigInt y = public_point().get_affine_y();

   size_t part_size = std::max(x.bytes(), y.bytes());

   std::vector<uint8_t> bits(2*part_size);

   x.binary_encode(&bits[part_size - x.bytes()]);
   y.binary_encode(&bits[2*part_size - y.bytes()]);

   // Keys are stored in little endian format (WTF)
   for(size_t i = 0; i != part_size / 2; ++i)
      {
      std::swap(bits[i], bits[part_size-1-i]);
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
      }

   std::vector<uint8_t> output;
   DER_Encoder(output).encode(bits, ASN1_Type::OctetString);
   return output;
   }

std::string GOST_3410_PublicKey::algo_name() const
   {
   const size_t p_bits = domain().get_p_bits();

   if(p_bits == 256 || p_bits == 512)
      return "GOST-34.10-2012-" + std::to_string(p_bits);
   else
      throw Encoding_Error("GOST-34.10-2012 is not defined for parameters of this size");
   }

AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
   {
   std::vector<uint8_t> params;

   const OID gost_oid = get_oid();
   const OID domain_oid = domain().get_curve_oid();

   DER_Encoder(params).start_sequence().encode(domain_oid).end_cons();

   return AlgorithmIdentifier(gost_oid, params);
   }

GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
                                         const std::vector<uint8_t>& key_bits)
   {
   OID ecc_param_id;

   // The parameters also includes hash and cipher OIDs
   BER_Decoder(alg_id.get_parameters()).start_sequence().decode(ecc_param_id);

   m_domain_params = EC_Group(ecc_param_id);

   const size_t p_bits = m_domain_params.get_p_bits();
   if(p_bits != 256 && p_bits != 512)
      throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
                           std::to_string(p_bits));

   secure_vector<uint8_t> bits;
   BER_Decoder(key_bits).decode(bits, ASN1_Type::OctetString);

   const size_t part_size = bits.size() / 2;

   // Keys are stored in little endian format (WTF)
   for(size_t i = 0; i != part_size / 2; ++i)
      {
      std::swap(bits[i], bits[part_size-1-i]);
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
      }

   BigInt x(bits.data(), part_size);
   BigInt y(&bits[part_size], part_size);

   m_public_key = domain().point(x, y);

   BOTAN_ASSERT(m_public_key.on_the_curve(),<commit_msg>Verify decoded length of GOST public keys<commit_after>/*
* GOST 34.10-2012
* (C) 2007 <NAME>, FlexSecure GmbH
*          <NAME>, FlexSecure GmbH
* (C) 2008-2010,2015,2018 <NAME>
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/gost_3410.h>
#include <botan/internal/pk_ops_impl.h>
#include <botan/internal/point_mul.h>
#include <botan/reducer.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>

namespace Botan {

std::vector<uint8_t> GOST_3410_PublicKey::public_key_bits() const
   {
   const BigInt x = public_point().get_affine_x();
   const BigInt y = public_point().get_affine_y();

   size_t part_size = std::max(x.bytes(), y.bytes());

   std::vector<uint8_t> bits(2*part_size);

   x.binary_encode(&bits[part_size - x.bytes()]);
   y.binary_encode(&bits[2*part_size - y.bytes()]);

   // Keys are stored in little endian format (WTF)
   for(size_t i = 0; i != part_size / 2; ++i)
      {
      std::swap(bits[i], bits[part_size-1-i]);
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
      }

   std::vector<uint8_t> output;
   DER_Encoder(output).encode(bits, ASN1_Type::OctetString);
   return output;
   }

std::string GOST_3410_PublicKey::algo_name() const
   {
   const size_t p_bits = domain().get_p_bits();

   if(p_bits == 256 || p_bits == 512)
      return "GOST-34.10-2012-" + std::to_string(p_bits);
   else
      throw Encoding_Error("GOST-34.10-2012 is not defined for parameters of this size");
   }

AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
   {
   std::vector<uint8_t> params;

   const OID gost_oid = get_oid();
   const OID domain_oid = domain().get_curve_oid();

   DER_Encoder(params).start_sequence().encode(domain_oid).end_cons();

   return AlgorithmIdentifier(gost_oid, params);
   }

GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
                                         const std::vector<uint8_t>& key_bits)
   {
   OID ecc_param_id;

   // The parameters also includes hash and cipher OIDs
   BER_Decoder(alg_id.get_parameters()).start_sequence().decode(ecc_param_id);

   m_domain_params = EC_Group(ecc_param_id);

   const size_t p_bits = m_domain_params.get_p_bits();
   if(p_bits != 256 && p_bits != 512)
      throw Decoding_Error("GOST-34.10-2012 is not defined for parameters of size " +
                           std::to_string(p_bits));

   secure_vector<uint8_t> bits;
   BER_Decoder(key_bits).decode(bits, ASN1_Type::OctetString);

   if(bits.size() != 2*(p_bits/8))
      throw Decoding_Error("GOST-34.10-2020 invalid encoding of public key");

   const size_t part_size = bits.size() / 2;

   // Keys are stored in little endian format (WTF)
   for(size_t i = 0; i != part_size / 2; ++i)
      {
      std::swap(bits[i], bits[part_size-1-i]);
      std::swap(bits[part_size+i], bits[2*part_size-1-i]);
      }

   BigInt x(bits.data(), part_size);
   BigInt y(&bits[part_size], part_size);

   m_public_key = domain().point(x, y);

   BOTAN_ASSERT(m_public_key.on_the_curve(),
{'fraction_non_alphanumeric': 0.143121426168853, 'fraction_numerical': 0.03834510595358224, 'mean_word_length': 3.734872611464968, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6800676', 'n_tokens_mistral': 2387, 'n_tokens_neox': 2171, 'n_words': 416}