chiark / gitweb /
catacomb/__init__.py: Refactor the XDH and EdDSA classes.
[catacomb-python] / catacomb / __init__.py
index 7ea8d575a79e9bbcd524b0d6d8fe66ebca600fbd..7ac5baf91383fba7f4f55635b7a4b55f6826aa3e 100644 (file)
@@ -835,77 +835,78 @@ X448_BASE = MP(5).storel(56)
 
 Z128 = ByteString.zero(16)
 
-class _BoxyPub (object):
+class _BasePub (object):
   def __init__(me, pub, *args, **kw):
-    if len(pub) != me._PUBSZ: raise ValueError, 'bad public key'
-    super(_BoxyPub, me).__init__(*args, **kw)
+    if not me._PUBSZ.check(len(pub)): raise ValueError, 'bad public key'
+    super(_BasePub, me).__init__(*args, **kw)
     me.pub = pub
   def __repr__(me): return '%s(pub = %r)' % (_clsname(me), me.pub)
+  def _pp(me, pp): _pp_kv(pp, 'pub', me.pub)
   def _repr_pretty_(me, pp, cyclep):
     ind = _pp_bgroup_tyname(pp, me)
-    if cyclep:
-      pp.text('...')
-    else:
-      _pp_kv(pp, 'pub', me.pub)
+    if cyclep: pp.text('...')
+    else: me._pp(pp)
     pp.end_group(ind, ')')
 
-class _BoxyPriv (_BoxyPub):
+class _BasePriv (object):
   def __init__(me, priv, pub = None, *args, **kw):
-    if len(priv) != me._KEYSZ: raise ValueError, 'bad private key'
-    if pub is None: pub = me._op(priv, me._BASE)
-    super(_BoxyPriv, me).__init__(pub = pub, *args, **kw)
+    if not me._KEYSZ.check(len(priv)): raise ValueError, 'bad private key'
+    if pub is None: pub = me._pubkey(priv)
+    super(_BasePriv, me).__init__(pub = pub, *args, **kw)
     me.priv = priv
+  @classmethod
+  def generate(cls, rng = rand):
+    return cls(rng.block(cls._KEYSZ.default))
+  def __repr__(me):
+    return '%s(priv = %d, pub = %r)' % \
+        (_clsname(me), _repr_secret(me.priv), me.pub)
+  def _pp(me, pp):
+    _pp_kv(pp, 'priv', me.priv, secretp = True); pp.text(','); pp.breakable()
+    super(_BasePriv, me)._pp(pp)
+
+class _XDHPub (_BasePub):  pass
+
+class _XDHPriv (_BasePriv):
+  def _pubkey(me, priv): return me._op(priv, me._BASE)
   def agree(me, you): return me._op(me.priv, you.pub)
-  def boxkey(me, recip):
-    return me._hashkey(me.agree(recip))
-  def box(me, recip, n, m):
-    return secret_box(me.boxkey(recip), n, m)
-  def unbox(me, recip, n, c):
-    return secret_unbox(me.boxkey(recip), n, c)
-  def __repr__(me): return '%s(priv = %s, pub = %r)' % \
-      (_clsname(me), _repr_secret(me.priv), me.pub)
-  def _repr_pretty_(me, pp, cyclep):
-    ind = _pp_bgroup_tyname(pp, me)
-    if cyclep:
-      pp.text('...')
-    else:
-      _pp_kv(pp, 'priv', me.priv, True); pp.text(','); pp.breakable()
-      _pp_kv(pp, 'pub', me.pub)
-    pp.end_group(ind, ')')
+  def boxkey(me, recip): return me._hashkey(me.agree(recip))
+  def box(me, recip, n, m): return secret_box(me.boxkey(recip), n, m)
+  def unbox(me, recip, n, c): return secret_unbox(me.boxkey(recip), n, c)
 
-class X25519Pub (_BoxyPub):
-  _PUBSZ = X25519_PUBSZ
+class X25519Pub (_XDHPub):
+  _PUBSZ = KeySZSet(X25519_PUBSZ)
   _BASE = X25519_BASE
 
-class X25519Priv (_BoxyPriv, X25519Pub):
-  _KEYSZ = X25519_KEYSZ
+class X25519Priv (_XDHPriv, X25519Pub):
+  _KEYSZ = KeySZSet(X25519_KEYSZ)
   def _op(me, k, X): return x25519(k, X)
   def _hashkey(me, z): return hsalsa20_prf(z, Z128)
 
-class X448Pub (_BoxyPub):
-  _PUBSZ = X448_PUBSZ
+class X448Pub (_XDHPub):
+  _PUBSZ = KeySZSet(X448_PUBSZ)
   _BASE = X448_BASE
 
-class X448Priv (_BoxyPriv, X448Pub):
-  _KEYSZ = X448_KEYSZ
+class X448Priv (_XDHPriv, X448Pub):
+  _KEYSZ = KeySZSet(X448_KEYSZ)
   def _op(me, k, X): return x448(k, X)
   ##def _hashkey(me, z): return ???
 
-class Ed25519Pub (object):
-  def __init__(me, pub):
-    me.pub = pub
+class _EdDSAPub (_BasePub):
+  pass
+
+class _EdDSAPriv (_BasePriv, _EdDSAPub):
+  pass
+
+class Ed25519Pub (_EdDSAPub):
+  _PUBSZ = KeySZSet(ED25519_PUBSZ)
   def verify(me, msg, sig):
     return ed25519_verify(me.pub, msg, sig)
 
-class Ed25519Priv (Ed25519Pub):
-  def __init__(me, priv):
-    me.priv = priv
-    Ed25519Pub.__init__(me, ed25519_pubkey(priv))
+class Ed25519Priv (_EdDSAPriv, Ed25519Pub):
+  _KEYSZ = KeySZAny(ED25519_KEYSZ)
+  def _pubkey(me, priv): return ed25519_pubkey(priv)
   def sign(me, msg):
     return ed25519_sign(me.priv, msg, pub = me.pub)
-  @classmethod
-  def generate(cls, rng = rand):
-    return cls(rng.block(ED25519_KEYSZ))
 
 ###--------------------------------------------------------------------------
 ### Built-in named curves and prime groups.