summaryrefslogtreecommitdiff
path: root/src/pycryptopp/publickey/ed25519/keys.py
diff options
context:
space:
mode:
authorMicah Anderson <micah@riseup.net>2013-08-22 16:39:52 -0400
committerMicah Anderson <micah@riseup.net>2013-08-22 16:39:52 -0400
commit5e60e0e3af85f22aa0afe8bf0ecf85619afacfeb (patch)
tree6a91a3de86fa8de0b4167cc947ab72991bf8da31 /src/pycryptopp/publickey/ed25519/keys.py
parent30e9097985656920f01a72efc1088caa2b8d41b3 (diff)
Imported Upstream version 0.6.0.12upstream/0.6.0.12
Diffstat (limited to 'src/pycryptopp/publickey/ed25519/keys.py')
-rw-r--r--src/pycryptopp/publickey/ed25519/keys.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/pycryptopp/publickey/ed25519/keys.py b/src/pycryptopp/publickey/ed25519/keys.py
new file mode 100644
index 0000000..5d7eafb
--- /dev/null
+++ b/src/pycryptopp/publickey/ed25519/keys.py
@@ -0,0 +1,70 @@
+import _ed25519
+BadSignatureError = _ed25519.BadSignatureError
+
+class SigningKey(object):
+ # this is how all keys are created
+ def __init__(self, sk_bytes):
+ if not isinstance(sk_bytes, type("")):
+ raise TypeError("must be bytes, not %s" % type(sk_bytes))
+ if len(sk_bytes) != 32:
+ raise ValueError("must be exactly 32 bytes")
+ vk_bytes, sk_and_vk = _ed25519.publickey(sk_bytes)
+ assert sk_and_vk[:32] == sk_bytes
+ assert vk_bytes == sk_and_vk[32:]
+ self.vk_bytes = vk_bytes
+ self.sk_and_vk = sk_and_vk
+
+ def __eq__(self, them):
+ if not isinstance(them, object): return False
+ return (them.__class__ == self.__class__
+ and them.sk_and_vk == self.sk_and_vk)
+
+ def get_verifying_key_bytes(self):
+ return self.vk_bytes
+
+ def sign(self, msg):
+ sig_and_msg = _ed25519.sign(msg, self.sk_and_vk)
+ # the response is R+S+msg
+ sig_R = sig_and_msg[0:32]
+ sig_S = sig_and_msg[32:64]
+ msg_out = sig_and_msg[64:]
+ sig_out = sig_R + sig_S
+ assert msg_out == msg
+ return sig_out
+
+class VerifyingKey(object):
+ def __init__(self, vk_bytes):
+ if not isinstance(vk_bytes, type("")):
+ raise TypeError("must be bytes, not %s" % type(vk_bytes))
+ if len(vk_bytes) != 32:
+ raise ValueError("must be exactly 32 bytes")
+ self.vk_bytes = vk_bytes
+
+ def __eq__(self, them):
+ if not isinstance(them, object): return False
+ return (them.__class__ == self.__class__
+ and them.vk_bytes == self.vk_bytes)
+
+ def verify(self, sig, msg):
+ assert isinstance(sig, type("")) # string, really bytes
+ assert len(sig) == 64
+ sig_R = sig[:32]
+ sig_S = sig[32:]
+ sig_and_msg = sig_R + sig_S + msg
+ # this might raise BadSignatureError
+ msg2 = _ed25519.open(sig_and_msg, self.vk_bytes)
+ assert msg2 == msg
+
+def selftest():
+ from binascii import unhexlify
+ message = "crypto libraries should always test themselves at powerup"
+ sk_bytes = unhexlify("548b1f9f938519ad3d527d8c47a1e6ec1439fbec61710b245363865c6f234899")
+ sk = SigningKey(sk_bytes)
+ vk_bytes = unhexlify("787162d9ad1ad571237681560c1ad653fb7df9e09e637e6a8072e4520fd288ca")
+ vk = VerifyingKey(vk_bytes)
+ assert sk.get_verifying_key_bytes() == vk_bytes
+ sig = sk.sign(message)
+ assert sig == "13f42bc2d485e76c7cfaad25e1a840ede25b44a73befb0a528d836d7b434cf87e260c09d980388fab4cb564885857ea4dc3fb04107ca74960cc5a4d415fbf50d".decode('hex'), sig
+ vk.verify(sig, message)
+
+selftest()