Botan  1.11.15
src/lib/pubkey/ecc_key/ecc_key.cpp
Go to the documentation of this file.
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 }