diff options
author | lloyd <[email protected]> | 2011-04-08 18:13:41 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2011-04-08 18:13:41 +0000 |
commit | 8b543e804375a788ae71d461c0f8cf5d4193fc25 (patch) | |
tree | 6177931cd84a9be204cdab6e62729954e69e0421 | |
parent | 3b66bfd4da97189ec275e5f85b9f85009d3f8370 (diff) |
ECC private keys had two different constructors, one taking a group
and a random number generator, and the other taking a group and a
preset private key value. The DL private keys instead have on
constructor for this; if the x value is zero, then a new random key is
created. For consistency, do this with ECC as well.
ECDH actually didn't have one of these constructors, forcing you to
either load from PKCS #8 or else use a random key.
Rename EC_Domain_Params to EC_Group, with a typedef for compatability.
More doc updates.
Update mtn ignores for Sphinx output
42 files changed, 281 insertions, 556 deletions
diff --git a/.mtn-ignore b/.mtn-ignore index 8be5a95a8..0c89431f5 100644 --- a/.mtn-ignore +++ b/.mtn-ignore @@ -9,9 +9,10 @@ callgrind.out.* ^checks/ecc_testdata/rsa_private.pkcs8.pem$ ^checks/ecc_testdata/wo_dompar_private.pkcs8.pem$ ^checks/nist_tests/x509test$ +^doc/_build$ +^doc/_static$ ^doc/botan.doxy$ ^doc/doxygen$ -^doc/[a-z]+\.(pdf|log|toc)$ ^doc/examples/.*\.pem$ ^doc/examples/[a-z0-9_]+$ ^src/wrap/perl-xs/Botan.(bs|c)$ @@ -19,3 +20,4 @@ callgrind.out.* ^src/wrap/perl-xs/.*blib$ ^[a-z]+\.(exe|dll)(\.manifest)?$ ^[a-z]+\.(exp|lib)$ +^libbotan\.so\..* diff --git a/checks/cvc_tests.cpp b/checks/cvc_tests.cpp index acc6b91cb..334fb8581 100644 --- a/checks/cvc_tests.cpp +++ b/checks/cvc_tests.cpp @@ -90,7 +90,7 @@ void test_enc_gen_selfsigned(RandomNumberGenerator& rng) opts.hash_alg = "SHA-256"; // creating a non sense selfsigned cert w/o dom pars - EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); + EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); ECDSA_PrivateKey key(rng, dom_pars); key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); EAC1_1_CVC cert = CVC_EAC::create_self_signed_cert(key, opts, rng); @@ -200,7 +200,7 @@ void test_enc_gen_req(RandomNumberGenerator& rng) opts.hash_alg = "SHA-160"; // creating a non sense selfsigned cert w/o dom pars - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); ECDSA_PrivateKey key(rng, dom_pars); key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); EAC1_1_Req req = CVC_EAC::create_cvc_req(key, opts.chr, opts.hash_alg, rng); @@ -225,7 +225,7 @@ void test_cvc_req_ext(RandomNumberGenerator&) std::cout << "." << std::flush; EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der"); - EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" + EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" //req_in.set_domain_parameters(dom_pars); std::auto_ptr<Public_Key> p_pk(req_in.subject_public_key()); ECDSA_PublicKey* p_ecdsa_pk = dynamic_cast<ECDSA_PublicKey*>(p_pk.get()); @@ -240,7 +240,7 @@ void test_cvc_ado_ext(RandomNumberGenerator&) std::cout << "." << std::flush; EAC1_1_ADO req_in(TEST_DATA_DIR "/ado.cvcreq"); - EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" + EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" //cout << "car = " << req_in.get_car().value() << std::endl; //req_in.set_domain_parameters(dom_pars); } @@ -255,7 +255,7 @@ void test_cvc_ado_creation(RandomNumberGenerator& rng) opts.hash_alg = "SHA-256"; // creating a non sense selfsigned cert w/o dom pars - EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); + EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); //cout << "mod = " << hex << dom_pars.get_curve().get_p() << std::endl; ECDSA_PrivateKey req_key(rng, dom_pars); req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); @@ -299,7 +299,7 @@ void test_cvc_ado_comparison(RandomNumberGenerator& rng) opts.hash_alg = "SHA-224"; // creating a non sense selfsigned cert w/o dom pars - EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); + EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.11")); ECDSA_PrivateKey req_key(rng, dom_pars); req_key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); //EAC1_1_Req req = CVC_EAC::create_cvc_req(req_key, opts); @@ -420,14 +420,14 @@ void test_copy_and_assignment(RandomNumberGenerator&) CHECK(cert_in == cert_ass); EAC1_1_ADO ado_in(TEST_DATA_DIR "/ado.cvcreq"); - //EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" + //EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" EAC1_1_ADO ado_cp(ado_in); EAC1_1_ADO ado_ass = ado_in; CHECK(ado_in == ado_cp); CHECK(ado_in == ado_ass); EAC1_1_Req req_in(TEST_DATA_DIR "/DE1_flen_chars_cvcRequest_ECDSA.der"); - //EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" + //EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" EAC1_1_Req req_cp(req_in); EAC1_1_Req req_ass = req_in; CHECK(req_in == req_cp); @@ -488,7 +488,7 @@ void test_cvc_chain(RandomNumberGenerator& rng) { std::cout << "." << std::flush; - EC_Domain_Params dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" + EC_Group dom_pars(OID("1.3.36.3.3.2.8.1.1.5")); // "german curve" ECDSA_PrivateKey cvca_privk(rng, dom_pars); std::string hash("SHA-224"); ASN1_Car car("DECVCA00001"); diff --git a/checks/ec_tests.cpp b/checks/ec_tests.cpp index e299fbcc0..bad0d8912 100644 --- a/checks/ec_tests.cpp +++ b/checks/ec_tests.cpp @@ -172,7 +172,7 @@ void test_point_transformation () std::cout << "." << std::flush; // get a vailid point - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); PointGFp p = dom_pars.get_base_point(); // get a copy @@ -186,7 +186,7 @@ void test_point_mult () { std::cout << "." << std::flush; - EC_Domain_Params secp160r1(OIDS::lookup("secp160r1")); + EC_Group secp160r1(OIDS::lookup("secp160r1")); const CurveGFp& curve = secp160r1.get_curve(); @@ -637,9 +637,9 @@ void test_gfp_store_restore() std::cout << "." << std::flush; // generate point - //EC_Domain_Params dom_pars = global_config().get_ec_dompar("1.3.132.0.8"); - //EC_Domain_Params dom_pars("1.3.132.0.8"); - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + //EC_Group dom_pars = global_config().get_ec_dompar("1.3.132.0.8"); + //EC_Group dom_pars("1.3.132.0.8"); + EC_Group dom_pars(OID("1.3.132.0.8")); PointGFp p = dom_pars.get_base_point(); //store point (to std::string) @@ -724,7 +724,7 @@ void test_mult_by_order() std::cout << "." << std::flush; // generate point - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); PointGFp p = dom_pars.get_base_point(); PointGFp shouldBeZero = p * dom_pars.get_order(); @@ -735,7 +735,7 @@ void test_point_swap(RandomNumberGenerator& rng) { std::cout << "." << std::flush; - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); PointGFp a(create_random_point(rng, dom_pars.get_curve())); PointGFp b(create_random_point(rng, dom_pars.get_curve())); @@ -756,7 +756,7 @@ void test_point_swap(RandomNumberGenerator& rng) void test_mult_sec_mass(RandomNumberGenerator& rng) { - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); for(int i = 0; i<50; i++) { std::cout << "." << std::flush; @@ -775,7 +775,7 @@ void test_curve_cp_ctor() { std::cout << "." << std::flush; - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); CurveGFp curve(dom_pars.get_curve()); } diff --git a/checks/ecdh.cpp b/checks/ecdh.cpp index a63742f2f..c641796d6 100644 --- a/checks/ecdh.cpp +++ b/checks/ecdh.cpp @@ -33,7 +33,7 @@ void test_ecdh_normal_derivation(RandomNumberGenerator& rng) { std::cout << "." << std::flush; - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); ECDH_PrivateKey private_a(rng, dom_pars); @@ -65,7 +65,7 @@ void test_ecdh_some_dp(RandomNumberGenerator& rng) std::cout << "." << std::flush; OID oid(oids[i]); - EC_Domain_Params dom_pars(oid); + EC_Group dom_pars(oid); ECDH_PrivateKey private_a(rng, dom_pars); ECDH_PrivateKey private_b(rng, dom_pars); @@ -91,7 +91,7 @@ void test_ecdh_der_derivation(RandomNumberGenerator& rng) for(u32bit i = 0; i< oids.size(); i++) { OID oid(oids[i]); - EC_Domain_Params dom_pars(oid); + EC_Group dom_pars(oid); ECDH_PrivateKey private_a(rng, dom_pars); ECDH_PrivateKey private_b(rng, dom_pars); diff --git a/checks/ecdsa.cpp b/checks/ecdsa.cpp index 12f62abba..58f76c9ba 100644 --- a/checks/ecdsa.cpp +++ b/checks/ecdsa.cpp @@ -48,7 +48,7 @@ void test_hash_larger_than_n(RandomNumberGenerator& rng) { std::cout << "." << std::flush; - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); // secp160r1 + EC_Group dom_pars(OID("1.3.132.0.8")); // secp160r1 // n = 0x0100000000000000000001f4c8f927aed3ca752257 (21 bytes) // -> shouldn't work with SHA224 which outputs 28 bytes @@ -137,7 +137,7 @@ void test_sign_then_ver(RandomNumberGenerator& rng) { std::cout << '.' << std::flush; - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); ECDSA_PrivateKey ecdsa(rng, dom_pars); PK_Signer signer(ecdsa, "EMSA1(SHA-1)"); @@ -165,7 +165,7 @@ bool test_ec_sign(RandomNumberGenerator& rng) try { - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); ECDSA_PrivateKey priv_key(rng, dom_pars); std::string pem_encoded_key = PKCS8::PEM_encode(priv_key); @@ -229,7 +229,7 @@ void test_create_pkcs8(RandomNumberGenerator& rng) std::ofstream rsa_priv_key(TEST_DATA_DIR "/rsa_private.pkcs8.pem"); rsa_priv_key << PKCS8::PEM_encode(rsa_key); - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); ECDSA_PrivateKey key(rng, dom_pars); // later used by other tests :( @@ -246,7 +246,7 @@ void test_create_and_verify(RandomNumberGenerator& rng) { std::cout << "." << std::flush; - EC_Domain_Params dom_pars(OID("1.3.132.0.8")); + EC_Group dom_pars(OID("1.3.132.0.8")); ECDSA_PrivateKey key(rng, dom_pars); std::ofstream priv_key(TEST_DATA_DIR "/dompar_private.pkcs8.pem"); priv_key << PKCS8::PEM_encode(key); @@ -281,7 +281,7 @@ void test_create_and_verify(RandomNumberGenerator& rng) CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp); PointGFp p_G = OS2ECP ( sv_G_secp_comp, curve ); - EC_Domain_Params dom_params(curve, p_G, bi_order_g, BigInt(1)); + EC_Group dom_params(curve, p_G, bi_order_g, BigInt(1)); if(!p_G.on_the_curve()) throw Internal_Error("Point not on the curve"); @@ -337,7 +337,7 @@ void test_curve_registry(RandomNumberGenerator& rng) try { OID oid(oids[i]); - EC_Domain_Params dom_pars(oid); + EC_Group dom_pars(oid); ECDSA_PrivateKey ecdsa(rng, dom_pars); PK_Signer signer(ecdsa, "EMSA1(SHA-1)"); diff --git a/checks/pk.cpp b/checks/pk.cpp index f38cf97a6..6291b1566 100644 --- a/checks/pk.cpp +++ b/checks/pk.cpp @@ -498,15 +498,16 @@ u32bit validate_dsa_sig(const std::string& algo, } u32bit validate_ecdsa_sig(const std::string& algo, - const std::vector<std::string>& str) + const std::vector<std::string>& str, + RandomNumberGenerator& rng) { if(str.size() != 5) throw std::runtime_error("Invalid input from pk_valid.dat"); #if defined(BOTAN_HAS_ECDSA) - EC_Domain_Params group(OIDS::lookup(str[0])); - ECDSA_PrivateKey ecdsa(group, to_bigint(str[1])); + EC_Group group(OIDS::lookup(str[0])); + ECDSA_PrivateKey ecdsa(rng, group, to_bigint(str[1])); std::string emsa = algo.substr(6, std::string::npos); @@ -529,7 +530,7 @@ u32bit validate_gost_ver(const std::string& algo, #if defined(BOTAN_HAS_GOST_34_10_2001) - EC_Domain_Params group(OIDS::lookup(str[0])); + EC_Group group(OIDS::lookup(str[0])); PointGFp public_point = OS2ECP(hex_decode(str[1]), group.get_curve()); @@ -696,7 +697,7 @@ void do_pk_keygen_tests(RandomNumberGenerator& rng) #define EC_KEY(TYPE, GROUP) \ { \ - TYPE key(rng, EC_Domain_Params(OIDS::lookup(GROUP))); \ + TYPE key(rng, EC_Group(OIDS::lookup(GROUP))); \ key.check_key(rng, true); \ validate_save_and_load(&key, rng); \ std::cout << '.' << std::flush; \ @@ -855,7 +856,7 @@ u32bit do_pk_validation_tests(const std::string& filename, new_errors = validate_dsa_ver(algorithm, substr); else if(algorithm.find("ECDSA/") == 0) - new_errors = validate_ecdsa_sig(algorithm, substr); + new_errors = validate_ecdsa_sig(algorithm, substr, rng); else if(algorithm.find("GOST_3410_VA/") == 0) new_errors = validate_gost_ver(algorithm, substr); diff --git a/checks/pk_bench.cpp b/checks/pk_bench.cpp index 348cb7ff1..b0e689b0c 100644 --- a/checks/pk_bench.cpp +++ b/checks/pk_bench.cpp @@ -305,7 +305,7 @@ void benchmark_ecdsa(RandomNumberGenerator& rng, { for(size_t j = 0; ec_domains[j]; j++) { - EC_Domain_Params params(OIDS::lookup(ec_domains[j])); + EC_Group params(ec_domains[j]); const size_t pbits = params.get_curve().get_p().bits(); @@ -354,7 +354,7 @@ void benchmark_gost_3410(RandomNumberGenerator& rng, { for(size_t j = 0; ec_domains[j]; j++) { - EC_Domain_Params params(OIDS::lookup(ec_domains[j])); + EC_Group params(ec_domains[j]); const size_t pbits = params.get_curve().get_p().bits(); @@ -396,7 +396,7 @@ void benchmark_ecdh(RandomNumberGenerator& rng, { for(size_t j = 0; ec_domains[j]; j++) { - EC_Domain_Params params(OIDS::lookup(ec_domains[j])); + EC_Group params(ec_domains[j]); size_t pbits = params.get_curve().get_p().bits(); diff --git a/checks/x509.cpp b/checks/x509.cpp index 43d374411..8c6cd8187 100644 --- a/checks/x509.cpp +++ b/checks/x509.cpp @@ -159,7 +159,7 @@ void do_x509_tests(RandomNumberGenerator& rng) /* Create user #2's key and cert request */ std::cout << '.' << std::flush; #if defined(BOTAN_HAS_ECDSA) - EC_Domain_Params ecc_domain(OID("1.2.840.10045.3.1.7")); + EC_Group ecc_domain(OID("1.2.840.10045.3.1.7")); ECDSA_PrivateKey user2_key(rng, ecc_domain); #else RSA_PrivateKey user2_key(rng, 1024); diff --git a/doc/Makefile b/doc/Makefile index 152fa3e09..e183a36ec 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build diff --git a/doc/examples/GNUmakefile b/doc/examples/GNUmakefile index c386f4390..44fcfeea5 100644 --- a/doc/examples/GNUmakefile +++ b/doc/examples/GNUmakefile @@ -2,8 +2,8 @@ BOTAN_CONFIG = botan-config CXX = g++ -CFLAGS = -O2 -ansi -W -Wall -I../build/include -LIBS = -L.. -lbotan +CFLAGS = -O2 -ansi -W -Wall -I../../build/include +LIBS = -L../.. -lbotan SRCS=$(wildcard *.cpp) diff --git a/doc/examples/asn1.cpp b/doc/examples/asn1.cpp index b0a6aa104..bb891d746 100644 --- a/doc/examples/asn1.cpp +++ b/doc/examples/asn1.cpp @@ -1,37 +1,3 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* - A simple ASN.1 parser, similiar to 'dumpasn1' or 'openssl asn1parse', though - without some of the bells and whistles of those. Primarily used for testing - the BER decoder. The output format is modeled loosely on 'asn1parse -i' - - The output is actually less precise than the other decoders named, because - the underlying BER_Decoder hides quite a bit from userspace, such as the use - of indefinite length encodings (and the EOC markers). At some point it will - also hide the constructed string types from the user, but right now you'll - seem them as-is. - - Written by Jack Lloyd, November 9-10, 2003 - - Nov 22: Updated to new BER_Object format (tag -> class_tag/type_tag) - - Nov 25: Much improved BIT STRING output - Can deal with non-constructed taggings - Can produce UTF-8 output -*/ - -// Set this if your terminal understands UTF-8; otherwise output is in Latin-1 -#define UTF8_TERMINAL 1 - -/* - What level the outermost layer of stuff is at. Probably 0 or 1; asn1parse - uses 0 as the outermost, while 1 makes more sense to me. 2+ doesn't make - much sense at all. -*/ -#define INITIAL_LEVEL 0 - #include <botan/botan.h> #include <botan/bigint.h> #include <botan/der_enc.h> @@ -45,6 +11,16 @@ using namespace Botan; #include <stdio.h> #include <ctype.h> +// Set this if your terminal understands UTF-8; otherwise output is in Latin-1 +#define UTF8_TERMINAL 1 + +/* + What level the outermost layer of stuff is at. Probably 0 or 1; asn1parse + uses 0 as the outermost, while 1 makes more sense to me. 2+ doesn't make + much sense at all. +*/ +#define INITIAL_LEVEL 0 + void decode(BER_Decoder&, u32bit); void emit(const std::string&, u32bit, u32bit, const std::string& = ""); std::string type_name(ASN1_Tag); @@ -57,7 +33,7 @@ int main(int argc, char* argv[]) return 1; } - Botan::LibraryInitializer init; + LibraryInitializer init; try { DataSource_Stream in(argv[1]); @@ -83,7 +59,7 @@ int main(int argc, char* argv[]) return 0; } -void decode(BER_Decoder& decoder, u32bit level) +void decode(BER_Decoder& decoder, size_t level) { BER_Object obj = decoder.get_next_object(); @@ -91,7 +67,7 @@ void decode(BER_Decoder& decoder, u32bit level) { const ASN1_Tag type_tag = obj.type_tag; const ASN1_Tag class_tag = obj.class_tag; - const u32bit length = obj.value.size(); + const size_t length = obj.value.size(); /* hack to insert the tag+length back in front of the stuff now that we've gotten the type info */ @@ -142,8 +118,8 @@ void decode(BER_Decoder& decoder, u32bit level) { bool not_text = false; - for(u32bit j = 0; j != bits.size(); j++) - if(!isgraph(bits[j]) && !isspace(bits[j])) + for(size_t i = 0; i != bits.size(); ++i) + if(!isgraph(bits[i]) && !isspace(bits[i])) not_text = true; Pipe pipe(((not_text) ? new Hex_Encoder : 0)); @@ -176,8 +152,8 @@ void decode(BER_Decoder& decoder, u32bit level) rep = BigInt::encode(number, BigInt::Hexadecimal); std::string str; - for(u32bit j = 0; j != rep.size(); j++) - str += (char)rep[j]; + for(size_t i = 0; i != rep.size(); ++i) + str += (char)rep[i]; emit(type_name(type_tag), level, length, str); } @@ -198,8 +174,8 @@ void decode(BER_Decoder& decoder, u32bit level) data.decode(bits, type_tag); bool not_text = false; - for(u32bit j = 0; j != bits.size(); j++) - if(!isgraph(bits[j]) && !isspace(bits[j])) + for(size_t i = 0; i != bits.size(); ++i) + if(!isgraph(bits[i]) && !isspace(bits[i])) not_text = true; Pipe pipe(((not_text) ? new Hex_Encoder : 0)); @@ -213,14 +189,14 @@ void decode(BER_Decoder& decoder, u32bit level) std::vector<bool> bit_set; - for(u32bit j = 0; j != bits.size(); j++) - for(u32bit k = 0; k != 8; k++) - bit_set.push_back((bool)((bits[bits.size()-j-1] >> (7-k)) & 1)); + for(size_t i = 0; i != bits.size(); ++i) + for(size_t j = 0; j != 8; ++j) + bit_set.push_back((bool)((bits[bits.size()-i-1] >> (7-j)) & 1)); std::string bit_str; - for(u32bit j = 0; j != bit_set.size(); j++) + for(size_t i = 0; i != bit_set.size(); ++i) { - bool the_bit = bit_set[bit_set.size()-j-1]; + bool the_bit = bit_set[bit_set.size()-i-1]; if(!the_bit && bit_str.size() == 0) continue; @@ -260,15 +236,15 @@ void decode(BER_Decoder& decoder, u32bit level) } } -void emit(const std::string& type, u32bit level, u32bit length, +void emit(const std::string& type, size_t level, size_t length, const std::string& value) { - const u32bit LIMIT = 128; - const u32bit BIN_LIMIT = 64; + const size_t LIMIT = 128; + const size_t BIN_LIMIT = 64; int written = 0; written += printf(" d=%2d, l=%4d: ", level, length); - for(u32bit j = INITIAL_LEVEL; j != level; j++) + for(size_t i = INITIAL_LEVEL; i != level; ++i) written += printf(" "); written += printf("%s ", type.c_str()); diff --git a/doc/examples/ca.cpp b/doc/examples/ca.cpp index 8dd3e981f..7a3e6daf9 100644 --- a/doc/examples/ca.cpp +++ b/doc/examples/ca.cpp @@ -1,20 +1,3 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* - Implement the functionality of a simple CA: read in a CA certificate, - the associated private key, and a PKCS #10 certificate request. Sign the - request and print out the new certificate. - - File names are hardcoded for simplicity. - cacert.pem: The CA's certificate (perhaps created by self_sig) - caprivate.pem: The CA's private key - req.pem: The user's PKCS #10 certificate request -*/ - #include <botan/botan.h> #include <botan/x509_ca.h> #include <botan/time.h> diff --git a/doc/examples/dsa_kgen.cpp b/doc/examples/dsa_kgen.cpp index fe3157370..fc5b7b501 100644 --- a/doc/examples/dsa_kgen.cpp +++ b/doc/examples/dsa_kgen.cpp @@ -1,13 +1,3 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -* -* Generate a 1024 bit DSA key and put it into a file. The public key -* format is that specified by X.509, while the private key format is -* PKCS #8. -*/ - #include <iostream> #include <fstream> #include <string> @@ -20,24 +10,24 @@ using namespace Botan; int main(int argc, char* argv[]) { - if(argc != 1 && argc != 2) - { - std::cout << "Usage: " << argv[0] << " [passphrase]" << std::endl; - return 1; - } - - Botan::LibraryInitializer init; - - std::ofstream priv("dsapriv.pem"); - std::ofstream pub("dsapub.pem"); - if(!priv || !pub) - { - std::cout << "Couldn't write output files" << std::endl; - return 1; - } - try { + if(argc != 1 && argc != 2) + { + std::cout << "Usage: " << argv[0] << " [passphrase]" << std::endl; + return 1; + } + + std::ofstream priv("dsapriv.pem"); + std::ofstream pub("dsapub.pem"); + if(!priv || !pub) + { + std::cout << "Couldn't write output files" << std::endl; + return 1; + } + + Botan::LibraryInitializer init; + AutoSeeded_RNG rng; DL_Group group(rng, DL_Group::DSA_Kosherizer, 2048, 256); diff --git a/doc/examples/dsa_sign.cpp b/doc/examples/dsa_sign.cpp index 5f02c0dc1..827fc7e0a 100644 --- a/doc/examples/dsa_sign.cpp +++ b/doc/examples/dsa_sign.cpp @@ -1,10 +1,3 @@ -/* -* DSA signature generation example -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - #include <iostream> #include <iomanip> #include <fstream> @@ -66,12 +59,10 @@ int main(int argc, char* argv[]) DataSource_Stream in(message); byte buf[4096] = { 0 }; - while(u32bit got = in.read(buf, sizeof(buf))) + while(size_t got = in.read(buf, sizeof(buf))) signer.update(buf, got); - Pipe pipe(new Base64_Encoder); - pipe.process_msg(signer.signature(rng)); - sigfile << pipe.read_all_as_string() << std::endl; + sigfile << base64_encode(signer.signature(rng)) << "\n"; } catch(std::exception& e) { diff --git a/doc/examples/dsa_ver.cpp b/doc/examples/dsa_ver.cpp index a666259c1..9cb85740e 100644 --- a/doc/examples/dsa_ver.cpp +++ b/doc/examples/dsa_ver.cpp @@ -1,18 +1,3 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -Grab an DSA public key from the file given as an argument, grab a -signature from another file, and verify the message (which, suprise, -is also in a file). - -The signature format isn't particularly standard: take the IEEE 1363 -signature format, encoded into base64 with a trailing newline. -*/ - #include <iostream> #include <iomanip> #include <fstream> @@ -45,28 +30,30 @@ int main(int argc, char* argv[]) return 1; } - Botan::LibraryInitializer init; - std::ifstream message(argv[2], std::ios::binary); - if(!message) - { - std::cout << "Couldn't read the message file." << std::endl; - return 1; - } + try { + Botan::LibraryInitializer init; - std::ifstream sigfile(argv[3]); - if(!sigfile) - { - std::cout << "Couldn't read the signature file." << std::endl; - return 1; - } + std::ifstream message(argv[2], std::ios::binary); + if(!message) + { + std::cout << "Couldn't read the message file." << std::endl; + return 1; + } + + std::ifstream sigfile(argv[3]); + if(!sigfile) + { + std::cout << "Couldn't read the signature file." << std::endl; + return 1; + } - try { std::string sigstr; getline(sigfile, sigstr); std::auto_ptr<X509_PublicKey> key(X509::load_key(argv[1])); DSA_PublicKey* dsakey = dynamic_cast<DSA_PublicKey*>(key.get()); + if(!dsakey) { std::cout << "The loaded key is not a DSA key!\n"; @@ -79,10 +66,10 @@ int main(int argc, char* argv[]) DataSource_Stream in(message); byte buf[4096] = { 0 }; - while(u32bit got = in.read(buf, sizeof(buf))) + while(size_t got = in.read(buf, sizeof(buf))) ver.update(buf, got); - bool ok = ver.check_signature(sig); + const bool ok = ver.check_signature(sig); if(ok) std::cout << "Signature verified\n"; diff --git a/doc/examples/eax_tv.txt b/doc/examples/eax.vec index 95cd7c1ab..95cd7c1ab 100644 --- a/doc/examples/eax_tv.txt +++ b/doc/examples/eax.vec diff --git a/doc/examples/eax_test.cpp b/doc/examples/eax_test.cpp index 32311800d..b43861132 100644 --- a/doc/examples/eax_test.cpp +++ b/doc/examples/eax_test.cpp @@ -236,7 +236,7 @@ void run_tests(std::istream& in) int main() { - std::ifstream in("eax_tv.txt"); + std::ifstream in("eax.vec"); Botan::LibraryInitializer init; diff --git a/doc/examples/ecdsa.cpp b/doc/examples/ecdsa.cpp index df1e1b93a..1607107eb 100644 --- a/doc/examples/ecdsa.cpp +++ b/doc/examples/ecdsa.cpp @@ -21,7 +21,7 @@ int main() { AutoSeeded_RNG rng; - EC_Domain_Params params("1.3.132.0.8"); + EC_Domain_Params params("secp160r1"); ECDSA_PrivateKey ecdsa(rng, params); diff --git a/doc/examples/fpe.cpp b/doc/examples/fpe.cpp index 9b18d4879..a7a483d65 100644 --- a/doc/examples/fpe.cpp +++ b/doc/examples/fpe.cpp @@ -1,17 +1,6 @@ -/* -* (C) 2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -* Encrypt credit cards numbers with valid checksums into other credit -* card numbers with valid checksums using format preserving encryption. -*/ - +#include <botan/botan.h> #include <botan/fpe.h> #include <botan/sha160.h> -#include <botan/init.h> using namespace Botan; @@ -130,7 +119,7 @@ int main(int argc, char* argv[]) std::cout << "Input was: " << cc_number << ' ' << luhn_check(cc_number) << '\n'; - /** + /* * In practice something like PBKDF2 with a salt and high iteration * count would be a good idea. */ diff --git a/doc/examples/pkcs10.cpp b/doc/examples/pkcs10.cpp index 3f5ec8e05..b5ad1d1dd 100644 --- a/doc/examples/pkcs10.cpp +++ b/doc/examples/pkcs10.cpp @@ -1,9 +1,3 @@ -/* -* (C) 2003 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - #include <botan/init.h> #include <botan/auto_rng.h> #include <botan/x509self.h> @@ -31,9 +25,6 @@ int main(int argc, char* argv[]) AutoSeeded_RNG rng; RSA_PrivateKey priv_key(rng, 1024); - // If you want a DSA key instead of RSA, comment out the above line and - // uncomment this one: - //DSA_PrivateKey priv_key(DL_Group("dsa/jce/1024")); std::ofstream key_file("private.pem"); key_file << PKCS8::PEM_encode(priv_key, rng, argv[1]); @@ -45,18 +36,8 @@ int main(int argc, char* argv[]) opts.organization = argv[4]; opts.email = argv[5]; - /* Some hard-coded options, just to give you an idea of what's there */ - opts.challenge = "a fixed challenge passphrase"; - opts.locality = "Baltimore"; - opts.state = "MD"; - opts.org_unit = "Testing"; - opts.add_ex_constraint("PKIX.ClientAuth"); - opts.add_ex_constraint("PKIX.IPsecUser"); - opts.add_ex_constraint("PKIX.EmailProtection"); - - opts.xmpp = "[email protected]"; - - PKCS10_Request req = X509::create_cert_req(opts, priv_key, "SHA-1", rng); + PKCS10_Request req = X509::create_cert_req(opts, priv_key, + "SHA-256", rng); std::ofstream req_file("req.pem"); req_file << req.PEM_encode(); diff --git a/doc/examples/python/nisttest.py b/doc/examples/python/nisttest.py index 3ea8fda0f..1260b1226 100755 --- a/doc/examples/python/nisttest.py +++ b/doc/examples/python/nisttest.py @@ -47,7 +47,7 @@ def main(): results[test] = result return results - results = load_results('results.txt') + results = load_results('results.vec') for root, dirs, files in os.walk('../../checks/nist_tests/tests'): if files: diff --git a/doc/examples/python/results.txt b/doc/examples/python/results.vec index 7a3824001..7a3824001 100644 --- a/doc/examples/python/results.txt +++ b/doc/examples/python/results.vec diff --git a/doc/examples/readme.txt b/doc/examples/readme.txt deleted file mode 100644 index fb6a03ddf..000000000 --- a/doc/examples/readme.txt +++ /dev/null @@ -1,77 +0,0 @@ -This directory contains some simple example applications for the Botan crypto -library. If you want to see something a bit more complicated, check out the -stuff in the checks/ directory. Both it and the files in this directory are in -the public domain, and you may do with them however you please. - -The makefile assumes that you built the library with g++; you'll have to change -it if this assumption proves incorrect. - -Some of these examples will not build on all configurations of the library, -particularly 'bzip', 'encrypt', 'decrypt', and 'hash_fd', as they require -various extensions. - -The examples are fairly small (50-150 lines). And that's with argument -processing, I/O, error checking, etc (which counts for 40% or more of most of -them). This is partially to make them easy to understand, and partially because -I'm lazy. For the most part, the examples cover the stuff a 'regular' -application might need. - -Feel free to contribute new examples. You too can gain fame and fortune by -writing example apps for obscure libraries! - -The examples are: - -* X.509 examples --------- -ca: A (very) simple CA application - -x509info: Prints some information about an X.509 certificate - -pkcs10: Generates a PKCS #10 certificate request for a 1024 bit RSA key - -self_sig: Generates a self-signed X.509v3 certificate with a 1024 bit RSA key --------- - -* RSA examples (also uses X.509, PKCS #8, block ciphers, MACs, PBKDF algorithms) --------- -rsa_kgen: Generate an RSA key, encrypt the private key with a passphrase, - output the keys to a pair of files -rsa_enc: Take a public key (generated by rsa_kgen) and encrypt a file - using CAST-128, MAC it with HMAC(SHA-1) -rsa_dec: Decrypt a file encrypted by rsa_enc - -* DSA examples (also uses X.509, PKCS #8) --------- -dsa_kgen: Generates a DSA key, encrypts the private key with a passphrase - and stores it in PKCS #8 format. -dsa_sign: Produce a DSA signature for a file. Uses SHA-1 -dsa_ver: Verify a message signed with dsa_sign - -* Encryption examples --------- -encrypt: Encrypt a file in CBC mode with a block cipher of your choice. Adds - a MAC for authentication, and compresses the plaintext with Zlib. - -decrypt: Decrypt the result of 'encrypt' - -xor_ciph: Shows how to add a new algorithm from application code - -* Hash function examples (also shows different methods of using Pipe) --------- -hash: Print digests of files, using any chosen hash function - -hash_fd: Same as hash, except that it uses Unix file I/O. Requires the - pipe_unixfd extension - -hasher: Print MD5, SHA-1, and RIPEMD-160 digests of files - -hasher2: Same as hasher, just shows an alternate method - -stack: A demonstration of some more advanced Pipe functionality. Prints - MD5 hashes - -* Misc examples --------- -base64: Simple base64 encoding/decoding tool - -bzip: Bzip2 compression/decompression. diff --git a/doc/examples/rsa_kgen.cpp b/doc/examples/rsa_kgen.cpp index f4566263b..a1f0fe71d 100644 --- a/doc/examples/rsa_kgen.cpp +++ b/doc/examples/rsa_kgen.cpp @@ -1,15 +1,3 @@ -/* -* (C) 2002 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -Generate an RSA key of a specified bitlength, and put it into a pair of key -files. One is the public key in X.509 format (PEM encoded), the private key is -in PKCS #8 format (also PEM encoded). -*/ - #include <iostream> #include <fstream> #include <string> @@ -29,25 +17,25 @@ int main(int argc, char* argv[]) return 1; } - u32bit bits = std::atoi(argv[1]); + const size_t bits = std::atoi(argv[1]); if(bits < 1024 || bits > 16384) { std::cout << "Invalid argument for bitsize" << std::endl; return 1; } - Botan::LibraryInitializer init; - - std::ofstream pub("rsapub.pem"); - std::ofstream priv("rsapriv.pem"); - if(!priv || !pub) - { - std::cout << "Couldn't write output files" << std::endl; - return 1; - } - try { + Botan::LibraryInitializer init; + + std::ofstream pub("rsapub.pem"); + std::ofstream priv("rsapriv.pem"); + if(!priv || !pub) + { + std::cout << "Couldn't write output files" << std::endl; + return 1; + } + AutoSeeded_RNG rng; RSA_PrivateKey key(rng, bits); diff --git a/doc/examples/self_sig.cpp b/doc/examples/self_sig.cpp index 6710cfb51..64b778b71 100644 --- a/doc/examples/self_sig.cpp +++ b/doc/examples/self_sig.cpp @@ -1,17 +1,3 @@ -/* -* (C) 2003 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -/* -Generate a 1024 bit RSA key, and then create a self-signed X.509v3 -certificate with that key. If the do_CA variable is set to true, then -it will be marked for CA use, otherwise it will get extensions -appropriate for use with a client certificate. The private key is -stored as an encrypted PKCS #8 object in another file. -*/ - #include <botan/botan.h> #include <botan/x509self.h> #include <botan/rsa.h> @@ -49,7 +35,7 @@ int main(int argc, char* argv[]) { AutoSeeded_RNG rng; - RSA_PrivateKey key(rng, 1024); + RSA_PrivateKey key(rng, 2048); std::ofstream priv_key("private.pem"); priv_key << PKCS8::PEM_encode(key, rng, argv[1]); diff --git a/doc/examples/x509info.cpp b/doc/examples/x509info.cpp deleted file mode 100644 index b22b4ebd8..000000000 --- a/doc/examples/x509info.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -* Read an X.509 certificate, and print various things about it -* (C) 2003 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/botan.h> -#include <botan/x509cert.h> -using namespace Botan; - -#include <iostream> - -int main(int argc, char* argv[]) - { - if(argc != 2) - { - std::cout << "Usage: " << argv[0] << " <x509cert>\n"; - return 1; - } - - Botan::LibraryInitializer init; - - try { - X509_Certificate cert(argv[1]); - - std::cout << cert.to_string(); - } - catch(std::exception& e) - { - std::cout << e.what() << std::endl; - return 1; - } - return 0; - } diff --git a/doc/log.txt b/doc/log.txt index 1f7107d8c..d146eb116 100644 --- a/doc/log.txt +++ b/doc/log.txt @@ -14,6 +14,12 @@ Version 1.9.16, Not Yet Released reStructuredText suitable for processing by Sphinx, which can generate nicely formatted HTML and PDFs. + * The class EC_Domain_Params has been renamed EC_Group, with a + typedef for backwards compatability. + + * EC_Group's string constructor didn't understand the standard + names like "secp160r1", forcing use of the OIDs. + * Change shared library versioning to match the normal Unix conventions. Instead of libbotan-X.Y.Z.so, the shared lib is named libbotan.so.X.Y.Z; this allows the runtime linker to do its diff --git a/doc/pubkey.txt b/doc/pubkey.txt index 254880f65..2089434d6 100644 --- a/doc/pubkey.txt +++ b/doc/pubkey.txt @@ -52,7 +52,7 @@ operations, like key agreement, the two keys *must* use the same group. There are currently two kinds of discrete logarithm groups supported in botan: the integers modulo a prime, represented by :ref:`dl_group`, and elliptic curves in GF(p), represented by -:ref:`ec_dompar`. A rough generalization is that the larger the group +:ref:`ec_group`. A rough generalization is that the larger the group is, the more secure the algorithm is, but coorespondingly the slower the operations will be. @@ -74,30 +74,14 @@ Nyberg-Rueppel key pairs with value. Normally, you would leave the value as zero, letting the class generate a new random key. -Finally, given an ``EC_Domain_Params`` object, you can create a new +Finally, given an ``EC_Group`` object, you can create a new ECDSA, ECDH, or GOST 34.10 private key with -.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain) +.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x = 0) -.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain) +.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x = 0) -.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain) - -Unlike the integer modulo a prime key types, the constructor that takes a -predefined ``BigInt`` private key value is different: - -.. cpp:function:: ECDSA_PrivateKey::ECDSA_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) - -.. cpp:function:: ECDH_PrivateKey::ECDH_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) - -.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) - -.. note:: - - It is likely that these constructors will be removed in a future - release, and a third optional parameter will be added to the - constructors described above, to match the integer modulo prime - versions. Only use them if you really need them. +.. cpp:function:: GOST_3410_PrivateKey::GOST_3410_PrivateKey(RandomNumberGenerator& rng, const EC_Group& domain, const BigInt& x = 0) .. _serializing_private_keys: @@ -274,12 +258,12 @@ You can reload a serialized group using .. cpp:function:: void DL_Group::PEM_decode(DataSource& source) -.. _ec_dompar: +.. _ec_group: -EC_Domain_Params +EC_Group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -An ``EC_Domain_Params`` is initialized by passing the name of the +An ``EC_Group`` is initialized by passing the name of the group to be used to the constructor. These groups have semi-standardized names like "secp256r1" and "brainpool512r1". @@ -305,96 +289,82 @@ Each public key type has a function checking, which includes expensive operations like primality checking. -Getting a PK algorithm object +Encryption --------------------------------- -The key types, like ``RSA_PrivateKey``, do not implement any kind of -padding or encoding (which is necessary for security). To get an -object that knows how to do padding, use the wrapper classes included -in ``pubkey.h``. These take a key, along with a string that specifies -what hashing and encoding method(s) to use. Examples of such strings -are "EME1(SHA-256)" for OAEP encryption and "EMSA4(SHA-256)" for PSS -signatures (where the message is hashed using SHA-256). +Safe public key encryption requires the use of a padding scheme which +hides the underlying mathematical properties of the algorithm. +Additionally, they will add randomness, so encrypting the same +plaintext twice produces two different ciphertexts. -Here are some basic examples (using an RSA key) to give you a feel for -the possibilities. These examples assume ``rsakey`` is an -``RSA_PrivateKey``, since otherwise we would not be able to create -a decryption or signature object with it (you can create encryption or -signature verification objects with public keys, naturally):: +The primary interface for encryption is ``PK_Encryptor``, which +provides the following interface: - // PKCS #1 v2.0 / IEEE 1363 compatible encryption - PK_Encryptor_EME rsa_enc_pkcs1_v2(rsakey, "EME1(SHA-1)"); - // PKCS #1 v1.5 compatible encryption - PK_Encryptor_EME rsa_enc_pkcs1_v15(rsakey, "PKCS1v15") +.. cpp:function:: SecureVector<byte> PK_Encryptor::encrypt(const byte in[], size_t length, RandomNumberGenerator& rng) const - // This object can decrypt things encrypted by rsa_ - PK_Decryptor_EME rsa_dec_pkcs1_v2(rsakey, "EME1(SHA-1)"); +.. cpp:function:: SecureVector<byte> PK_Encryptor::encrypt(const MemoryRegion<byte>& in, RandomNumberGenerator& rng) const - // PKCS #1 v1.5 compatible signatures - PK_Signer rsa_sign_pkcs1_v15(rsakey, "EMSA3(MD5)"); - PK_Verifier rsa_verify_pkcs1_v15(rsakey, "EMSA3(MD5)"); - // PKCS #1 v2.1 compatible signatures - PK_Signer rsa_sign_pkcs1_v2(rsakey, "EMSA4(SHA-1)"); - PK_Verifier rsa_verify_pkcs1_v2(rsakey, "EMSA4(SHA-1)"); +.. cpp:function:: size_t PK_Encryptor::maximum_input_size() const -Encryption ---------------------------------- + This function returns the maximum size of the message that can + be processed, in bytes. If you call ``encrypt`` with a value + larger than this the operation will fail with an exception. + +``PK_Encryptor`` is only an interface; to use one you have to create +an implementation; there are currently two availabie in the library, +``PK_Encryptor_EME`` and ``DLIES_Encryptor``. DLIES is a standard +method (from IEEE 1363) that uses a key agreement technique such as DH +or ECDH to perform message encryption. Normally, public key encryption +is done using algorithms which support it directly, such as RSA or +ElGamal; these use ``PK_Encryptor_EME``. The construction method is +simple; call + +.. cpp:function:: PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key, std::string eme) + + With *key* being the key you want to encrypt messages to. The + padding method to use is specified in *eme*. + + The recommended values for *eme* is "EME1(SHA-1)" or + "EME1(SHA-256)". If you need compatability with protocols using the + PKCS #1 v1.5 standard, you can also use "EME-PKCS1-v1_5". + +The DLIES encryptor is defined in the header ``dlies.h``, and +is created by the constructor: + +.. cpp:function:: DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key&, KDF* kdf, MessageAuthenticationCode* mac, size_t mac_key_len = 20) + + Where *kdf* is a :ref:`key_derivation_function` and *mac* is a + :ref:`message_auth_code`. + +The decryption classes are named ``PK_Decryptor``, +``PK_Decryptor_EME``, and ``DLIES_Decryptor``. They are created in the +exact same way, except they take the private key, and the processing +function is named ``decrypt``. -The ``PK_Encryptor`` and ``PK_Decryptor`` classes are the -interface for encryption and decryption, respectively. - -Calling ``encrypt`` with a ``byte`` array, a length -parameter, and an RNG object will return the input encrypted with -whatever scheme is being used. Calling the similar ``decrypt`` -will perform the inverse operation. You can also do these operations -with ``SecureVector<byte>``s. In all cases, the output is returned -via a ``SecureVector<byte>``. - -If you attempt an operation with a larger size than the key can -support (this limit varies based on the algorithm, the key size, and -the padding method used (if any)), an exception will be thrown. You -can call ``maximum_input_size`` to find out the maximum size -input (in bytes) that you can safely use with any particular key. - -Available public key encryption algorithms in Botan are RSA and -ElGamal. The encoding methods are EME1, denoted by "EME1(HASHNAME)", -PKCS #1 v1.5, called "PKCS1v15" or "EME-PKCS1-v1_5", and raw encoding -("Raw"). - -For compatibility reasons, PKCS #1 v1.5 is recommend for use with -ElGamal (most other implementations of ElGamal do not support any -other encoding format). RSA can also be used with PKCS # 1 encoding, -but because of various possible attacks, EME1 is the preferred -encoding. EME1 requires the use of a hash function: unless a competent -applied cryptographer tells you otherwise, you should use SHA-256 or -SHA-512. - -Don't use "Raw" encoding unless you need it for backward -compatibility with old protocols. There are many possible attacks -against both ElGamal and RSA when they are used in this way. Signatures --------------------------------- + The signature algorithms look quite a bit like the hash functions. You -can repeatedly call ``update``, giving more and more of a -message you wish to sign, and then call ``signature``, which -will return a signature for that message. If you want to do it all in -one shot, call ``sign_message``, which will just call -``update`` with its argument and then return whatever -``signature`` returns. Generating a signature requires random -numbers with some schemes, so ``signature`` and +can repeatedly call ``update``, giving more and more of a message you +wish to sign, and then call ``signature``, which will return a +signature for that message. If you want to do it all in one shot, call +``sign_message``, which will just call ``update`` with its argument +and then return whatever ``signature`` returns. Generating a signature +requires random numbers with some schemes, so ``signature`` and ``sign_message`` both take a ``RandomNumberGenerator&``. -You can validate a signature by updating the verifier class, and finally seeing -the if the value returned from ``check_signature`` is true (you pass -the supposed signature to the ``check_signature`` function as a byte -array and a length or as a ``MemoryRegion<byte>``). There is another -function, ``verify_message``, which takes a pair of byte array/length -pairs (or a pair of ``MemoryRegion<byte>`` objects), the first of which is -the message, the second being the (supposed) signature. It returns true if the -signature is valid and false otherwise. +You can validate a signature by updating the verifier class, and +finally seeing the if the value returned from ``check_signature`` is +true (you pass the supposed signature to the ``check_signature`` +function as a byte array and a length or as a +``MemoryRegion<byte>``). There is another function, +``verify_message``, which takes a pair of byte array/length pairs (or +a pair of ``MemoryRegion<byte>`` objects), the first of which is the +message, the second being the (supposed) signature. It returns true if +the signature is valid and false otherwise. Available public key signature algorithms in Botan are RSA, DSA, ECDSA, GOST-34.11, Nyberg-Rueppel, and Rabin-Williams. Signature diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp index 1097d45d1..662a1d2be 100644 --- a/src/cert/cvc/cvc_self.cpp +++ b/src/cert/cvc/cvc_self.cpp @@ -41,7 +41,7 @@ MemoryVector<byte> eac_1_1_encoding(const EC_PublicKey* key, if(key->domain_format() == EC_DOMPAR_ENC_OID) throw Encoding_Error("CVC encoder: cannot encode parameters by OID"); - const EC_Domain_Params& domain = key->domain(); + const EC_Group& domain = key->domain(); // This is why we can't have nice things diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_group/ec_group.cpp index deb512518..fe4fae885 100644 --- a/src/pubkey/ec_dompar/ec_dompar.cpp +++ b/src/pubkey/ec_group/ec_group.cpp @@ -7,7 +7,7 @@ * Distributed under the terms of the Botan license */ -#include <botan/ec_dompar.h> +#include <botan/ec_group.h> #include <botan/ber_dec.h> #include <botan/der_enc.h> #include <botan/libstate.h> @@ -16,7 +16,7 @@ namespace Botan { -EC_Domain_Params::EC_Domain_Params(const OID& domain_oid) +EC_Group::EC_Group(const OID& domain_oid) { std::string pem = global_state().get("ec", OIDS::lookup(domain_oid)); @@ -24,31 +24,31 @@ EC_Domain_Params::EC_Domain_Params(const OID& domain_oid) if(pem == "") throw Lookup_Error("No ECC domain data for " + domain_oid.as_string()); - *this = EC_Domain_Params(pem); + *this = EC_Group(pem); oid = domain_oid.as_string(); } -EC_Domain_Params::EC_Domain_Params(const std::string& pem) +EC_Group::EC_Group(const std::string& str) { - if(pem == "") + if(str == "") return; // no initialization / uninitialized try { - DataSource_Memory input(pem); + DataSource_Memory input(str); SecureVector<byte> ber = PEM_Code::decode_check_label(input, "EC PARAMETERS"); - *this = EC_Domain_Params(ber); + *this = EC_Group(ber); } catch(Decoding_Error) // hmm, not PEM? { - *this = EC_Domain_Params(OID(pem)); + *this = EC_Group(OIDS::lookup(str)); } } -EC_Domain_Params::EC_Domain_Params(const MemoryRegion<byte>& ber_data) +EC_Group::EC_Group(const MemoryRegion<byte>& ber_data) { BER_Decoder ber(ber_data); BER_Object obj = ber.get_next_object(); @@ -59,7 +59,7 @@ EC_Domain_Params::EC_Domain_Params(const MemoryRegion<byte>& ber_data) { OID dom_par_oid; BER_Decoder(ber_data).decode(dom_par_oid); - *this = EC_Domain_Params(dom_par_oid); + *this = EC_Group(dom_par_oid); } else if(obj.type_tag == SEQUENCE) { @@ -92,7 +92,7 @@ EC_Domain_Params::EC_Domain_Params(const MemoryRegion<byte>& ber_data) } SecureVector<byte> -EC_Domain_Params::DER_encode(EC_Domain_Params_Encoding form) const +EC_Group::DER_encode(EC_Group_Encoding form) const { if(form == EC_DOMPAR_ENC_EXPLICIT) { @@ -125,10 +125,10 @@ EC_Domain_Params::DER_encode(EC_Domain_Params_Encoding form) const else if(form == EC_DOMPAR_ENC_IMPLICITCA) return DER_Encoder().encode_null().get_contents(); else - throw Internal_Error("EC_Domain_Params::DER_encode: Unknown encoding"); + throw Internal_Error("EC_Group::DER_encode: Unknown encoding"); } -std::string EC_Domain_Params::PEM_encode() const +std::string EC_Group::PEM_encode() const { SecureVector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT); return PEM_Code::encode(der, "EC PARAMETERS"); diff --git a/src/pubkey/ec_dompar/ec_dompar.h b/src/pubkey/ec_group/ec_group.h index 2508d5a2d..b7b09985e 100644 --- a/src/pubkey/ec_dompar/ec_dompar.h +++ b/src/pubkey/ec_group/ec_group.h @@ -19,7 +19,7 @@ namespace Botan { /** * This class represents elliptic curce domain parameters */ -enum EC_Domain_Params_Encoding { +enum EC_Group_Encoding { EC_DOMPAR_ENC_EXPLICIT = 0, EC_DOMPAR_ENC_IMPLICITCA = 1, EC_DOMPAR_ENC_OID = 2 @@ -28,7 +28,7 @@ enum EC_Domain_Params_Encoding { /** * Class representing an elliptic curve */ -class BOTAN_DLL EC_Domain_Params +class BOTAN_DLL EC_Group { public: @@ -39,7 +39,7 @@ class BOTAN_DLL EC_Domain_Params * @param order the order of the base point * @param cofactor the cofactor */ - EC_Domain_Params(const CurveGFp& curve, + EC_Group(const CurveGFp& curve, const PointGFp& base_point, const BigInt& order, const BigInt& cofactor) : @@ -54,27 +54,27 @@ class BOTAN_DLL EC_Domain_Params * Decode a BER encoded ECC domain parameter set * @param ber_encoding the bytes of the BER encoding */ - EC_Domain_Params(const MemoryRegion<byte>& ber_encoding); + EC_Group(const MemoryRegion<byte>& ber_encoding); /** * Create an EC domain by OID (or throw if unknown) * @param oid the OID of the EC domain to create */ - EC_Domain_Params(const OID& oid); + EC_Group(const OID& oid); /** * Create an EC domain from PEM encoding (as from PEM_encode), * or from an OID name (eg "secp16r1", or "1.3.132.0.8") * @param pem_or_oid PEM-encoded data, or an OID */ - EC_Domain_Params(const std::string& pem_or_oid = ""); + EC_Group(const std::string& pem_or_oid = ""); /** * Create the DER encoding of this domain * @param form of encoding to use * @returns bytes encododed as DER */ - SecureVector<byte> DER_encode(EC_Domain_Params_Encoding form) const; + SecureVector<byte> DER_encode(EC_Group_Encoding form) const; /** * Return the PEM encoding (always in explicit form) @@ -114,7 +114,7 @@ class BOTAN_DLL EC_Domain_Params */ std::string get_oid() const { return oid; } - bool operator==(const EC_Domain_Params& other) const + bool operator==(const EC_Group& other) const { return ((get_curve() == other.get_curve()) && (get_base_point() == other.get_base_point()) && @@ -129,12 +129,15 @@ class BOTAN_DLL EC_Domain_Params std::string oid; }; -inline bool operator!=(const EC_Domain_Params& lhs, - const EC_Domain_Params& rhs) +inline bool operator!=(const EC_Group& lhs, + const EC_Group& rhs) { return !(lhs == rhs); } +// For compatability with 1.8 +typedef EC_Group EC_Domain_Params; + } #endif diff --git a/src/pubkey/ec_dompar/info.txt b/src/pubkey/ec_group/info.txt index ae6c328e2..c611914e9 100644 --- a/src/pubkey/ec_dompar/info.txt +++ b/src/pubkey/ec_group/info.txt @@ -1,4 +1,4 @@ -define ECC_DOMAIN_PARAMATERS +define ECC_GROUP <requires> asn1 diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp index bd04e3197..991446f07 100644 --- a/src/pubkey/ecc_key/ecc_key.cpp +++ b/src/pubkey/ecc_key/ecc_key.cpp @@ -18,7 +18,7 @@ namespace Botan { -EC_PublicKey::EC_PublicKey(const EC_Domain_Params& dom_par, +EC_PublicKey::EC_PublicKey(const EC_Group& dom_par, const PointGFp& pub_point) : domain_params(dom_par), public_key(pub_point), domain_encoding(EC_DOMPAR_ENC_EXPLICIT) @@ -30,7 +30,7 @@ EC_PublicKey::EC_PublicKey(const EC_Domain_Params& dom_par, EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, const MemoryRegion<byte>& key_bits) { - domain_params = EC_Domain_Params(alg_id.parameters); + domain_params = EC_Group(alg_id.parameters); domain_encoding = EC_DOMPAR_ENC_EXPLICIT; public_key = OS2ECP(key_bits, domain().get_curve()); @@ -52,7 +52,7 @@ MemoryVector<byte> EC_PublicKey::x509_subject_public_key() const return EC2OSP(public_point(), PointGFp::COMPRESSED); } -void EC_PublicKey::set_parameter_encoding(EC_Domain_Params_Encoding form) +void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form) { if(form != EC_DOMPAR_ENC_EXPLICIT && form != EC_DOMPAR_ENC_IMPLICITCA && @@ -76,32 +76,24 @@ const BigInt& EC_PrivateKey::private_value() const } /** -* EC_PrivateKey generator -*/ -EC_PrivateKey::EC_PrivateKey(const EC_Domain_Params& dom_par, - const BigInt& priv_key) - { - domain_params = dom_par; - domain_encoding = EC_DOMPAR_ENC_EXPLICIT; - - public_key = domain().get_base_point() * priv_key; - private_key = priv_key; - } - -/** -* EC_PrivateKey generator +* EC_PrivateKey constructor */ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, - const EC_Domain_Params& dom_par) + const EC_Group& ec_group, + const BigInt& x) { - domain_params = dom_par; + domain_params = ec_group; domain_encoding = EC_DOMPAR_ENC_EXPLICIT; - private_key = BigInt::random_integer(rng, 1, domain().get_order()); + if(x == 0) + private_key = BigInt::random_integer(rng, 1, domain().get_order()); + else + private_key = x; + public_key = domain().get_base_point() * private_key; BOTAN_ASSERT(public_key.on_the_curve(), - "generated ECC private key was not on the curve"); + "ECC private key was not on the curve"); } MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const @@ -118,7 +110,7 @@ MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, const MemoryRegion<byte>& key_bits) { - domain_params = EC_Domain_Params(alg_id.parameters); + domain_params = EC_Group(alg_id.parameters); domain_encoding = EC_DOMPAR_ENC_EXPLICIT; BER_Decoder(key_bits) diff --git a/src/pubkey/ecc_key/ecc_key.h b/src/pubkey/ecc_key/ecc_key.h index a20516ec6..cccc8d53c 100644 --- a/src/pubkey/ecc_key/ecc_key.h +++ b/src/pubkey/ecc_key/ecc_key.h @@ -10,7 +10,7 @@ #ifndef BOTAN_ECC_PUBLIC_KEY_BASE_H__ #define BOTAN_ECC_PUBLIC_KEY_BASE_H__ -#include <botan/ec_dompar.h> +#include <botan/ec_group.h> #include <botan/pk_keys.h> #include <botan/x509_key.h> #include <botan/pkcs8.h> @@ -18,7 +18,7 @@ namespace Botan { /** -* This class represents abstract EC Public Keys. When encoding a key +* This class represents abstract ECC public keys. When encoding a key * via an encoder that can be accessed via the corresponding member * functions, the key will decide upon its internally stored encoding * information whether to encode itself with or without domain @@ -30,7 +30,7 @@ namespace Botan { class BOTAN_DLL EC_PublicKey : public virtual Public_Key { public: - EC_PublicKey(const EC_Domain_Params& dom_par, + EC_PublicKey(const EC_Group& dom_par, const PointGFp& pub_point); EC_PublicKey(const AlgorithmIdentifier& alg_id, @@ -57,13 +57,13 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key * domain parameters of this point are not set * @result the domain parameters of this key */ - const EC_Domain_Params& domain() const { return domain_params; } + const EC_Group& domain() const { return domain_params; } /** * Set the domain parameter encoding to be used when encoding this key. * @param enc the encoding to use */ - void set_parameter_encoding(EC_Domain_Params_Encoding enc); + void set_parameter_encoding(EC_Group_Encoding enc); /** * Return the DER encoding of this keys domain in whatever format @@ -76,28 +76,26 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key * Get the domain parameter encoding to be used when encoding this key. * @result the encoding to use */ - EC_Domain_Params_Encoding domain_format() const + EC_Group_Encoding domain_format() const { return domain_encoding; } protected: EC_PublicKey() : domain_encoding(EC_DOMPAR_ENC_EXPLICIT) {} - EC_Domain_Params domain_params; + EC_Group domain_params; PointGFp public_key; - EC_Domain_Params_Encoding domain_encoding; + EC_Group_Encoding domain_encoding; }; /** -* This abstract class represents general EC Private Keys +* This abstract class represents ECC private keys */ class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey, public virtual Private_Key { public: - EC_PrivateKey(const EC_Domain_Params& domain, - const BigInt& private_key); - - EC_PrivateKey(RandomNumberGenerator& rng, - const EC_Domain_Params& domain); + EC_PrivateKey(RandomNumberGenerator& rng, + const EC_Group& domain, + const BigInt& private_key); EC_PrivateKey(const AlgorithmIdentifier& alg_id, const MemoryRegion<byte>& key_bits); diff --git a/src/pubkey/ecc_key/info.txt b/src/pubkey/ecc_key/info.txt index e08a4231d..be281d697 100644 --- a/src/pubkey/ecc_key/info.txt +++ b/src/pubkey/ecc_key/info.txt @@ -4,6 +4,6 @@ define ECC_PUBLIC_KEY_CRYPTO alloc asn1 bigint -ec_dompar +ec_group numbertheory </requires> diff --git a/src/pubkey/ecdh/ecdh.h b/src/pubkey/ecdh/ecdh.h index 301bb1591..2edbfe86d 100644 --- a/src/pubkey/ecdh/ecdh.h +++ b/src/pubkey/ecdh/ecdh.h @@ -32,7 +32,7 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey * @param dom_par the domain parameters associated with this key * @param public_point the public point defining this key */ - ECDH_PublicKey(const EC_Domain_Params& dom_par, + ECDH_PublicKey(const EC_Group& dom_par, const PointGFp& public_point) : EC_PublicKey(dom_par, public_point) {} @@ -77,10 +77,12 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, * Generate a new private key * @param rng a random number generator * @param domain parameters to used for this key + * @param x the private key; if zero, a new random key is generated */ ECDH_PrivateKey(RandomNumberGenerator& rng, - const EC_Domain_Params& domain) : - EC_PrivateKey(rng, domain) {} + const EC_Group& domain, + const BigInt& x = 0) : + EC_PrivateKey(rng, domain, x) {} MemoryVector<byte> public_value() const { return ECDH_PublicKey::public_value(); } diff --git a/src/pubkey/ecdh/info.txt b/src/pubkey/ecdh/info.txt index 12826c81b..7e7d50fef 100644 --- a/src/pubkey/ecdh/info.txt +++ b/src/pubkey/ecdh/info.txt @@ -3,7 +3,7 @@ define ECDH <requires> alloc asn1 -ec_dompar +ec_group ecc_key libstate numbertheory diff --git a/src/pubkey/ecdsa/ecdsa.h b/src/pubkey/ecdsa/ecdsa.h index 6d62a168d..f0834abd8 100644 --- a/src/pubkey/ecdsa/ecdsa.h +++ b/src/pubkey/ecdsa/ecdsa.h @@ -28,7 +28,7 @@ class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey * @param dom_par the domain parameters associated with this key * @param public_point the public point defining this key */ - ECDSA_PublicKey(const EC_Domain_Params& dom_par, + ECDSA_PublicKey(const EC_Group& dom_par, const PointGFp& public_point) : EC_PublicKey(dom_par, public_point) {} @@ -66,6 +66,11 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey, { public: + /** + * Load a private key + * @param alg_id the X.509 algorithm identifier + * @param key_bits PKCS #8 structure + */ ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id, const MemoryRegion<byte>& key_bits) : EC_PrivateKey(alg_id, key_bits) {} @@ -74,19 +79,12 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey, * Generate a new private key * @param rng a random number generator * @param domain parameters to used for this key + * @param x the private key (if zero, generate a ney random key) */ ECDSA_PrivateKey(RandomNumberGenerator& rng, - const EC_Domain_Params& domain) : - EC_PrivateKey(rng, domain) {} - - /** - * Load a private key - * @param domain parameters - * @param x the private key - */ - ECDSA_PrivateKey(const EC_Domain_Params& domain, - const BigInt& x) : - EC_PrivateKey(domain, x) {} + const EC_Group& domain, + const BigInt& x = 0) : + EC_PrivateKey(rng, domain, x) {} bool check_key(RandomNumberGenerator& rng, bool) const; }; diff --git a/src/pubkey/ecdsa/info.txt b/src/pubkey/ecdsa/info.txt index ca2694ad1..7a2113a30 100644 --- a/src/pubkey/ecdsa/info.txt +++ b/src/pubkey/ecdsa/info.txt @@ -2,7 +2,7 @@ define ECDSA <requires> asn1 -ec_dompar +ec_group ecc_key numbertheory rng diff --git a/src/pubkey/gost_3410/gost_3410.cpp b/src/pubkey/gost_3410/gost_3410.cpp index fa72d0673..507ebb5a0 100644 --- a/src/pubkey/gost_3410/gost_3410.cpp +++ b/src/pubkey/gost_3410/gost_3410.cpp @@ -56,7 +56,7 @@ GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, // Also includes hash and cipher OIDs... brilliant design guys BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id); - domain_params = EC_Domain_Params(ecc_param_id); + domain_params = EC_Group(ecc_param_id); SecureVector<byte> bits; BER_Decoder(key_bits).decode(bits, OCTET_STRING); diff --git a/src/pubkey/gost_3410/gost_3410.h b/src/pubkey/gost_3410/gost_3410.h index 4fb7b42c3..7b638d7b5 100644 --- a/src/pubkey/gost_3410/gost_3410.h +++ b/src/pubkey/gost_3410/gost_3410.h @@ -27,7 +27,7 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey * @param dom_par the domain parameters associated with this key * @param public_point the public point defining this key */ - GOST_3410_PublicKey(const EC_Domain_Params& dom_par, + GOST_3410_PublicKey(const EC_Group& dom_par, const PointGFp& public_point) : EC_PublicKey(dom_par, public_point) {} @@ -80,18 +80,12 @@ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey, * Generate a new private key * @param rng a random number generator * @param domain parameters to used for this key + * @param x the private key; if zero, a new random key is generated */ GOST_3410_PrivateKey(RandomNumberGenerator& rng, - const EC_Domain_Params& domain) : - EC_PrivateKey(rng, domain) {} - - /** - * Load a private key - * @param domain parameters - * @param x the private key - */ - GOST_3410_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) : - EC_PrivateKey(domain, x) {} + const EC_Group& domain, + const BigInt& x = 0) : + EC_PrivateKey(rng, domain, x) {} AlgorithmIdentifier pkcs8_algorithm_identifier() const { return EC_PublicKey::algorithm_identifier(); } diff --git a/src/pubkey/gost_3410/info.txt b/src/pubkey/gost_3410/info.txt index 05df445ec..9fbc3099f 100644 --- a/src/pubkey/gost_3410/info.txt +++ b/src/pubkey/gost_3410/info.txt @@ -5,7 +5,7 @@ load_on auto <requires> alloc asn1 -ec_dompar +ec_group ecc_key libstate numbertheory |