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>
27 std::vector<uint8_t> bits(2 * part_size);
33 for(
size_t i = 0; i != part_size / 2; ++i) {
34 std::swap(bits[i], bits[part_size - 1 - i]);
35 std::swap(bits[part_size + i], bits[2 * part_size - 1 - i]);
38 std::vector<uint8_t> output;
46 if(p_bits == 256 || p_bits == 512) {
47 return fmt(
"GOST-34.10-2012-{}", p_bits);
49 throw Encoding_Error(
"GOST-34.10-2012 is not defined for parameters of this size");
54 std::vector<uint8_t> params;
73 if(p_bits != 256 && p_bits != 512) {
74 throw Decoding_Error(
fmt(
"GOST-34.10-2012 is not defined for parameters of size {}", p_bits));
80 if(bits.size() != 2 * (p_bits / 8)) {
81 throw Decoding_Error(
"GOST-34.10-2020 invalid encoding of public key");
84 const size_t part_size = bits.size() / 2;
87 for(
size_t i = 0; i != part_size / 2; ++i) {
88 std::swap(bits[i], bits[part_size - 1 - i]);
89 std::swap(bits[part_size + i], bits[2 * part_size - 1 - i]);
92 BigInt x(bits.data(), part_size);
93 BigInt y(&bits[part_size], part_size);
103 if(p_bits != 256 && p_bits != 512) {
104 throw Decoding_Error(
fmt(
"GOST-34.10-2012 is not defined for parameters of size {}", p_bits));
114BigInt decode_le(
const uint8_t msg[],
size_t msg_len) {
117 for(
size_t i = 0; i != msg_le.size() / 2; ++i) {
118 std::swap(msg_le[i], msg_le[msg_le.size() - 1 - i]);
121 return BigInt(msg_le.data(), msg_le.size());
127class GOST_3410_Signature_Operation
final :
public PK_Ops::Signature_with_Hash {
129 GOST_3410_Signature_Operation(
const GOST_3410_PrivateKey& gost_3410, std::string_view emsa) :
130 PK_Ops::Signature_with_Hash(emsa), m_group(gost_3410.domain()), m_x(gost_3410.private_value()) {}
132 size_t signature_length()
const override {
return 2 * m_group.get_order_bytes(); }
134 AlgorithmIdentifier algorithm_identifier()
const override;
136 secure_vector<uint8_t> raw_sign(
const uint8_t msg[],
size_t msg_len, RandomNumberGenerator& rng)
override;
139 const EC_Group m_group;
141 std::vector<BigInt> m_ws;
144AlgorithmIdentifier GOST_3410_Signature_Operation::algorithm_identifier()
const {
145 const std::string hash_fn = hash_function();
149 std::string oid_name;
150 if(hash_fn ==
"GOST-R-34.11-94") {
151 oid_name =
"GOST-34.10/GOST-R-34.11-94";
152 }
else if(hash_fn ==
"Streebog-256" && p_bits == 256) {
153 oid_name =
"GOST-34.10-2012-256/Streebog-256";
154 }
else if(hash_fn ==
"Streebog-512" && p_bits == 512) {
155 oid_name =
"GOST-34.10-2012-512/Streebog-512";
156 }
else if(hash_fn ==
"SHA-256" && p_bits == 256) {
157 oid_name =
"GOST-34.10-2012-256/SHA-256";
160 if(oid_name.empty()) {
161 throw Not_Implemented(
"No encoding defined for GOST with " + hash_fn);
164 return AlgorithmIdentifier(oid_name, AlgorithmIdentifier::USE_EMPTY_PARAM);
167secure_vector<uint8_t> GOST_3410_Signature_Operation::raw_sign(
const uint8_t msg[],
169 RandomNumberGenerator& rng) {
172 BigInt e = decode_le(msg, msg_len);
183 if(r == 0 || s == 0) {
184 throw Internal_Error(
"GOST 34.10 signature generation failed, r/s equal to zero");
187 return BigInt::encode_fixed_length_int_pair(s, r, m_group.
get_order_bytes());
190std::string gost_hash_from_algid(
const AlgorithmIdentifier& alg_id) {
191 if(!alg_id.parameters_are_empty()) {
192 throw Decoding_Error(
"Unexpected non-empty AlgorithmIdentifier parameters for GOST 34.10 signature");
195 const std::string oid_str = alg_id.oid().to_formatted_string();
196 if(oid_str ==
"GOST-34.10/GOST-R-34.11-94") {
197 return "GOST-R-34.11-94";
199 if(oid_str ==
"GOST-34.10-2012-256/Streebog-256") {
200 return "Streebog-256";
202 if(oid_str ==
"GOST-34.10-2012-512/Streebog-512") {
203 return "Streebog-512";
205 if(oid_str ==
"GOST-34.10-2012-256/SHA-256") {
209 throw Decoding_Error(
fmt(
"Unknown OID ({}) for GOST 34.10 signatures", alg_id.oid()));
215class GOST_3410_Verification_Operation
final :
public PK_Ops::Verification_with_Hash {
217 GOST_3410_Verification_Operation(
const GOST_3410_PublicKey& gost, std::string_view padding) :
218 PK_Ops::Verification_with_Hash(padding),
219 m_group(gost.domain()),
220 m_gy_mul(m_group.get_base_point(), gost.public_point()) {}
222 GOST_3410_Verification_Operation(
const GOST_3410_PublicKey& gost,
const AlgorithmIdentifier& alg_id) :
223 PK_Ops::Verification_with_Hash(gost_hash_from_algid(alg_id)),
224 m_group(gost.domain()),
225 m_gy_mul(m_group.get_base_point(), gost.public_point()) {}
227 bool verify(
const uint8_t msg[],
size_t msg_len,
const uint8_t sig[],
size_t sig_len)
override;
230 const EC_Group m_group;
231 const EC_Point_Multi_Point_Precompute m_gy_mul;
234bool GOST_3410_Verification_Operation::verify(
const uint8_t msg[],
242 const BigInt s(sig, sig_len / 2);
243 const BigInt r(sig + sig_len / 2, sig_len / 2);
245 const BigInt& order = m_group.
get_order();
247 if(r <= 0 || r >= order || s <= 0 || s >= order) {
251 BigInt e = decode_le(msg, msg_len);
262 const EC_Point R = m_gy_mul.
multi_exp(z1, z2);
268 return (R.get_affine_x() == r);
274 return std::make_unique<GOST_3410_PrivateKey>(rng, domain());
278 std::string_view provider)
const {
279 if(provider ==
"base" || provider.empty()) {
280 return std::make_unique<GOST_3410_Verification_Operation>(*
this, params);
287 if(provider ==
"base" || provider.empty()) {
288 return std::make_unique<GOST_3410_Verification_Operation>(*
this, signature_algorithm);
295 std::string_view params,
296 std::string_view provider)
const {
297 if(provider ==
"base" || provider.empty()) {
298 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()
void binary_encode(uint8_t buf[]) const
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
const OID & get_curve_oid() const
BigInt inverse_mod_order(const BigInt &x) const
size_t get_p_bytes() const
BigInt random_scalar(RandomNumberGenerator &rng) const
size_t get_order_bytes() const
EC_Point multi_exp(const BigInt &k1, const BigInt &k2) const
BigInt get_affine_x() const
bool on_the_curve() const
BigInt get_affine_y() 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