diff options
author | lloyd <[email protected]> | 2014-01-10 03:41:59 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2014-01-10 03:41:59 +0000 |
commit | 6894dca64c04936d07048c0e8cbf7e25858548c3 (patch) | |
tree | 5d572bfde9fe667dab14e3f04b5285a85d8acd95 /src/lib/pubkey/gost_3410 | |
parent | 9efa3be92442afb3d0b69890a36c7f122df18eda (diff) |
Move lib into src
Diffstat (limited to 'src/lib/pubkey/gost_3410')
-rw-r--r-- | src/lib/pubkey/gost_3410/gost_3410.cpp | 176 | ||||
-rw-r--r-- | src/lib/pubkey/gost_3410/gost_3410.h | 139 | ||||
-rw-r--r-- | src/lib/pubkey/gost_3410/info.txt | 13 |
3 files changed, 328 insertions, 0 deletions
diff --git a/src/lib/pubkey/gost_3410/gost_3410.cpp b/src/lib/pubkey/gost_3410/gost_3410.cpp new file mode 100644 index 000000000..9a1e6d85b --- /dev/null +++ b/src/lib/pubkey/gost_3410/gost_3410.cpp @@ -0,0 +1,176 @@ +/* +* GOST 34.10-2001 implemenation +* (C) 2007 Falko Strenzke, FlexSecure GmbH +* Manuel Hartl, FlexSecure GmbH +* (C) 2008-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/gost_3410.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> + +namespace Botan { + +std::vector<byte> GOST_3410_PublicKey::x509_subject_public_key() const + { + // Trust CryptoPro to come up with something obnoxious + 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<byte> 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]); + } + + return DER_Encoder().encode(bits, OCTET_STRING).get_contents_unlocked(); + } + +AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const + { + std::vector<byte> params = + DER_Encoder().start_cons(SEQUENCE) + .encode(OID(domain().get_oid())) + .end_cons() + .get_contents_unlocked(); + + return AlgorithmIdentifier(get_oid(), params); + } + +GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, + const secure_vector<byte>& key_bits) + { + OID ecc_param_id; + + // Also includes hash and cipher OIDs... brilliant design guys + BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id); + + domain_params = EC_Group(ecc_param_id); + + secure_vector<byte> bits; + BER_Decoder(key_bits).decode(bits, OCTET_STRING); + + 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[0], part_size); + BigInt y(&bits[part_size], part_size); + + public_key = PointGFp(domain().get_curve(), x, y); + + BOTAN_ASSERT(public_key.on_the_curve(), + "Loaded GOST 34.10 public key is on the curve"); + } + +namespace { + +BigInt decode_le(const byte msg[], size_t msg_len) + { + secure_vector<byte> msg_le(msg, msg + msg_len); + + for(size_t i = 0; i != msg_le.size() / 2; ++i) + std::swap(msg_le[i], msg_le[msg_le.size()-1-i]); + + return BigInt(&msg_le[0], msg_le.size()); + } + +} + +GOST_3410_Signature_Operation::GOST_3410_Signature_Operation( + const GOST_3410_PrivateKey& gost_3410) : + + base_point(gost_3410.domain().get_base_point()), + order(gost_3410.domain().get_order()), + x(gost_3410.private_value()) + { + } + +secure_vector<byte> +GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len, + RandomNumberGenerator& rng) + { + BigInt k; + do + k.randomize(rng, order.bits()-1); + while(k >= order); + + BigInt e = decode_le(msg, msg_len); + + e %= order; + if(e == 0) + e = 1; + + PointGFp k_times_P = base_point * k; + + BOTAN_ASSERT(k_times_P.on_the_curve(), + "GOST 34.10 k*g is on the curve"); + + BigInt r = k_times_P.get_affine_x() % order; + + BigInt s = (r*x + k*e) % order; + + if(r == 0 || s == 0) + throw Invalid_State("GOST 34.10: r == 0 || s == 0"); + + secure_vector<byte> output(2*order.bytes()); + s.binary_encode(&output[output.size() / 2 - s.bytes()]); + r.binary_encode(&output[output.size() - r.bytes()]); + return output; + } + +GOST_3410_Verification_Operation::GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost) : + base_point(gost.domain().get_base_point()), + public_point(gost.public_point()), + order(gost.domain().get_order()) + { + } + +bool GOST_3410_Verification_Operation::verify(const byte msg[], size_t msg_len, + const byte sig[], size_t sig_len) + { + if(sig_len != order.bytes()*2) + return false; + + BigInt e = decode_le(msg, msg_len); + + BigInt s(sig, sig_len / 2); + BigInt r(sig + sig_len / 2, sig_len / 2); + + if(r <= 0 || r >= order || s <= 0 || s >= order) + return false; + + e %= order; + if(e == 0) + e = 1; + + BigInt v = inverse_mod(e, order); + + BigInt z1 = (s*v) % order; + BigInt z2 = (-r*v) % order; + + PointGFp R = multi_exponentiate(base_point, z1, + public_point, z2); + + if(R.is_zero()) + return false; + + return (R.get_affine_x() == r); + } + +} diff --git a/src/lib/pubkey/gost_3410/gost_3410.h b/src/lib/pubkey/gost_3410/gost_3410.h new file mode 100644 index 000000000..6b1506b10 --- /dev/null +++ b/src/lib/pubkey/gost_3410/gost_3410.h @@ -0,0 +1,139 @@ +/* +* GOST 34.10-2001 +* (C) 2007 Falko Strenzke, FlexSecure GmbH +* Manuel Hartl, FlexSecure GmbH +* (C) 2008-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_GOST_3410_KEY_H__ +#define BOTAN_GOST_3410_KEY_H__ + +#include <botan/ecc_key.h> +#include <botan/pk_ops.h> + +namespace Botan { + +/** +* GOST-34.10 Public Key +*/ +class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey + { + public: + + /** + * Construct a public key from a given public point. + * @param dom_par the domain parameters associated with this key + * @param public_point the public point defining this key + */ + GOST_3410_PublicKey(const EC_Group& dom_par, + const PointGFp& public_point) : + EC_PublicKey(dom_par, public_point) {} + + /** + * Construct from X.509 algorithm id and subject public key bits + */ + GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, + const secure_vector<byte>& key_bits); + + /** + * Get this keys algorithm name. + * @result this keys algorithm name + */ + std::string algo_name() const { return "GOST-34.10"; } + + AlgorithmIdentifier algorithm_identifier() const; + + std::vector<byte> x509_subject_public_key() const; + + /** + * Get the maximum number of bits allowed to be fed to this key. + * This is the bitlength of the order of the base point. + + * @result the maximum number of input bits + */ + size_t max_input_bits() const { return domain().get_order().bits(); } + + size_t message_parts() const { return 2; } + + size_t message_part_size() const + { return domain().get_order().bytes(); } + + protected: + GOST_3410_PublicKey() {} + }; + +/** +* GOST-34.10 Private Key +*/ +class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey, + public EC_PrivateKey + { + public: + + GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id, + const secure_vector<byte>& key_bits) : + EC_PrivateKey(alg_id, key_bits) {} + + /** + * Generate a new private key + * @param rng a random number generator + * @param domain parameters to used for this key + * @param x the private key; if zero, a new random key is generated + */ + GOST_3410_PrivateKey(RandomNumberGenerator& rng, + const EC_Group& domain, + const BigInt& x = 0) : + EC_PrivateKey(rng, domain, x) {} + + AlgorithmIdentifier pkcs8_algorithm_identifier() const + { return EC_PublicKey::algorithm_identifier(); } + }; + +/** +* GOST-34.10 signature operation +*/ +class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature + { + public: + GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410); + + size_t message_parts() const { return 2; } + size_t message_part_size() const { return order.bytes(); } + size_t max_input_bits() const { return order.bits(); } + + secure_vector<byte> sign(const byte msg[], size_t msg_len, + RandomNumberGenerator& rng); + + private: + const PointGFp& base_point; + const BigInt& order; + const BigInt& x; + }; + +/** +* GOST-34.10 verification operation +*/ +class BOTAN_DLL GOST_3410_Verification_Operation : public PK_Ops::Verification + { + public: + GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost); + + size_t message_parts() const { return 2; } + size_t message_part_size() const { return order.bytes(); } + size_t max_input_bits() const { return order.bits(); } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], size_t msg_len, + const byte sig[], size_t sig_len); + private: + const PointGFp& base_point; + const PointGFp& public_point; + const BigInt& order; + }; + +} + +#endif diff --git a/src/lib/pubkey/gost_3410/info.txt b/src/lib/pubkey/gost_3410/info.txt new file mode 100644 index 000000000..63521d3dd --- /dev/null +++ b/src/lib/pubkey/gost_3410/info.txt @@ -0,0 +1,13 @@ +define GOST_34_10_2001 20131128 + +load_on auto + +<requires> +alloc +asn1 +ec_group +ecc_key +libstate +numbertheory +rng +</requires> |