diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/build-data/innosetup.in | 3 | ||||
-rwxr-xr-x | src/scripts/examples/cipher.py | 44 | ||||
-rwxr-xr-x | src/scripts/examples/cryptobox.py | 36 | ||||
-rwxr-xr-x | src/scripts/examples/nisttest.py | 61 | ||||
-rw-r--r-- | src/scripts/examples/results.vec | 60 | ||||
-rwxr-xr-x | src/scripts/examples/rng_test.py | 22 | ||||
-rwxr-xr-x | src/scripts/examples/rsa.py | 47 | ||||
-rw-r--r-- | src/tests/test_bigint.cpp | 237 |
8 files changed, 416 insertions, 94 deletions
diff --git a/src/build-data/innosetup.in b/src/build-data/innosetup.in index a0928ca40..e9109e65f 100644 --- a/src/build-data/innosetup.in +++ b/src/build-data/innosetup.in @@ -44,8 +44,7 @@ Source: "..\botan.dll.manifest"; DestDir: "{app}"; Components: dll; Flags: skipi Source: "include\botan\*"; DestDir: "{app}\include\botan"; Components: includes; AfterInstall: ConvertLineEndings -Source: "..\readme.txt"; DestDir: "{app}\doc"; Components: docs; AfterInstall: ConvertLineEndings -Source: "..\doc\*.rst"; DestDir: "{app}\doc"; Excludes: "license.txt"; Components: docs; AfterInstall: ConvertLineEndings +Source: "..\doc\*.rst"; DestDir: "{app}\doc"; Excludes: "license.rst"; Components: docs; AfterInstall: ConvertLineEndings Source: "..\doc\examples\*.cpp"; DestDir: "{app}\doc\examples"; Components: docs; AfterInstall: ConvertLineEndings diff --git a/src/scripts/examples/cipher.py b/src/scripts/examples/cipher.py new file mode 100755 index 000000000..1be2759ae --- /dev/null +++ b/src/scripts/examples/cipher.py @@ -0,0 +1,44 @@ +#!/usr/bin/python + +import botan +import sys + +def encrypt(input, passphrase): + rng = botan.RandomNumberGenerator() + + # Use as both EAX IV and PBKDF2 salt + salt = rng.gen_random(10) + + iterations = 10000 + output_size = 16 + + key = botan.pbkdf2(passphrase, salt, iterations, output_size, "SHA-1") + + encryptor = botan.Cipher("AES-128/EAX", "encrypt", key) + + ciphertext = encryptor.cipher(input, salt) + return (ciphertext, salt) + +def decrypt(input, salt, passphrase): + iterations = 10000 + output_size = 16 + + key = botan.pbkdf2(passphrase, salt, iterations, output_size, "SHA-1") + + decryptor = botan.Cipher("AES-128/EAX", "decrypt", key) + + return decryptor.cipher(input, salt) + +def main(args = None): + if args is None: + args = sys.argv + + passphrase = args[1] + input = ''.join(open(args[2]).readlines()) + + (ciphertext, salt) = encrypt(input, passphrase) + + print decrypt(ciphertext, salt, passphrase) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/scripts/examples/cryptobox.py b/src/scripts/examples/cryptobox.py new file mode 100755 index 000000000..f76ed6bc3 --- /dev/null +++ b/src/scripts/examples/cryptobox.py @@ -0,0 +1,36 @@ +#!/usr/bin/python + +import sys +import botan + +def main(args = None): + if args is None: + args = sys.argv + + if len(args) != 3: + raise Exception("Usage: <password> <input>"); + + password = args[1] + input = ''.join(open(args[2]).readlines()) + + rng = botan.RandomNumberGenerator() + + ciphertext = botan.cryptobox_encrypt(input, password, rng) + + print ciphertext + + plaintext = '' + + try: + plaintext = botan.cryptobox_decrypt(ciphertext, password + 'FAIL') + except Exception, e: + print "Good news: bad password caused exception: " + print e + + plaintext = botan.cryptobox_decrypt(ciphertext, password) + + print "Original input was: " + print plaintext + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/scripts/examples/nisttest.py b/src/scripts/examples/nisttest.py new file mode 100755 index 000000000..1260b1226 --- /dev/null +++ b/src/scripts/examples/nisttest.py @@ -0,0 +1,61 @@ +#!/usr/bin/python + +import sys, os, botan +from os.path import join; + +def validate(ca_certs, certs, crls, ee_certs): + store = botan.X509_Store() + for cert in certs: + if cert not in ee_certs: + store.add_cert(botan.X509_Certificate(cert), cert in ca_certs) + + for crl in crls: + r = store.add_crl(botan.X509_CRL(crl)) + if r != botan.verify_result.verified: + return r + + for ee in ee_certs: + r = store.validate(botan.X509_Certificate(ee)) + if r != botan.verify_result.verified: + return r + + return botan.verify_result.verified + +def run_test(files, rootdir, testname, expected): + crls = [join(rootdir,x) for x in files if x.endswith(".crl")] + certs = [join(rootdir,x) for x in files if x.endswith(".crt")] + end_entity = [x for x in certs if x.find("end.crt") != -1] + ca_certs = [x for x in certs if x.find("root.crt") != -1] + + print "%s..." % testname, + + result = validate(ca_certs, certs, crls, end_entity) + result = repr(result).replace('botan._botan.verify_result.', '') + + if result != expected: + print "FAILED: got %s, expected %s" % (result, expected) + else: + print "passed" + +def main(): + def load_results(file): + results = {} + for line in open(file, 'r'): + line = line[0:line.find('#')].strip() + if line: + test,result = line.split(' ') + results[test] = result + return results + + results = load_results('results.vec') + + for root, dirs, files in os.walk('../../checks/nist_tests/tests'): + if files: + thistest = root[root.rfind('/')+1:] + if thistest in results: + run_test(files, root, thistest, results[thistest]) + else: + print "%s... skipping - no expected result set" % thistest + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/scripts/examples/results.vec b/src/scripts/examples/results.vec new file mode 100644 index 000000000..7a3824001 --- /dev/null +++ b/src/scripts/examples/results.vec @@ -0,0 +1,60 @@ +# This is the file of expected results for nisttest.py +test01 verified +test02 signature_error +test03 signature_error +test04 verified +test05 cert_not_yet_valid +test06 cert_not_yet_valid +test07 verified +test08 cert_not_yet_valid +test09 cert_has_expired +test10 cert_has_expired +test11 cert_has_expired +test12 verified +test13 cert_issuer_not_found +test14 cert_issuer_not_found +test15 verified +test16 verified +test17 verified +test18 verified +# changed; should be no_revocation_data_available, but I don't want to +# force people to use CRLs +test19 verified +test20 cert_is_revoked +test21 cert_is_revoked +test22 ca_cert_not_for_cert_issuer +test23 ca_cert_not_for_cert_issuer +test24 verified +test25 ca_cert_not_for_cert_issuer +test26 verified +test27 verified +test28 ca_cert_not_for_cert_issuer +test29 ca_cert_not_for_cert_issuer +test30 verified +test31 ca_cert_not_for_crl_issuer +test32 ca_cert_not_for_crl_issuer +test33 verified +test54 cert_chain_too_long +test55 cert_chain_too_long +test56 verified +test57 verified +test58 cert_chain_too_long +test59 cert_chain_too_long +test60 cert_chain_too_long +test61 cert_chain_too_long +test62 verified +test63 verified +test64 signature_error +# changed; I have no idea why this test is supposed to fail +test65 verified +test66 crl_issuer_not_found +# changed; one of the CRLs has an unknown creator, so we fail +# prior to getting to the end-entity check +test67 crl_issuer_not_found +test68 cert_is_revoked +test69 cert_is_revoked +test70 cert_is_revoked +test71 cert_is_revoked +test72 crl_has_expired +test73 crl_has_expired +test74 verified diff --git a/src/scripts/examples/rng_test.py b/src/scripts/examples/rng_test.py new file mode 100755 index 000000000..06c79b84e --- /dev/null +++ b/src/scripts/examples/rng_test.py @@ -0,0 +1,22 @@ +#!/usr/bin/python + +import botan + +rng = botan.RandomNumberGenerator() + +print "name", rng.name() + +rng.add_entropy("blah") + +print "random 16", rng.gen_random(16).encode("hex") +print "random 32", rng.gen_random(32).encode("base64"), + +rng.reseed() + +for i in range(0, 10): + print rng.gen_random_byte(), +print + +rng.add_entropy("blah") + +print "random 16", rng.gen_random(16).encode("hex") diff --git a/src/scripts/examples/rsa.py b/src/scripts/examples/rsa.py new file mode 100755 index 000000000..998b72b7b --- /dev/null +++ b/src/scripts/examples/rsa.py @@ -0,0 +1,47 @@ +#!/usr/bin/python + +import botan + +def make_into_c_array(ber): + output = 'static unsigned char key_data[%d] = {\n\t' % (len(ber)) + + for (idx,c) in zip(range(len(ber)), ber): + if idx != 0 and idx % 8 == 0: + output += "\n\t" + output += "0x%s, " % (c.encode('hex')) + + output += "\n};\n" + + return output + +rng = botan.RandomNumberGenerator() + +rsa_priv = botan.RSA_PrivateKey(1024, rng) + +print rsa_priv.to_string() +print int(rsa_priv.get_N()) +print int(rsa_priv.get_E()) + +rsa_pub = botan.RSA_PublicKey(rsa_priv) + +print make_into_c_array(rsa_pub.to_ber()) +#print make_into_c_array(rsa_priv.to_ber()) + +key = rng.gen_random(20) + +ciphertext = rsa_pub.encrypt(key, 'EME1(SHA-1)', rng) + +print ciphertext.encode('hex') + +plaintext = rsa_priv.decrypt(ciphertext, 'EME1(SHA-1)') + +print plaintext == key + +signature = rsa_priv.sign(key, 'EMSA4(SHA-256)', rng) + +print rsa_pub.verify(key, signature, 'EMSA4(SHA-256)') + +# Corrupt the signature, make sure it doesn't verify +signature = signature.replace(signature[0], '0') + +print rsa_pub.verify(key, signature, 'EMSA4(SHA-256)') diff --git a/src/tests/test_bigint.cpp b/src/tests/test_bigint.cpp index 45a20cef6..7f866d212 100644 --- a/src/tests/test_bigint.cpp +++ b/src/tests/test_bigint.cpp @@ -11,126 +11,79 @@ #include <fstream> #include <iostream> #include <cstdlib> +#include <iterator> #include <botan/auto_rng.h> #include <botan/bigint.h> #include <botan/exceptn.h> #include <botan/numthry.h> -using namespace Botan; -size_t check_add(const std::vector<std::string>&); -size_t check_sub(const std::vector<std::string>&); -size_t check_mul(const std::vector<std::string>&); -size_t check_sqr(const std::vector<std::string>&); -size_t check_div(const std::vector<std::string>&); -size_t check_mod(const std::vector<std::string>&, - Botan::RandomNumberGenerator& rng); -size_t check_shr(const std::vector<std::string>&); -size_t check_shl(const std::vector<std::string>&); +using namespace Botan; -size_t check_powmod(const std::vector<std::string>&); -size_t check_primetest(const std::vector<std::string>&, - Botan::RandomNumberGenerator&); +namespace { -size_t test_bigint() +size_t test_make_prime() { - const std::string filename = CHECKS_DIR "/mp_valid.dat"; - std::ifstream test_data(filename.c_str()); + AutoSeeded_RNG rng; - if(!test_data) - throw Botan::Stream_IO_Error("Couldn't open test file " + filename); + std::set<BigInt> primes; - size_t total_errors = 0; - size_t errors = 0, alg_count = 0; - std::string algorithm; - bool first = true; - size_t counter = 0; + std::map<int, int> bit_count; - AutoSeeded_RNG rng; + int not_new = 0; - while(!test_data.eof()) + while(primes.size() < 10000) { - if(test_data.bad() || test_data.fail()) - throw Botan::Stream_IO_Error("File I/O error reading from " + - filename); - - std::string line; - std::getline(test_data, line); + u32bit start_cnt = primes.size(); - strip(line); - if(line.size() == 0) continue; + u32bit bits = 18; - // Do line continuation - while(line[line.size()-1] == '\\' && !test_data.eof()) - { - line.replace(line.size()-1, 1, ""); - std::string nextline; - std::getline(test_data, nextline); - strip(nextline); - if(nextline.size() == 0) continue; - line += nextline; - } + if(rng.next_byte() % 128 == 0) + bits -= rng.next_byte() % (bits-2); - if(line[0] == '[' && line[line.size() - 1] == ']') - { - if(!first) - test_report("Bigint " + algorithm, alg_count, errors); + bit_count[bits]++; - algorithm = line.substr(1, line.size() - 2); + //std::cout << "random_prime(" << bits << ")\n"; - total_errors += errors; - errors = 0; - alg_count = 0; - counter = 0; + BigInt p = random_prime(rng, bits); - first = false; - continue; + if(p.bits() != bits) + { + std::cout << "Asked for " << bits << " got " << p + << " " << p.bits() << " bits\n"; + return 1; } - std::vector<std::string> substr = parse(line); - -#if DEBUG - std::cout << "Testing: " << algorithm << std::endl; -#endif + primes.insert(random_prime(rng, bits)); - size_t new_errors = 0; - if(algorithm.find("Addition") != std::string::npos) - new_errors = check_add(substr); - else if(algorithm.find("Subtraction") != std::string::npos) - new_errors = check_sub(substr); - else if(algorithm.find("Multiplication") != std::string::npos) - new_errors = check_mul(substr); - else if(algorithm.find("Square") != std::string::npos) - new_errors = check_sqr(substr); - else if(algorithm.find("Division") != std::string::npos) - new_errors = check_div(substr); - else if(algorithm.find("Modulo") != std::string::npos) - new_errors = check_mod(substr, rng); - else if(algorithm.find("LeftShift") != std::string::npos) - new_errors = check_shl(substr); - else if(algorithm.find("RightShift") != std::string::npos) - new_errors = check_shr(substr); - else if(algorithm.find("ModExp") != std::string::npos) - new_errors = check_powmod(substr); - else if(algorithm.find("PrimeTest") != std::string::npos) - new_errors = check_primetest(substr, rng); + if(primes.size() != start_cnt) + std::cout << primes.size() << "\n"; else - std::cout << "Unknown MPI test " << algorithm << std::endl; + not_new++; - counter++; - alg_count++; - errors += new_errors; + //std::cout << "miss: " << not_new << "\n"; - if(new_errors) - std::cout << "ERROR: BigInt " << algorithm << " failed test #" - << std::dec << alg_count << std::endl; + if(not_new % 100000 == 0) + { + for(std::map<int, int>::iterator i = bit_count.begin(); + i != bit_count.end(); ++i) + std::cout << "bit_count[" << i->first << "] = " + << i->second << "\n"; + std::copy(primes.begin(), primes.end(), + std::ostream_iterator<BigInt>(std::cout, " ")); + } } - return total_errors; + std::cout << "Generated all? primes\n"; + /* + for(u32bit j = 0; j != PRIME_TABLE_SIZE; ++j) + { + if(primes.count(PRIMES[j]) != 1) + std::cout << "Missing " << PRIMES[j] << "\n"; + } + */ } -namespace { - // c==expected, d==a op b, e==a op= b size_t results(std::string op, const BigInt& a, const BigInt& b, @@ -163,8 +116,6 @@ size_t results(std::string op, } } -} - size_t check_add(const std::vector<std::string>& args) { BigInt a(args[0]); @@ -355,3 +306,105 @@ size_t check_primetest(const std::vector<std::string>& args, } return 0; } + +} + +size_t test_bigint() + { + const std::string filename = CHECKS_DIR "/mp_valid.dat"; + std::ifstream test_data(filename.c_str()); + + if(!test_data) + throw Botan::Stream_IO_Error("Couldn't open test file " + filename); + + size_t total_errors = 0; + size_t errors = 0, alg_count = 0; + std::string algorithm; + bool first = true; + size_t counter = 0; + + AutoSeeded_RNG rng; + + while(!test_data.eof()) + { + if(test_data.bad() || test_data.fail()) + throw Botan::Stream_IO_Error("File I/O error reading from " + + filename); + + std::string line; + std::getline(test_data, line); + + strip(line); + if(line.size() == 0) continue; + + // Do line continuation + while(line[line.size()-1] == '\\' && !test_data.eof()) + { + line.replace(line.size()-1, 1, ""); + std::string nextline; + std::getline(test_data, nextline); + strip(nextline); + if(nextline.size() == 0) continue; + line += nextline; + } + + if(line[0] == '[' && line[line.size() - 1] == ']') + { + if(!first) + test_report("Bigint " + algorithm, alg_count, errors); + + algorithm = line.substr(1, line.size() - 2); + + total_errors += errors; + errors = 0; + alg_count = 0; + counter = 0; + + first = false; + continue; + } + + std::vector<std::string> substr = parse(line); + +#if DEBUG + std::cout << "Testing: " << algorithm << std::endl; +#endif + + size_t new_errors = 0; + if(algorithm.find("Addition") != std::string::npos) + new_errors = check_add(substr); + else if(algorithm.find("Subtraction") != std::string::npos) + new_errors = check_sub(substr); + else if(algorithm.find("Multiplication") != std::string::npos) + new_errors = check_mul(substr); + else if(algorithm.find("Square") != std::string::npos) + new_errors = check_sqr(substr); + else if(algorithm.find("Division") != std::string::npos) + new_errors = check_div(substr); + else if(algorithm.find("Modulo") != std::string::npos) + new_errors = check_mod(substr, rng); + else if(algorithm.find("LeftShift") != std::string::npos) + new_errors = check_shl(substr); + else if(algorithm.find("RightShift") != std::string::npos) + new_errors = check_shr(substr); + else if(algorithm.find("ModExp") != std::string::npos) + new_errors = check_powmod(substr); + else if(algorithm.find("PrimeTest") != std::string::npos) + new_errors = check_primetest(substr, rng); + else + std::cout << "Unknown MPI test " << algorithm << std::endl; + + counter++; + alg_count++; + errors += new_errors; + + if(new_errors) + std::cout << "ERROR: BigInt " << algorithm << " failed test #" + << std::dec << alg_count << std::endl; + } + + //total_errors += test_make_prime(); + + return total_errors; + } + |