Botan  1.11.15
src/lib/pubkey/ecdsa/ecdsa.cpp
Go to the documentation of this file.
00001 /*
00002 * ECDSA implemenation
00003 * (C) 2007 Manuel Hartl, FlexSecure GmbH
00004 *     2007 Falko Strenzke, FlexSecure GmbH
00005 *     2008-2010 Jack Lloyd
00006 *
00007 * Botan is released under the Simplified BSD License (see license.txt)
00008 */
00009 
00010 #include <botan/internal/pk_utils.h>
00011 #include <botan/ecdsa.h>
00012 #include <botan/reducer.h>
00013 #include <botan/keypair.h>
00014 #include <botan/rfc6979.h>
00015 
00016 namespace Botan {
00017 
00018 bool ECDSA_PrivateKey::check_key(RandomNumberGenerator& rng,
00019                                  bool strong) const
00020    {
00021    if(!public_point().on_the_curve())
00022       return false;
00023 
00024    if(!strong)
00025       return true;
00026 
00027    return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)");
00028    }
00029 
00030 namespace {
00031 
00032 /**
00033 * ECDSA signature operation
00034 */
00035 class ECDSA_Signature_Operation : public PK_Ops::Signature
00036    {
00037    public:
00038       typedef ECDSA_PrivateKey Key_Type;
00039 
00040       ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa,
00041                                 const std::string& emsa) :
00042          base_point(ecdsa.domain().get_base_point()),
00043          order(ecdsa.domain().get_order()),
00044          x(ecdsa.private_value()),
00045          mod_order(order),
00046          m_hash(hash_for_deterministic_signature(emsa))
00047          {
00048          }
00049 
00050       secure_vector<byte> sign(const byte msg[], size_t msg_len,
00051                               RandomNumberGenerator& rng);
00052 
00053       size_t message_parts() const { return 2; }
00054       size_t message_part_size() const { return order.bytes(); }
00055       size_t max_input_bits() const { return order.bits(); }
00056 
00057    private:
00058       const PointGFp& base_point;
00059       const BigInt& order;
00060       const BigInt& x;
00061       Modular_Reducer mod_order;
00062       std::string m_hash;
00063    };
00064 
00065 secure_vector<byte>
00066 ECDSA_Signature_Operation::sign(const byte msg[], size_t msg_len,
00067                                 RandomNumberGenerator&)
00068    {
00069    const BigInt m(msg, msg_len);
00070 
00071    const BigInt k = generate_rfc6979_nonce(x, order, m, m_hash);
00072 
00073    const PointGFp k_times_P = base_point * k;
00074    const BigInt r = mod_order.reduce(k_times_P.get_affine_x());
00075    const BigInt s = mod_order.multiply(inverse_mod(k, order), mul_add(x, r, m));
00076 
00077    // With overwhelming probability, a bug rather than actual zero r/s
00078    BOTAN_ASSERT(s != 0, "invalid s");
00079    BOTAN_ASSERT(r != 0, "invalid r");
00080 
00081    secure_vector<byte> output(2*order.bytes());
00082    r.binary_encode(&output[output.size() / 2 - r.bytes()]);
00083    s.binary_encode(&output[output.size() - s.bytes()]);
00084    return output;
00085    }
00086 
00087 /**
00088 * ECDSA verification operation
00089 */
00090 class ECDSA_Verification_Operation : public PK_Ops::Verification
00091    {
00092    public:
00093       typedef ECDSA_PublicKey Key_Type;
00094       ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa,
00095                                    const std::string&) :
00096          base_point(ecdsa.domain().get_base_point()),
00097          public_point(ecdsa.public_point()),
00098          order(ecdsa.domain().get_order())
00099          {
00100          }
00101 
00102       size_t message_parts() const { return 2; }
00103       size_t message_part_size() const { return order.bytes(); }
00104       size_t max_input_bits() const { return order.bits(); }
00105 
00106       bool with_recovery() const { return false; }
00107 
00108       bool verify(const byte msg[], size_t msg_len,
00109                   const byte sig[], size_t sig_len);
00110    private:
00111       const PointGFp& base_point;
00112       const PointGFp& public_point;
00113       const BigInt& order;
00114    };
00115 
00116 bool ECDSA_Verification_Operation::verify(const byte msg[], size_t msg_len,
00117                                           const byte sig[], size_t sig_len)
00118    {
00119    if(sig_len != order.bytes()*2)
00120       return false;
00121 
00122    BigInt e(msg, msg_len);
00123 
00124    BigInt r(sig, sig_len / 2);
00125    BigInt s(sig + sig_len / 2, sig_len / 2);
00126 
00127    if(r <= 0 || r >= order || s <= 0 || s >= order)
00128       return false;
00129 
00130    BigInt w = inverse_mod(s, order);
00131 
00132    PointGFp R = w * multi_exponentiate(base_point, e,
00133                                        public_point, r);
00134 
00135    if(R.is_zero())
00136       return false;
00137 
00138    return (R.get_affine_x() % order == r);
00139    }
00140 
00141 BOTAN_REGISTER_PK_SIGNATURE_OP("ECDSA", ECDSA_Signature_Operation);
00142 BOTAN_REGISTER_PK_VERIFY_OP("ECDSA", ECDSA_Verification_Operation);
00143 
00144 }
00145 
00146 }