Botan  1.11.15
src/lib/pubkey/gost_3410/gost_3410.cpp
Go to the documentation of this file.
00001 /*
00002 * GOST 34.10-2001 implemenation
00003 * (C) 2007 Falko Strenzke, FlexSecure GmbH
00004 *          Manuel Hartl, FlexSecure GmbH
00005 * (C) 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/gost_3410.h>
00012 #include <botan/der_enc.h>
00013 #include <botan/ber_dec.h>
00014 
00015 namespace Botan {
00016 
00017 std::vector<byte> GOST_3410_PublicKey::x509_subject_public_key() const
00018    {
00019    // Trust CryptoPro to come up with something obnoxious
00020    const BigInt x = public_point().get_affine_x();
00021    const BigInt y = public_point().get_affine_y();
00022 
00023    size_t part_size = std::max(x.bytes(), y.bytes());
00024 
00025    std::vector<byte> bits(2*part_size);
00026 
00027    x.binary_encode(&bits[part_size - x.bytes()]);
00028    y.binary_encode(&bits[2*part_size - y.bytes()]);
00029 
00030    // Keys are stored in little endian format (WTF)
00031    for(size_t i = 0; i != part_size / 2; ++i)
00032       {
00033       std::swap(bits[i], bits[part_size-1-i]);
00034       std::swap(bits[part_size+i], bits[2*part_size-1-i]);
00035       }
00036 
00037    return DER_Encoder().encode(bits, OCTET_STRING).get_contents_unlocked();
00038    }
00039 
00040 AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
00041    {
00042    std::vector<byte> params =
00043       DER_Encoder().start_cons(SEQUENCE)
00044          .encode(OID(domain().get_oid()))
00045          .end_cons()
00046       .get_contents_unlocked();
00047 
00048    return AlgorithmIdentifier(get_oid(), params);
00049    }
00050 
00051 GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
00052                                          const secure_vector<byte>& key_bits)
00053    {
00054    OID ecc_param_id;
00055 
00056    // Also includes hash and cipher OIDs... brilliant design guys
00057    BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id);
00058 
00059    domain_params = EC_Group(ecc_param_id);
00060 
00061    secure_vector<byte> bits;
00062    BER_Decoder(key_bits).decode(bits, OCTET_STRING);
00063 
00064    const size_t part_size = bits.size() / 2;
00065 
00066    // Keys are stored in little endian format (WTF)
00067    for(size_t i = 0; i != part_size / 2; ++i)
00068       {
00069       std::swap(bits[i], bits[part_size-1-i]);
00070       std::swap(bits[part_size+i], bits[2*part_size-1-i]);
00071       }
00072 
00073    BigInt x(&bits[0], part_size);
00074    BigInt y(&bits[part_size], part_size);
00075 
00076    public_key = PointGFp(domain().get_curve(), x, y);
00077 
00078    BOTAN_ASSERT(public_key.on_the_curve(),
00079                 "Loaded GOST 34.10 public key is on the curve");
00080    }
00081 
00082 namespace {
00083 
00084 BigInt decode_le(const byte msg[], size_t msg_len)
00085    {
00086    secure_vector<byte> msg_le(msg, msg + msg_len);
00087 
00088    for(size_t i = 0; i != msg_le.size() / 2; ++i)
00089       std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
00090 
00091    return BigInt(&msg_le[0], msg_le.size());
00092    }
00093 
00094 /**
00095 * GOST-34.10 signature operation
00096 */
00097 class GOST_3410_Signature_Operation : public PK_Ops::Signature
00098    {
00099    public:
00100       typedef GOST_3410_PrivateKey Key_Type;
00101       GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410, const std::string&):
00102          base_point(gost_3410.domain().get_base_point()),
00103          order(gost_3410.domain().get_order()),
00104          x(gost_3410.private_value()) {}
00105 
00106       size_t message_parts() const { return 2; }
00107       size_t message_part_size() const { return order.bytes(); }
00108       size_t max_input_bits() const { return order.bits(); }
00109 
00110       secure_vector<byte> sign(const byte msg[], size_t msg_len,
00111                               RandomNumberGenerator& rng);
00112 
00113    private:
00114       const PointGFp& base_point;
00115       const BigInt& order;
00116       const BigInt& x;
00117    };
00118 
00119 secure_vector<byte>
00120 GOST_3410_Signature_Operation::sign(const byte msg[], size_t msg_len,
00121                                     RandomNumberGenerator& rng)
00122    {
00123    BigInt k;
00124    do
00125       k.randomize(rng, order.bits()-1);
00126    while(k >= order);
00127 
00128    BigInt e = decode_le(msg, msg_len);
00129 
00130    e %= order;
00131    if(e == 0)
00132       e = 1;
00133 
00134    PointGFp k_times_P = base_point * k;
00135    BOTAN_ASSERT(k_times_P.on_the_curve(), "GOST 34.10 k*g is on the curve");
00136 
00137    BigInt r = k_times_P.get_affine_x() % order;
00138 
00139    BigInt s = (r*x + k*e) % order;
00140 
00141    if(r == 0 || s == 0)
00142       throw Invalid_State("GOST 34.10: r == 0 || s == 0");
00143 
00144    secure_vector<byte> output(2*order.bytes());
00145    s.binary_encode(&output[output.size() / 2 - s.bytes()]);
00146    r.binary_encode(&output[output.size() - r.bytes()]);
00147    return output;
00148    }
00149 
00150 /**
00151 * GOST-34.10 verification operation
00152 */
00153 class GOST_3410_Verification_Operation : public PK_Ops::Verification
00154    {
00155    public:
00156       typedef GOST_3410_PublicKey Key_Type;
00157 
00158       GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost, const std::string&) :
00159          base_point(gost.domain().get_base_point()),
00160          public_point(gost.public_point()),
00161          order(gost.domain().get_order()) {}
00162 
00163       size_t message_parts() const { return 2; }
00164       size_t message_part_size() const { return order.bytes(); }
00165       size_t max_input_bits() const { return order.bits(); }
00166 
00167       bool with_recovery() const { return false; }
00168 
00169       bool verify(const byte msg[], size_t msg_len,
00170                   const byte sig[], size_t sig_len);
00171    private:
00172       const PointGFp& base_point;
00173       const PointGFp& public_point;
00174       const BigInt& order;
00175    };
00176 
00177 bool GOST_3410_Verification_Operation::verify(const byte msg[], size_t msg_len,
00178                                               const byte sig[], size_t sig_len)
00179    {
00180    if(sig_len != order.bytes()*2)
00181       return false;
00182 
00183    BigInt e = decode_le(msg, msg_len);
00184 
00185    BigInt s(sig, sig_len / 2);
00186    BigInt r(sig + sig_len / 2, sig_len / 2);
00187 
00188    if(r <= 0 || r >= order || s <= 0 || s >= order)
00189       return false;
00190 
00191    e %= order;
00192    if(e == 0)
00193       e = 1;
00194 
00195    BigInt v = inverse_mod(e, order);
00196 
00197    BigInt z1 = (s*v) % order;
00198    BigInt z2 = (-r*v) % order;
00199 
00200    PointGFp R = multi_exponentiate(base_point, z1,
00201                                    public_point, z2);
00202 
00203    if(R.is_zero())
00204      return false;
00205 
00206    return (R.get_affine_x() == r);
00207    }
00208 
00209 }
00210 
00211 BOTAN_REGISTER_PK_SIGNATURE_OP("GOST-34.10", GOST_3410_Signature_Operation);
00212 BOTAN_REGISTER_PK_VERIFY_OP("GOST-34.10", GOST_3410_Verification_Operation);
00213 
00214 }