10#include <botan/gost_3410.h>
12#include <botan/ber_dec.h>
13#include <botan/der_enc.h>
14#include <botan/reducer.h>
15#include <botan/internal/fmt.h>
16#include <botan/internal/pk_ops_impl.h>
17#include <botan/internal/point_mul.h>
24 const size_t part_size = bits.size() / 2;
27 for(
size_t i = 0; i != part_size / 2; ++i) {
28 std::swap(bits[i], bits[part_size - 1 - i]);
29 std::swap(bits[part_size + i], bits[2 * part_size - 1 - i]);
32 std::vector<uint8_t> output;
40 if(p_bits == 256 || p_bits == 512) {
41 return fmt(
"GOST-34.10-2012-{}", p_bits);
43 throw Encoding_Error(
"GOST-34.10-2012 is not defined for parameters of this size");
48 std::vector<uint8_t> params;
67 if(p_bits != 256 && p_bits != 512) {
68 throw Decoding_Error(
fmt(
"GOST-34.10-2012 is not defined for parameters of size {}", p_bits));
74 if(bits.size() != 2 * (p_bits / 8)) {
75 throw Decoding_Error(
"GOST-34.10-2020 invalid encoding of public key");
78 const size_t part_size = bits.size() / 2;
81 for(
size_t i = 0; i != part_size / 2; ++i) {
82 std::swap(bits[i], bits[part_size - 1 - i]);
83 std::swap(bits[part_size + i], bits[2 * part_size - 1 - i]);
86 BigInt x(bits.data(), part_size);
87 BigInt y(&bits[part_size], part_size);
97 if(p_bits != 256 && p_bits != 512) {
98 throw Decoding_Error(
fmt(
"GOST-34.10-2012 is not defined for parameters of size {}", p_bits));
108BigInt decode_le(
const uint8_t msg[],
size_t msg_len) {
111 for(
size_t i = 0; i != msg_le.size() / 2; ++i) {
112 std::swap(msg_le[i], msg_le[msg_le.size() - 1 - i]);
115 return BigInt(msg_le.data(), msg_le.size());
121class GOST_3410_Signature_Operation
final :
public PK_Ops::Signature_with_Hash {
123 GOST_3410_Signature_Operation(
const GOST_3410_PrivateKey& gost_3410, std::string_view emsa) :
124 PK_Ops::Signature_with_Hash(emsa), m_group(gost_3410.domain()), m_x(gost_3410.private_value()) {}
126 size_t signature_length()
const override {
return 2 * m_group.get_order_bytes(); }
128 AlgorithmIdentifier algorithm_identifier()
const override;
130 secure_vector<uint8_t> raw_sign(
const uint8_t msg[],
size_t msg_len, RandomNumberGenerator& rng)
override;
133 const EC_Group m_group;
135 std::vector<BigInt> m_ws;
138AlgorithmIdentifier GOST_3410_Signature_Operation::algorithm_identifier()
const {
139 const std::string hash_fn = hash_function();
143 std::string oid_name;
144 if(hash_fn ==
"GOST-R-34.11-94") {
145 oid_name =
"GOST-34.10/GOST-R-34.11-94";
146 }
else if(hash_fn ==
"Streebog-256" && p_bits == 256) {
147 oid_name =
"GOST-34.10-2012-256/Streebog-256";
148 }
else if(hash_fn ==
"Streebog-512" && p_bits == 512) {
149 oid_name =
"GOST-34.10-2012-512/Streebog-512";
150 }
else if(hash_fn ==
"SHA-256" && p_bits == 256) {
151 oid_name =
"GOST-34.10-2012-256/SHA-256";
154 if(oid_name.empty()) {
155 throw Not_Implemented(
"No encoding defined for GOST with " + hash_fn);
158 return AlgorithmIdentifier(oid_name, AlgorithmIdentifier::USE_EMPTY_PARAM);
163 RandomNumberGenerator& rng) {
166 BigInt e = decode_le(msg, msg_len);
177 if(r == 0 || s == 0) {
178 throw Internal_Error(
"GOST 34.10 signature generation failed, r/s equal to zero");
181 return BigInt::encode_fixed_length_int_pair(s, r, m_group.
get_order_bytes());
184std::string gost_hash_from_algid(
const AlgorithmIdentifier& alg_id) {
185 if(!alg_id.parameters_are_empty()) {
186 throw Decoding_Error(
"Unexpected non-empty AlgorithmIdentifier parameters for GOST 34.10 signature");
189 const std::string oid_str = alg_id.oid().to_formatted_string();
190 if(oid_str ==
"GOST-34.10/GOST-R-34.11-94") {
191 return "GOST-R-34.11-94";
193 if(oid_str ==
"GOST-34.10-2012-256/Streebog-256") {
194 return "Streebog-256";
196 if(oid_str ==
"GOST-34.10-2012-512/Streebog-512") {
197 return "Streebog-512";
199 if(oid_str ==
"GOST-34.10-2012-256/SHA-256") {
203 throw Decoding_Error(
fmt(
"Unknown OID ({}) for GOST 34.10 signatures", alg_id.oid()));
209class GOST_3410_Verification_Operation
final :
public PK_Ops::Verification_with_Hash {
211 GOST_3410_Verification_Operation(
const GOST_3410_PublicKey& gost, std::string_view padding) :
212 PK_Ops::Verification_with_Hash(padding),
213 m_group(gost.domain()),
214 m_gy_mul(m_group.get_base_point(), gost.public_point()) {}
216 GOST_3410_Verification_Operation(
const GOST_3410_PublicKey& gost,
const AlgorithmIdentifier& alg_id) :
217 PK_Ops::Verification_with_Hash(gost_hash_from_algid(alg_id)),
218 m_group(gost.domain()),
219 m_gy_mul(m_group.get_base_point(), gost.public_point()) {}
221 bool verify(
const uint8_t msg[],
size_t msg_len,
const uint8_t sig[],
size_t sig_len)
override;
224 const EC_Group m_group;
225 const EC_Point_Multi_Point_Precompute m_gy_mul;
228bool GOST_3410_Verification_Operation::verify(
const uint8_t msg[],
236 const BigInt s(sig, sig_len / 2);
237 const BigInt r(sig + sig_len / 2, sig_len / 2);
239 const BigInt& order = m_group.
get_order();
241 if(r <= 0 || r >= order || s <= 0 || s >= order) {
245 BigInt e = decode_le(msg, msg_len);
256 const EC_Point R = m_gy_mul.
multi_exp(z1, z2);
262 return (R.get_affine_x() == r);
268 return std::make_unique<GOST_3410_PrivateKey>(rng, domain());
272 std::string_view provider)
const {
273 if(provider ==
"base" || provider.empty()) {
274 return std::make_unique<GOST_3410_Verification_Operation>(*
this, params);
281 if(provider ==
"base" || provider.empty()) {
282 return std::make_unique<GOST_3410_Verification_Operation>(*
this, signature_algorithm);
289 std::string_view params,
290 std::string_view provider)
const {
291 if(provider ==
"base" || provider.empty()) {
292 return std::make_unique<GOST_3410_Signature_Operation>(*
this, params);
#define BOTAN_ASSERT(expr, assertion_made)
const std::vector< uint8_t > & parameters() const
virtual OID object_identifier() const
BER_Decoder & decode(bool &out)
BER_Decoder start_sequence()
DER_Encoder & start_sequence()
DER_Encoder & encode(bool b)
BigInt blinded_base_point_multiply_x(const BigInt &k, RandomNumberGenerator &rng, std::vector< BigInt > &ws) const
BigInt mod_order(const BigInt &x) const
BigInt multiply_mod_order(const BigInt &x, const BigInt &y) const
const BigInt & get_order() const
size_t get_p_bits() const
EC_Point point(const BigInt &x, const BigInt &y) const
static EC_Group from_OID(const OID &oid)
const OID & get_curve_oid() const
BigInt inverse_mod_order(const BigInt &x) const
BigInt random_scalar(RandomNumberGenerator &rng) const
size_t get_order_bytes() const
EC_Point multi_exp(const BigInt &k1, const BigInt &k2) const
secure_vector< uint8_t > xy_bytes() const
bool on_the_curve() const
const EC_Group & domain() const
const EC_Point & public_point() const
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
std::unique_ptr< Public_Key > public_key() const override
GOST_3410_PrivateKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
AlgorithmIdentifier algorithm_identifier() const override
GOST_3410_PublicKey()=default
std::string algo_name() const override
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
std::vector< uint8_t > public_key_bits() const override
int(* final)(unsigned char *, CTX *)
std::string fmt(std::string_view format, const T &... args)
std::vector< T, secure_allocator< T > > secure_vector