aboutsummaryrefslogtreecommitdiffstats
path: root/src/python
diff options
context:
space:
mode:
authorlloyd <[email protected]>2015-02-16 23:25:15 +0000
committerlloyd <[email protected]>2015-02-16 23:25:15 +0000
commitd9ef5466f91b3da090ea4585e8fb8e478ffa3466 (patch)
treed11b3adac410df204b4732a8ae3496475ff7ac76 /src/python
parent3b9a0c1535e40f8f9fc4cfbc734144ee229df65d (diff)
Python: docs, key agreement, fix bcrypt trailing null byte.
Initial very incomplete pass at error return value sanity.
Diffstat (limited to 'src/python')
-rwxr-xr-xsrc/python/botan.py101
1 files changed, 78 insertions, 23 deletions
diff --git a/src/python/botan.py b/src/python/botan.py
index 8414308ec..2957dce29 100755
--- a/src/python/botan.py
+++ b/src/python/botan.py
@@ -44,7 +44,7 @@ RNG
"""
class rng(object):
# Can also use type "system"
- def __init__(self, rng_type = 'user'):
+ def __init__(self, rng_type = 'system'):
botan.botan_rng_init.argtypes = [c_void_p, c_char_p]
self.rng = c_void_p(0)
rc = botan.botan_rng_init(byref(self.rng), rng_type)
@@ -155,12 +155,6 @@ class cipher(object):
botan.botan_cipher_destroy.argtypes = [c_void_p]
botan.botan_cipher_destroy(self.cipher)
- def tag_length(self):
- botan.botan_cipher_tag_length.argtypes = [c_void_p,POINTER(c_size_t)]
- l = c_size_t(0)
- botan.botan_cipher_tag_size(self.cipher, byref(l))
- return l.value
-
def default_nonce_length(self):
botan.botan_cipher_default_nonce_length.argtypes = [c_void_p, POINTER(c_size_t)]
l = c_size_t(0)
@@ -234,14 +228,19 @@ class cipher(object):
Bcrypt
TODO: might not be enabled - handle that gracefully!
"""
-def generate_bcrypt(passwd, rng, work_factor = 10):
- botan.botan_bcrypt_generate.argtypes = [POINTER(c_char), c_size_t, c_char_p, c_void_p, c_size_t]
- out = create_string_buffer(61)
- rc = botan.botan_bcrypt_generate(out, sizeof(out), passwd, rng.rng, c_size_t(work_factor))
-
+def bcrypt(passwd, rng, work_factor = 10):
+ botan.botan_bcrypt_generate.argtypes = [POINTER(c_char), POINTER(c_size_t),
+ c_char_p, c_void_p, c_size_t, c_uint32]
+ out_len = c_size_t(64)
+ out = create_string_buffer(out_len.value)
+ flags = c_uint32(0)
+ rc = botan.botan_bcrypt_generate(out, byref(out_len), passwd, rng.rng, c_size_t(work_factor), flags)
if rc != 0:
raise Exception('botan bcrypt failed, error %s' % (rc))
- return str(out.raw)
+ b = out.raw[0:out_len.value]
+ if b[-1] == '\x00':
+ b = b[:-1]
+ return b
def check_bcrypt(passwd, bcrypt):
rc = botan.botan_bcrypt_is_valid(passwd, bcrypt)
@@ -250,17 +249,16 @@ def check_bcrypt(passwd, bcrypt):
"""
PBKDF
"""
-def pbkdf(algo, password, out_len, iterations, salt):
+def pbkdf(algo, password, out_len, iterations = 10000, salt = rng().get(12)):
botan.botan_pbkdf.argtypes = [c_char_p, POINTER(c_char), c_size_t, c_char_p, c_void_p, c_size_t, c_size_t]
out_buf = create_string_buffer(out_len)
botan.botan_pbkdf(algo, out_buf, out_len, password, salt, len(salt), iterations)
- return out_buf.raw
+ return (salt,iterations,out_buf.raw)
-def pbkdf_timed(algo, password, out_len, rng, ms_to_run, salt_len = 12):
+def pbkdf_timed(algo, password, out_len, ms_to_run = 300, salt = rng().get(12))
botan.botan_pbkdf_timed.argtypes = [c_char_p, POINTER(c_char), c_size_t, c_char_p,
c_void_p, c_size_t, c_size_t, POINTER(c_size_t)]
out_buf = create_string_buffer(out_len)
- salt = rng.get(salt_len)
iterations = c_size_t(0)
botan.botan_pbkdf_timed(algo, out_buf, out_len, password, salt, len(salt), ms_to_run, byref(iterations))
return (salt,iterations.value,out_buf.raw)
@@ -434,10 +432,48 @@ class pk_op_verify(object):
return True
return False
+class pk_op_key_agreement(object):
+ def __init__(self, key, kdf):
+ botan.botan_pk_op_key_agreement_create.argtypes = [c_void_p, c_void_p, c_char_p, c_uint32]
+ botan.botan_pk_op_key_agreement_export_public.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ self.op = c_void_p(0)
+ flags = 0 # always zero in this ABI
+ botan.botan_pk_op_key_agreement_create(byref(self.op), key.privkey, kdf, flags)
+ if not self.op:
+ raise Exception("No key agreement for you")
+
+ pub = create_string_buffer(4096)
+ pub_len = c_size_t(len(pub))
+ botan.botan_pk_op_key_agreement_export_public(key.privkey, pub, byref(pub_len))
+ self.m_public_value = pub.raw[0:pub_len.value]
+
+ def __del__(self):
+ botan.botan_pk_op_key_agreement_destroy.argtypes = [c_void_p]
+ botan.botan_pk_op_key_agreement_destroy(self.op)
+
+ def public_value(self):
+ return self.m_public_value
+
+ def agree(self, other, key_len, salt):
+ botan.botan_pk_op_key_agreement.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t),
+ POINTER(c_char), c_size_t, POINTER(c_char), c_size_t]
+
+ outbuf_sz = c_size_t(key_len)
+ outbuf = create_string_buffer(outbuf_sz.value)
+ rc = botan.botan_pk_op_key_agreement(self.op, outbuf, byref(outbuf_sz), other, len(other), salt, len(salt))
+
+ if rc == -1 and outbuf_sz.value > len(outbuf):
+ outbuf = create_string_buffer(outbuf_sz.value)
+ botan.botan_pk_op_key_agreement(self.op, outbuf, byref(outbuf_sz), other, len(other), salt, len(salt))
+ return outbuf.raw[0:outbuf_sz.value]
+
"""
Tests and examples
"""
def test():
+ r = rng("user")
+
+
print version_string()
print version_major(), version_minor(), version_patch()
@@ -447,7 +483,6 @@ def test():
print pbkdf('PBKDF2(SHA-1)', '', 32, 10000, '0001020304050607'.decode('hex')).encode('hex').upper()
print '59B2B1143B4CB1059EC58D9722FB1C72471E0D85C6F7543BA5228526375B0127'
- r = rng("user")
(salt,iterations,psk) = pbkdf_timed('PBKDF2(SHA-256)', 'xyz', 32, r, 200, 12)
print salt.encode('hex'), iterations
print 'x', psk.encode('hex')
@@ -483,8 +518,8 @@ def test():
signer = pk_op_sign(rsapriv, 'EMSA4(SHA-384)')
- signer.update('mess')
- signer.update('age')
+ signer.update('messa')
+ signer.update('ge')
sig = signer.finish(r)
r.reseed(200)
@@ -494,14 +529,34 @@ def test():
verify.update('mess')
verify.update('age')
- print "correct sig accepted?", verify.check_signature(sig)
+ print "good sig accepted?", verify.check_signature(sig)
verify.update('mess of things')
verify.update('age')
print "bad sig accepted?", verify.check_signature(sig)
- key = private_key('ecdsa', 'secp256r1', r)
- blob = key.export()
+ verify.update('message')
+ print "good sig accepted?", verify.check_signature(sig)
+
+ dh_grp = 'secp256r1'
+ #dh_grp = 'curve25519'
+ dh_kdf = 'KDF2(SHA-384)'
+ a_dh_priv = private_key('ecdh', dh_grp, r)
+ a_dh_pub = a_dh_priv.get_public_key()
+
+ b_dh_priv = private_key('ecdh', dh_grp, r)
+ b_dh_pub = b_dh_priv.get_public_key()
+
+ a_dh = pk_op_key_agreement(a_dh_priv, dh_kdf)
+ b_dh = pk_op_key_agreement(b_dh_priv, dh_kdf)
+
+ print "dh pubs", a_dh.public_value().encode('hex'), b_dh.public_value().encode('hex')
+
+ a_key = a_dh.agree(b_dh.public_value(), 20, 'salt')
+ b_key = b_dh.agree(a_dh.public_value(), 20, 'salt')
+
+ print "dh shared", a_key.encode('hex'), b_key.encode('hex')
+
#f = open('key.ber','wb')
#f.write(blob)