diff --git a/python/BSSpeke.py b/python/BSSpeke.py
deleted file mode 100644
index 85d093a3bebbaaf26b602878f1d1185c6e19c989..0000000000000000000000000000000000000000
--- a/python/BSSpeke.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#import base64
-
-from _bsspeke_cffi import ffi, lib
-
-class Client:
-    
-    def __init__(self, user_id, server_id, password):
-        uid_utf8 = user_id.encode('utf-8')
-        print("uid_utf8:", uid_utf8.decode('utf-8'), len(uid_utf8))
-        sid_utf8 = server_id.encode('utf-8')
-        print("sid_utf8:", sid_utf8.decode('utf-8'), len(sid_utf8))
-        pwd_utf8 = password.encode('utf-8')
-        print("pwd_utf8:", pwd_utf8.decode('utf-8'), len(pwd_utf8))
-
-        from _bsspeke_cffi import ffi, lib
-        self.ffi = ffi
-        self.lib = lib
-
-        self.ctx = self.ffi.new("bsspeke_client_ctx *")
-        self.lib.bsspeke_client_init(self.ctx,
-                                     uid_utf8, len(uid_utf8),
-                                     sid_utf8, len(sid_utf8),
-                                     pwd_utf8, len(pwd_utf8))
-
-    def generate_blind(self):
-        blind = bytes(32)
-        self.lib.bsspeke_client_generate_blind(blind, self.ctx)
-        return blind
-
-
-    def get_client_id(self):
-        clientid_len = self.ctx.client_id_len
-        client_id_bytes = bytes(ffi.buffer(self.ctx.client_id, self.ctx.client_id_len))
-        client_id = client_id_bytes.decode('utf-8')
-        #print("ClientId string = [%s]" % client_id)
-        return client_id
-
-
-    def generate_P_and_V(self, blind_salt, phf_params):
-        P = bytes(32)
-        V = bytes(32)
-        phf_blocks = phf_params["blocks"]
-        phf_iterations = phf_params["iterations"]
-        self.lib.bsspeke_client_generate_P_and_V(P, V,
-                                                 blind_salt,
-                                                 phf_blocks, phf_iterations,
-                                                 self.ctx)
-        return P,V
-#        request = {}
-#        request["P"] = base64.b64encode(P)
-#        request["V"] = base64.b64encode(V)
-#        request["phf"] = {}
-#        request["phf"]["name"] = "argon2i"
-#        request["phf"]["blocks"] = phf_blocks
-#        request["phf"]["iterations"] = phf_iterations
-#
-#        return request
-
-    def generate_A(self, blind_salt, phf_params):
-        phf_blocks = phf_params["blocks"]
-        phf_iterations = phf_params["iterations"]
-        self.lib.bsspeke_client_generate_A(blind_salt,
-                                           phf_blocks,
-                                           phf_iterations,
-                                           self.ctx)
-        A = bytes(ffi.buffer(self.ctx.A, 32))
-        return A
-
-    def derive_shared_key(self, B):
-        self.lib.bsspeke_client_derive_shared_key(B, self.ctx)
-
-    def generate_verifier(self):
-        client_verifier = bytes(32)
-        self.lib.bsspeke_client_generate_verifier(client_verifier, self.ctx)
-        return client_verifier
-
-    def verify_server(self, server_verifier):
-        rc = self.lib.bsspeke_client_verify_server(server_verifier, self.ctx)
-        if rc != 0:
-            return False
-        else:
-            return True
-
-
-class Server:
-    def __init__(self, server_id, user_id):
-        sid_utf8 = server_id.encode('utf-8')
-        print("sid_utf8:", sid_utf8.decode('utf-8'), len(sid_utf8))
-        uid_utf8 = user_id.encode('utf-8')
-        print("uid_utf8:", uid_utf8.decode('utf-8'), len(uid_utf8))
-
-        from _bsspeke_cffi import ffi, lib
-        self.ffi = ffi
-        self.lib = lib
-        
-        self.ctx = self.ffi.new("bsspeke_server_ctx *")
-        self.lib.bsspeke_server_init(self.ctx,
-                                     sid_utf8, len(sid_utf8),
-                                     uid_utf8, len(uid_utf8))
-
-    def blind_salt(self, blind, salt):
-        blind_salt = bytes(32)
-        self.lib.bsspeke_server_blind_salt(blind_salt, blind, salt, len(salt))
-        return blind_salt
-
-    def generate_B(self, P):
-        self.lib.bsspeke_server_generate_B(P, self.ctx)
-        B = bytes(self.ffi.buffer(self.ctx.B, 32))
-        return B
-
-    def derive_shared_key(self, A, V):
-        self.lib.bsspeke_server_derive_shared_key(A, V, self.ctx)
-        
-    def verify_client(self, client_verifier):
-        rc = self.lib.bsspeke_server_verify_client(client_verifier, self.ctx)
-        if rc != 0:
-            return False
-        else:
-            return True
-
-    def generate_verifier(self):
-        server_verifier = bytes(32)
-        self.lib.bsspeke_server_generate_verifier(server_verifier, self.ctx)
-        return server_verifier
-
diff --git a/python/BSSpeke/Client.py b/python/BSSpeke/Client.py
deleted file mode 100644
index 9b0308f5e429e13a608c77529073627131e38a5d..0000000000000000000000000000000000000000
--- a/python/BSSpeke/Client.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#import base64
-
-from _bsspeke_cffi import ffi, lib
-
-class Client:
-    
-    def __init__(self, user_id, server_id, password):
-        uid_utf8 = user_id.encode('utf-8')
-        print("uid_utf8:", uid_utf8.decode('utf-8'), len(uid_utf8))
-        sid_utf8 = server_id.encode('utf-8')
-        print("sid_utf8:", sid_utf8.decode('utf-8'), len(sid_utf8))
-        pwd_utf8 = password.encode('utf-8')
-        print("pwd_utf8:", pwd_utf8.decode('utf-8'), len(pwd_utf8))
-
-        from _bsspeke_cffi import ffi, lib
-        self.ffi = ffi
-        self.lib = lib
-
-        self.ctx = self.ffi.new("bsspeke_client_ctx *")
-        self.lib.bsspeke_client_init(self.ctx,
-                                     uid_utf8, len(uid_utf8),
-                                     sid_utf8, len(sid_utf8),
-                                     pwd_utf8, len(pwd_utf8))
-
-    def generate_blind(self):
-        blind = bytes(32)
-        self.lib.bsspeke_client_generate_blind(blind, self.ctx)
-        return blind
-
-
-    def get_client_id(self):
-        clientid_len = self.ctx.client_id_len
-        client_id_bytes = bytes(ffi.buffer(self.ctx.client_id, self.ctx.client_id_len))
-        client_id = client_id_bytes.decode('utf-8')
-        #print("ClientId string = [%s]" % client_id)
-        return client_id
-
-
-    def generate_P_and_V(self, blind_salt, phf_params):
-        P = bytes(32)
-        V = bytes(32)
-        phf_blocks = phf_params["blocks"]
-        phf_iterations = phf_params["iterations"]
-        self.lib.bsspeke_client_generate_P_and_V(P, V,
-                                                 blind_salt,
-                                                 phf_blocks, phf_iterations,
-                                                 self.ctx)
-        return P,V
-#        request = {}
-#        request["P"] = base64.b64encode(P)
-#        request["V"] = base64.b64encode(V)
-#        request["phf"] = {}
-#        request["phf"]["name"] = "argon2i"
-#        request["phf"]["blocks"] = phf_blocks
-#        request["phf"]["iterations"] = phf_iterations
-#
-#        return request
-
-    def generate_A(self, blind_salt, phf_params):
-        phf_blocks = phf_params["blocks"]
-        phf_iterations = phf_params["iterations"]
-        self.lib.bsspeke_client_generate_A(blind_salt,
-                                           phf_blocks,
-                                           phf_iterations,
-                                           self.ctx)
-        A = bytes(ffi.buffer(self.ctx.A, 32))
-        return A
-
-    def derive_shared_key(self, B):
-        self.lib.bsspeke_client_derive_shared_key(B, self.ctx)
-
-    def generate_verifier(self):
-        client_verifier = bytes(32)
-        self.lib.bsspeke_client_generate_verifier(client_verifier, self.ctx)
-        return client_verifier
-
-    def verify_server(self, server_verifier):
-        rc = self.lib.bsspeke_client_verify_server(server_verifier, self.ctx)
-        if rc != 0:
-            return False
-        else:
-            return True
-
diff --git a/python/BSSpeke/Server.py b/python/BSSpeke/Server.py
deleted file mode 100644
index dea1b0c2e731d4cb23f08c2d6a82d3ab31a2d698..0000000000000000000000000000000000000000
--- a/python/BSSpeke/Server.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#import base64
-
-from _bsspeke_cffi import ffi, lib
-
-class Server:
-    def __init__(self, server_id, user_id):
-        sid_utf8 = server_id.encode('utf-8')
-        print("sid_utf8:", sid_utf8.decode('utf-8'), len(sid_utf8))
-        uid_utf8 = user_id.encode('utf-8')
-        print("uid_utf8:", uid_utf8.decode('utf-8'), len(uid_utf8))
-
-        from _bsspeke_cffi import ffi, lib
-        self.ffi = ffi
-        self.lib = lib
-        
-        self.ctx = self.ffi.new("bsspeke_server_ctx *")
-        self.lib.bsspeke_server_init(self.ctx,
-                                     sid_utf8, len(sid_utf8),
-                                     uid_utf8, len(uid_utf8))
-
-    def blind_salt(self, blind, salt):
-        blind_salt = bytes(32)
-        self.lib.bsspeke_server_blind_salt(blind_salt, blind, salt, len(salt))
-        return blind_salt
-
-    def generate_B(self, P):
-        self.lib.bsspeke_server_generate_B(P, self.ctx)
-        B = bytes(self.ffi.buffer(self.ctx.B, 32))
-        return B
-
-    def derive_shared_key(self, A, V):
-        self.lib.bsspeke_server_derive_shared_key(A, V, self.ctx)
-        
-    def verify_client(self, client_verifier):
-        rc = self.lib.bsspeke_server_verify_client(client_verifier, self.ctx)
-        if rc != 0:
-            return False
-        else:
-            return True
-
-    def generate_verifier(self):
-        server_verifier = bytes(32)
-        self.lib.bsspeke_server_generate_verifier(server_verifier, self.ctx)
-        return server_verifier
-
diff --git a/python/BSSpeke/__init__.py b/python/BSSpeke/__init__.py
deleted file mode 100644
index 2b27b5d8f30acf795dfd5eb46345d4ee5cfa814a..0000000000000000000000000000000000000000
--- a/python/BSSpeke/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .Client import Client
-from .Server import Server
diff --git a/python/LICENSE.txt b/python/LICENSE.txt
deleted file mode 100644
index d645695673349e3947e8e5ae42332d0ac3164cd7..0000000000000000000000000000000000000000
--- a/python/LICENSE.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/python/Makefile b/python/Makefile
deleted file mode 100644
index e9d2877fb3a1cd297b1327b0b6a2a263f7df20dd..0000000000000000000000000000000000000000
--- a/python/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-headers: ../bsspeke.h
-	mkdir -p include
-	$(CPP) -I .. -o include/bsspeke.h ../bsspeke.h
diff --git a/python/README.md b/python/README.md
deleted file mode 100644
index cf842f0d917dc7b3964ccbcfaedc1ae5439cc7a3..0000000000000000000000000000000000000000
--- a/python/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-This package provides a Python interface for speaking the BS-SPEKE
-protocol for augmented password-authenticated key agreement (aPAKE).
diff --git a/python/bsspeke_build.py b/python/bsspeke_build.py
deleted file mode 100644
index 93b941ffd4aa8dfbcd8ecf73cbc2553e791e1602..0000000000000000000000000000000000000000
--- a/python/bsspeke_build.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from cffi import FFI
-import subprocess
-
-
-ffibuilder = FFI()
-
-compile_args = ["-I.."]
-link_args = ["-L.."]
-
-# cvw: Borrowed this trick from libolm :)
-headers_build = subprocess.Popen("make headers", shell=True)
-headers_build.wait()
-
-# cdef() expects a single string declaring the C types, functions and
-# globals needed to use the shared object. It must be in valid C syntax.
-#ffibuilder.cdef("""
-#    float pi_approx(int n);
-#""")
-with open("include/bsspeke.h") as f:
-    ffibuilder.cdef(f.read())
-
-# set_source() gives the name of the python extension module to
-# produce, and some C source code as a string.  This C code needs
-# to make the declarated functions, types and globals available,
-# so it is often just the "#include".
-ffibuilder.set_source("_bsspeke_cffi",
-"""
-     #include "bsspeke.h"   // the C header of the library
-""",
-     libraries=['bsspeke'],   # library name, for the linker
-     extra_compile_args=compile_args,
-     extra_link_args=link_args)
-
-if __name__ == "__main__":
-    ffibuilder.compile(verbose=True)
diff --git a/python/cffi_demo.py b/python/cffi_demo.py
deleted file mode 100644
index fd118aea21b73089d0bd439bdd3f5682cb4d1ac5..0000000000000000000000000000000000000000
--- a/python/cffi_demo.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/bin/env python3
-
-from _bsspeke_cffi import ffi, lib
-
-def bsspeke_setup():
-    client = ffi.new("bsspeke_client_ctx *")
-    lib.bsspeke_client_init(client, b"@alice:example.com", 18, b"example.com", 11, b"P@ssword1", 9)
-
-    server = ffi.new("bsspeke_server_ctx *")
-    lib.bsspeke_server_init(server, b"example.com", 11, b"@alice:example.com", 18)
-
-    print("Message 1")
-    blind = bytes(32)
-    lib.bsspeke_client_generate_blind(blind, client)
-
-    print("Message 2")
-    salt = b"\xff" * 32
-    blind_salt = bytes(32)
-    lib.bsspeke_server_blind_salt(blind_salt, blind, salt, 32)
-
-    print("Message 3")
-    P = bytes(32)
-    V = bytes(32)
-    phf_blocks = 100000
-    phf_iterations = 3
-    lib.bsspeke_client_generate_P_and_V(P, V, blind_salt, phf_blocks, phf_iterations, client)
-
-    return (P,V,phf_blocks,phf_iterations)
-
-
-def bsspeke_login(user_params):
-    client = ffi.new("bsspeke_client_ctx *")
-    lib.bsspeke_client_init(client, b"@alice:example.com", 18, b"example.com", 11, b"P@ssword1", 9)
-
-    server = ffi.new("bsspeke_server_ctx *")
-    lib.bsspeke_server_init(server, b"example.com", 11, b"@alice:example.com", 18)
-
-    P,V,phf_blocks,phf_iterations = user_params
-
-    print("Message 1")
-    blind = bytes(32)
-    lib.bsspeke_client_generate_blind(blind, client)
-
-    print("Message 2")
-    salt = b"\xff" * 32
-    blind_salt = bytes(32)
-    lib.bsspeke_server_blind_salt(blind_salt, blind, salt, 32)
-    lib.bsspeke_server_generate_B(P, server);
-    B = bytes(ffi.buffer(server.B, 32))
-
-    print("Message 3")
-    lib.bsspeke_client_generate_A(blind_salt, phf_blocks, phf_iterations, client)
-    A = bytes(ffi.buffer(client.A, 32))
-    lib.bsspeke_client_derive_shared_key(B, client)
-    client_verifier = bytes(32)
-    lib.bsspeke_client_generate_verifier(client_verifier, client)
-
-    print("Message 4")
-    lib.bsspeke_server_derive_shared_key(A, V, server)
-    rc_server = lib.bsspeke_server_verify_client(client_verifier, server)
-    if rc_server != 0:
-        print("ERROR: Server failed to verify client")
-        print("LOGIN FAILED")
-        return -1
-    server_verifier = bytes(32)
-    lib.bsspeke_server_generate_verifier(server_verifier, server)
-
-    print("Wrapping Up")
-    rc_client = lib.bsspeke_client_verify_server(server_verifier, client)
-    if rc_client != 0:
-        print("ERROR: Client failed to verify server")
-        print("LOGIN FAILED")
-        return -1
-
-    return 0
-
-
-if __name__ == "__main__":
-    print("Creating user info object to represent the server's long-term storage")
-
-    print("\n\nStarting setup...")
-    user_params = bsspeke_setup()
-
-    print("\n\nRunning login...")
-    rc = bsspeke_login(user_params)
-    if rc != 0:
-        print("BS-SPEKE login failed :(")
-    else:
-        print("SUCCESS!!!!!")
diff --git a/python/setup.py b/python/setup.py
deleted file mode 100644
index bc3a7b97a3e944225e69894be7de93e2632c5e17..0000000000000000000000000000000000000000
--- a/python/setup.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from setuptools import setup
-
-setup(
-    name='BSSpeke',
-    version='0.1.0',
-    author='Charles Wright',
-    author_email='cvwright@futo.org',
-    packages=['BSSpeke'],
-    #scripts=['bin/script1','bin/script2'],
-    url='http://pypi.python.org/pypi/BS-SPEKE/',
-    license='LICENSE.txt',
-    description='An awesome package that does something',
-    long_description=open('README.md').read(),
-    setup_requires=["cffi>=1.0.0"],
-    cffi_modules=["bsspeke_build.py:ffibuilder"],
-    install_requires=["cffi>=1.0.0"],
-)
diff --git a/python/swiclops_register_bsspeke.py b/python/swiclops_register_bsspeke.py
deleted file mode 100644
index 251883f9114b947608936f7a236d65a43fd37e0d..0000000000000000000000000000000000000000
--- a/python/swiclops_register_bsspeke.py
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/bin/env python3
-
-import sys
-
-import base64
-import binascii
-import json
-
-import BSSpeke
-
-import requests
-
-import random
-
-#domain = "example.com"
-domain = sys.argv[1]
-username = "test_%04x" % random.getrandbits(16)
-user_id = "@%s:%s" % (username, domain)
-print("Running test with user id [%s]" % user_id)
-password = "P@ssword1"
-
-client = BSSpeke.Client(user_id, domain, password)
-client_id = client.get_client_id()
-blind = client.generate_blind()
-print("Got client_id = [%s]" % client_id)
-print("Got blind = [%s]" % str(blind))
-
-server = "https://matrix.%s" % domain
-print("Got server = [%s]" % server)
-path = "/_matrix/client/v3/register"
-
-email = sys.argv[2]
-
-url = server + path
-
-headers = {
-    'Content-Type': 'application/json',
-    'Accept': 'application/json'
-}
-
-
-# Request 1: Empty #####################################################
-print("\n\nRequest 1: New session\n")
-r1 = requests.post(url, headers=headers, json={})
-print("Got status: %d" % r1.status_code)
-j1 = r1.json()
-session_id = j1.get("session", None)
-print("Got session id = [%s]" % session_id)
-flows = j1.get("flows", None)
-print("Got flows:")
-uia_stages = None
-for flow in flows:
-    stages = flow.get("stages", [])
-    print("\t", stages)
-    if uia_stages is None:
-        uia_stages = stages
-print("Got response: ", json.dumps(j1, indent=4))
-
-# Request 2: Registration token ########################################
-print("\n\nRequest 2: Registration token\n")
-body = {
-    "username": username,
-    "auth": {
-        "type": "m.login.registration_token",
-        "token": "0000-1111-2222-4444",
-        "session": session_id
-    }
-}
-r2 = requests.post(url, headers=headers, json=body)
-print("Got status: %d" % r2.status_code)
-j2 = r2.json()
-completed = j2.get("completed", [])
-print("Got completed stages: ", completed)
-print("Got response: ", json.dumps(j2, indent=2))
-
-# Request 3: Terms of service ##########################################
-print("\n\nRequest 3: Terms of service\n")
-body = {
-    "username": username,
-    "auth": {
-        "type": "m.login.terms",
-        "session": session_id
-    }
-}
-r3 = requests.post(url, headers=headers, json=body)
-print("Got status: %d" % r3.status_code)
-j3 = r3.json()
-completed = j3.get("completed", [])
-print("Got completed stages: ", completed)
-print("Got response: ", json.dumps(j3, indent=4))
-
-require_email = True
-if require_email:
-
-    # Request 4: Request email token #######################################
-    print("\n\nRequest 4: Request email token\n")
-    body = {
-        "username": username,
-        "auth": {
-            "type": "m.enroll.email.request_token",
-            "email": email,
-            "session": session_id
-        }
-    }
-    r4 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r4.status_code)
-    completed = r4.json().get("completed", [])
-    print("Got completed stages: ", completed)
-
-    # Request 5: Submit email token #######################################
-    email_token = input("Enter email token: ")
-    print("\n\nRequest 5: Submit email token\n")
-    body = {
-        "username": username,
-        "auth": {
-            "type": "m.enroll.email.submit_token",
-            "token": email_token,
-            "session": session_id
-        }
-    }
-    r5 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r5.status_code)
-    completed = r5.json().get("completed", [])
-    print("Got completed stages: ", completed)
-
-# Request 6: BS-SPEKE OPRF
-print("\n\nRequest 6: BS-SPEKE OPRF\n")
-oprf_params = j1["params"]["m.enroll.bsspeke-ecc.oprf"]
-curve = oprf_params["curve"]
-blind_base64 = binascii.b2a_base64(blind, newline=False).decode('utf-8')
-print("Blind (base64) = [%s]" % blind_base64)
-
-body = {
-    "username": username,
-    "auth": {
-        "type": "m.enroll.bsspeke-ecc.oprf",
-        "curve": curve,
-        "blind": blind_base64,
-        "session": session_id
-    }
-}
-r6 = requests.post(url, headers=headers, json=body)
-print("Got status: %d" % r6.status_code)
-j6 = r6.json()
-print("Got response: ", json.dumps(j6, indent=4))
-completed = j6.get("completed", [])
-print("Got completed stages: ", completed)
-r6_params = j6.get("params", {})
-print("Got params: ", json.dumps(r6_params))
-if r6.status_code != 401:
-    error = j6.get("error", "???")
-    errcode = j6.get("errcode", "???")
-    print("Got error response: %s %s" % (errcode, error))
-
-# Request 7: BS-SPEKE Save 
-print("\n\nRequest 7: BS-SPEKE OPRF\n")
-save_params = j6["params"]["m.enroll.bsspeke-ecc.save"]
-blind_salt = save_params["blind_salt"]
-phf_params = {
-    "name": "argon2i",
-    "iterations": 3,
-    "blocks": 100000
-}
-P,V = client.generate_P_and_V(base64.b64decode(blind_salt), phf_params)
-
-body = {
-    "username": username,
-    "auth": {
-        "type": "m.enroll.bsspeke-ecc.save",
-        "P": binascii.b2a_base64(P, newline=False).decode('utf-8'),
-        "V": binascii.b2a_base64(V, newline=False).decode('utf-8'),
-        "phf_params": phf_params,
-        "session": session_id
-    }
-}
-r7 = requests.post(url, headers=headers, json=body)
-print("Got status: %d" % r7.status_code)
-j7 = r7.json()
-completed = j7.get("completed", [])
-print("Got completed stages: ", completed)
-if r7.status_code != 200:
-    error = j7.get("error", "???")
-    errcode = j7.get("errcode", "???")
-    print("Got error response: %s %s" % (errcode, error))
-
-
diff --git a/python/swiclops_register_bsspeke_and_login.py b/python/swiclops_register_bsspeke_and_login.py
deleted file mode 100644
index f3a8c74db132e3e22d50696451a2de245dd670e2..0000000000000000000000000000000000000000
--- a/python/swiclops_register_bsspeke_and_login.py
+++ /dev/null
@@ -1,310 +0,0 @@
-#!/bin/env python3
-
-import sys
-import base64
-import binascii
-import json
-import requests
-import random
-import secrets
-
-import BSSpeke
-
-def register(server, username, password, email):
-
-    path = "/_matrix/client/v3/register"
-    url = server + path
-
-    headers = {
-        'Content-Type': 'application/json',
-        'Accept': 'application/json'
-    }
-
-    # Request 1: Empty #####################################################
-    print("\n\nRequest 1: New session\n")
-    r1 = requests.post(url, headers=headers, json={})
-    print("Got status: %d" % r1.status_code)
-    j1 = r1.json()
-    session_id = j1.get("session", None)
-    print("Got session id = [%s]" % session_id)
-    flows = j1.get("flows", None)
-    print("Got flows:")
-    uia_stages = None
-    for flow in flows:
-        stages = flow.get("stages", [])
-        print("\t", stages)
-        if uia_stages is None:
-            uia_stages = stages
-    print("Got response: ", json.dumps(j1, indent=4))
-
-    # Request 2: Registration token ########################################
-    print("\n\nRequest 2: Registration token\n")
-    body = {
-        "username": username,
-        "auth": {
-            "type": "m.login.registration_token",
-            "token": "0000-1111-2222-4444",
-            "session": session_id
-        }
-    }
-    r2 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r2.status_code)
-    j2 = r2.json()
-    completed = j2.get("completed", [])
-    print("Got completed stages: ", completed)
-    print("Got response: ", json.dumps(j2, indent=2))
-
-    # Request 3: Terms of service ##########################################
-    print("\n\nRequest 3: Terms of service\n")
-    body = {
-        "username": username,
-        "auth": {
-            "type": "m.login.terms",
-            "session": session_id
-        }
-    }
-    r3 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r3.status_code)
-    j3 = r3.json()
-    completed = j3.get("completed", [])
-    print("Got completed stages: ", completed)
-    print("Got response: ", json.dumps(j3, indent=4))
-
-    require_email = True
-    if require_email:
-
-        # Request 4: Request email token #######################################
-        print("\n\nRequest 4: Request email token\n")
-        body = {
-            "username": username,
-            "auth": {
-                "type": "m.enroll.email.request_token",
-                "email": email,
-                "session": session_id
-            }
-        }
-        r4 = requests.post(url, headers=headers, json=body)
-        print("Got status: %d" % r4.status_code)
-        completed = r4.json().get("completed", [])
-        print("Got completed stages: ", completed)
-
-        # Request 5: Submit email token #######################################
-        email_token = input("Enter email token: ")
-        print("\n\nRequest 5: Submit email token\n")
-        body = {
-            "username": username,
-            "auth": {
-                "type": "m.enroll.email.submit_token",
-                "token": email_token,
-                "session": session_id
-            }
-        }
-        r5 = requests.post(url, headers=headers, json=body)
-        print("Got status: %d" % r5.status_code)
-        completed = r5.json().get("completed", [])
-        print("Got completed stages: ", completed)
-
-    # Request 6: BS-SPEKE OPRF
-    print("\n\nRequest 6: BS-SPEKE OPRF\n")
-    client = BSSpeke.Client(user_id, domain, password)
-    client_id = client.get_client_id()
-    blind = client.generate_blind()
-    print("Got client_id = [%s]" % client_id)
-    print("Got blind = [%s]" % str(blind))
-
-    oprf_params = j1["params"]["m.enroll.bsspeke-ecc.oprf"]
-    curve = oprf_params["curve"]
-    blind_base64 = binascii.b2a_base64(blind, newline=False).decode('utf-8')
-    print("Blind (base64) = [%s]" % blind_base64)
-
-    body = {
-        "username": username,
-        "auth": {
-            "type": "m.enroll.bsspeke-ecc.oprf",
-            "curve": curve,
-            "blind": blind_base64,
-            "session": session_id
-        }
-    }
-    r6 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r6.status_code)
-    j6 = r6.json()
-    print("Got response: ", json.dumps(j6, indent=4))
-    completed = j6.get("completed", [])
-    print("Got completed stages: ", completed)
-    r6_params = j6.get("params", {})
-    print("Got params: ", json.dumps(r6_params))
-    if r6.status_code != 401:
-        error = j6.get("error", "???")
-        errcode = j6.get("errcode", "???")
-        print("Got error response: %s %s" % (errcode, error))
-
-    # Request 7: BS-SPEKE Save 
-    print("\n\nRequest 7: BS-SPEKE OPRF\n")
-    save_params = j6["params"]["m.enroll.bsspeke-ecc.save"]
-    blind_salt = save_params["blind_salt"]
-    phf_params = {
-        "name": "argon2i",
-        "iterations": 3,
-        "blocks": 100000
-    }
-    P,V = client.generate_P_and_V(base64.b64decode(blind_salt), phf_params)
-
-    body = {
-        "username": username,
-        "auth": {
-            "type": "m.enroll.bsspeke-ecc.save",
-            "P": binascii.b2a_base64(P, newline=False).decode('utf-8'),
-            "V": binascii.b2a_base64(V, newline=False).decode('utf-8'),
-            "phf_params": phf_params,
-            "session": session_id
-        }
-    }
-    r7 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r7.status_code)
-    j7 = r7.json()
-    completed = j7.get("completed", [])
-    print("Got completed stages: ", completed)
-    if r7.status_code != 200:
-        error = j7.get("error", "???")
-        errcode = j7.get("errcode", "???")
-        print("Got error response: %s %s" % (errcode, error))
-
-
-def login(server, username, password):
-
-    path = "/_matrix/client/v3/login"
-    url = server + path
-
-    headers = {
-        'Content-Type': 'application/json',
-        'Accept': 'application/json'
-    }
-
-    client = BSSpeke.Client(user_id, domain, password)
-    client_id = client.get_client_id()
-    blind = client.generate_blind()
-    print("Got client_id = [%s]" % client_id)
-    print("Got blind = [%s]" % str(blind))
-
-    # Request 1: Empty #####################################################
-    print("\n\nRequest 1: New session\n")
-    body = {
-        "identifier": {
-            "type": "m.id.user",
-            "user": user_id
-        }
-    }
-    r1 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r1.status_code)
-    j1 = r1.json()
-    session_id = j1.get("session", None)
-    print("Got session id = [%s]" % session_id)
-    flows = j1.get("flows", None)
-    print("Got flows:")
-    uia_stages = None
-    for flow in flows:
-        stages = flow.get("stages", [])
-        print("\t", stages)
-        if uia_stages is None:
-            uia_stages = stages
-    print("Got response: ", json.dumps(j1, indent=4))
-
-    # Request 2: BS-SPEKE OPRF
-    print("\n\nRequest 2: BS-SPEKE OPRF\n")
-    client = BSSpeke.Client(user_id, domain, password)
-    client_id = client.get_client_id()
-    blind = client.generate_blind()
-    print("Got client_id = [%s]" % client_id)
-    print("Got blind = [%s]" % str(blind))
-
-    oprf_params = j1["params"]["m.login.bsspeke-ecc.oprf"]
-    curve = oprf_params["curve"]
-    phf_params = oprf_params["phf_params"]
-    blind_base64 = binascii.b2a_base64(blind, newline=False).decode('utf-8')
-    print("Blind (base64) = [%s]" % blind_base64)
-
-    body = {
-        "username": username,
-        "auth": {
-            "type": "m.login.bsspeke-ecc.oprf",
-            "curve": curve,
-            "blind": blind_base64,
-            "session": session_id
-        }
-    }
-    r2 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r2.status_code)
-    j2 = r2.json()
-    print("Got response: ", json.dumps(j2, indent=4))
-    completed = j2.get("completed", [])
-    print("Got completed stages: ", completed)
-    r2_params = j2.get("params", {})
-    print("Got params: ", json.dumps(r2_params))
-    if r2.status_code != 401:
-        error = j2.get("error", "???")
-        errcode = j2.get("errcode", "???")
-        print("Got error response: %s %s" % (errcode, error))
-
-    # Request 3: BS-SPEKE Verify
-    print("\n\nRequest 7: BS-SPEKE Verify\n")
-    verify_params = j2["params"]["m.login.bsspeke-ecc.verify"]
-    blind_salt_str = verify_params["blind_salt"]
-    B_str = verify_params["B"]
-    blind_salt = base64.b64decode(blind_salt_str)
-    B = base64.b64decode(B_str)
-    B_hex = binascii.b2a_hex(B).decode('utf-8')
-    print("\tB:\t[%s]" % B_hex)
-
-    A_bytes = client.generate_A(blind_salt, phf_params)
-    client.derive_shared_key(B)
-    verifier_bytes = client.generate_verifier()
-
-    A = binascii.b2a_base64(A_bytes, newline=False).decode('utf-8')
-    A_hex = binascii.b2a_hex(A_bytes).decode('utf-8')
-    print("\tA:\t[%s]" % A_hex)
-    verifier = binascii.b2a_base64(verifier_bytes, newline=False).decode('utf-8')
-
-    body = {
-        "username": username,
-        "auth": {
-            "type": "m.login.bsspeke-ecc.verify",
-            "A": A,
-            "verifier": verifier,
-            "session": session_id
-        }
-    }
-    r3 = requests.post(url, headers=headers, json=body)
-    print("Got status: %d" % r3.status_code)
-    j3 = r3.json()
-    completed = j3.get("completed", [])
-    print("Got completed stages: ", completed)
-    if r3.status_code != 200:
-        error = j3.get("error", "???")
-        errcode = j3.get("errcode", "???")
-        print("Got error response: %s %s" % (errcode, error))
-
-
-
-
-if __name__ == "__main__":
-
-    #domain = "example.com"
-    domain = sys.argv[1]
-    username = "test_%04x" % random.getrandbits(16)
-    user_id = "@%s:%s" % (username, domain)
-    print("Running test with user id [%s]" % user_id)
-    password = secrets.token_hex(8)
-
-    server = "https://matrix.%s" % domain
-    print("Got server = [%s]" % server)
-
-    email = sys.argv[2]
-
-    register(server, username, password, email)
-
-    login(server, user_id, password)
-
-
-
-