Botan
1.11.15
|
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 }