Botan
1.11.15
|
00001 /* 00002 * ECC Key implemenation 00003 * (C) 2007 Manuel Hartl, FlexSecure GmbH 00004 * 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/ecc_key.h> 00011 #include <botan/x509_key.h> 00012 #include <botan/numthry.h> 00013 #include <botan/der_enc.h> 00014 #include <botan/ber_dec.h> 00015 #include <botan/secmem.h> 00016 #include <botan/point_gfp.h> 00017 #include <botan/workfactor.h> 00018 00019 namespace Botan { 00020 00021 size_t EC_PublicKey::estimated_strength() const 00022 { 00023 return ecp_work_factor(domain().get_curve().get_p().bits()); 00024 } 00025 00026 EC_PublicKey::EC_PublicKey(const EC_Group& dom_par, 00027 const PointGFp& pub_point) : 00028 domain_params(dom_par), public_key(pub_point), 00029 domain_encoding(EC_DOMPAR_ENC_EXPLICIT) 00030 { 00031 if(domain().get_curve() != public_point().get_curve()) 00032 throw Invalid_Argument("EC_PublicKey: curve mismatch in constructor"); 00033 } 00034 00035 EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, 00036 const secure_vector<byte>& key_bits) 00037 { 00038 domain_params = EC_Group(alg_id.parameters); 00039 domain_encoding = EC_DOMPAR_ENC_EXPLICIT; 00040 00041 public_key = OS2ECP(key_bits, domain().get_curve()); 00042 } 00043 00044 bool EC_PublicKey::check_key(RandomNumberGenerator&, 00045 bool) const 00046 { 00047 return public_point().on_the_curve(); 00048 } 00049 00050 AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const 00051 { 00052 return AlgorithmIdentifier(get_oid(), DER_domain()); 00053 } 00054 00055 std::vector<byte> EC_PublicKey::x509_subject_public_key() const 00056 { 00057 return unlock(EC2OSP(public_point(), PointGFp::COMPRESSED)); 00058 } 00059 00060 void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) 00061 { 00062 if(form != EC_DOMPAR_ENC_EXPLICIT && 00063 form != EC_DOMPAR_ENC_IMPLICITCA && 00064 form != EC_DOMPAR_ENC_OID) 00065 throw Invalid_Argument("Invalid encoding form for EC-key object specified"); 00066 00067 if((form == EC_DOMPAR_ENC_OID) && (domain_params.get_oid() == "")) 00068 throw Invalid_Argument("Invalid encoding form OID specified for " 00069 "EC-key object whose corresponding domain " 00070 "parameters are without oid"); 00071 00072 domain_encoding = form; 00073 } 00074 00075 const BigInt& EC_PrivateKey::private_value() const 00076 { 00077 if(private_key == 0) 00078 throw Invalid_State("EC_PrivateKey::private_value - uninitialized"); 00079 00080 return private_key; 00081 } 00082 00083 /** 00084 * EC_PrivateKey constructor 00085 */ 00086 EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, 00087 const EC_Group& ec_group, 00088 const BigInt& x) 00089 { 00090 domain_params = ec_group; 00091 domain_encoding = EC_DOMPAR_ENC_EXPLICIT; 00092 00093 if(x == 0) 00094 private_key = BigInt::random_integer(rng, 1, domain().get_order()); 00095 else 00096 private_key = x; 00097 00098 public_key = domain().get_base_point() * private_key; 00099 00100 BOTAN_ASSERT(public_key.on_the_curve(), 00101 "Generated public key point was on the curve"); 00102 } 00103 00104 secure_vector<byte> EC_PrivateKey::pkcs8_private_key() const 00105 { 00106 return DER_Encoder() 00107 .start_cons(SEQUENCE) 00108 .encode(static_cast<size_t>(1)) 00109 .encode(BigInt::encode_1363(private_key, private_key.bytes()), 00110 OCTET_STRING) 00111 .end_cons() 00112 .get_contents(); 00113 } 00114 00115 EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, 00116 const secure_vector<byte>& key_bits) 00117 { 00118 domain_params = EC_Group(alg_id.parameters); 00119 domain_encoding = EC_DOMPAR_ENC_EXPLICIT; 00120 00121 OID key_parameters; 00122 secure_vector<byte> public_key_bits; 00123 00124 BER_Decoder(key_bits) 00125 .start_cons(SEQUENCE) 00126 .decode_and_check<size_t>(1, "Unknown version code for ECC key") 00127 .decode_octet_string_bigint(private_key) 00128 .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE) 00129 .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE) 00130 .end_cons(); 00131 00132 if(!key_parameters.empty() && key_parameters != alg_id.oid) 00133 throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match"); 00134 00135 if(public_key_bits.empty()) 00136 { 00137 public_key = domain().get_base_point() * private_key; 00138 00139 BOTAN_ASSERT(public_key.on_the_curve(), 00140 "Public point derived from loaded key was on the curve"); 00141 } 00142 else 00143 { 00144 public_key = OS2ECP(public_key_bits, domain().get_curve()); 00145 // OS2ECP verifies that the point is on the curve 00146 } 00147 } 00148 00149 }