aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build-data/innosetup.in3
-rwxr-xr-xsrc/scripts/examples/cipher.py44
-rwxr-xr-xsrc/scripts/examples/cryptobox.py36
-rwxr-xr-xsrc/scripts/examples/nisttest.py61
-rw-r--r--src/scripts/examples/results.vec60
-rwxr-xr-xsrc/scripts/examples/rng_test.py22
-rwxr-xr-xsrc/scripts/examples/rsa.py47
-rw-r--r--src/tests/test_bigint.cpp237
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;
+ }
+