From 52926494f12d2952775ee4dc0f2f22eb9a3661cd Mon Sep 17 00:00:00 2001 From: Donald Stufft <donald@stufft.io> Date: Sun, 17 Mar 2013 17:35:09 -0400 Subject: [PATCH] Enable deriving PublicKey from a PrivateKey * Uses lower level functions to generate a public_key from a private key. * Reworks the generate method to just generate a random value. --- nacl/nacl.py | 7 +++++++ nacl/public.py | 47 +++++++++++++++++++++-------------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/nacl/nacl.py b/nacl/nacl.py index aa78d852..20cc74d3 100644 --- a/nacl/nacl.py +++ b/nacl/nacl.py @@ -66,6 +66,11 @@ ffi.cdef( """ void randombytes(unsigned char * const buf, const unsigned long long buf_len); """ + + # Low Level - Scalar Multiplication + """ + int crypto_scalarmult_curve25519_base(unsigned char *q, const unsigned char *n); + """ ) @@ -98,3 +103,5 @@ lib.crypto_box_beforenm = wrap_nacl_function(lib.crypto_box_beforenm) lib.crypto_hash = wrap_nacl_function(lib.crypto_hash) lib.crypto_hash_sha256 = wrap_nacl_function(lib.crypto_hash_sha256) lib.crypto_hash_sha512 = wrap_nacl_function(lib.crypto_hash_sha512) + +lib.crypto_scalarmult_curve25519_base = wrap_nacl_function(lib.crypto_scalarmult_curve25519_base) diff --git a/nacl/public.py b/nacl/public.py index c62b6edd..0f84a7b8 100644 --- a/nacl/public.py +++ b/nacl/public.py @@ -5,6 +5,7 @@ from . import six from . import nacl, encoding from .exceptions import CryptoError +from .utils import random class PublicKey(encoding.Encodable, six.StringFixer, object): @@ -47,12 +48,24 @@ class PrivateKey(encoding.Encodable, six.StringFixer, object): PRIVATEKEY_SIZE = nacl.lib.crypto_box_SECRETKEYBYTES def __init__(self, private_key, encoder=encoding.RawEncoder): - self._private_key = encoder.decode(private_key) - self._public_key = None + # Decode the secret_key + private_key = encoder.decode(private_key) - if len(self._private_key) != self.PRIVATEKEY_SIZE: - raise ValueError('The private key must be exactly %s bytes long' % - self.PRIVATEKEY_SIZE) + # Verify that our seed is the proper size + skey_size = nacl.lib.crypto_box_SECRETKEYBYTES + if len(private_key) != skey_size: + raise ValueError( + 'The secret key must be exactly %d bytes long' % (skey_size,)) + + pk = nacl.ffi.new("unsigned char[]", nacl.lib.crypto_box_PUBLICKEYBYTES) + + if not nacl.lib.crypto_scalarmult_curve25519_base(pk, private_key): + raise CryptoError("Failed to generate a key pair") + + _pkey = nacl.ffi.buffer(pk, nacl.lib.crypto_box_PUBLICKEYBYTES)[:] + + self._private_key = private_key + self.public_key = PublicKey(_pkey) def __bytes__(self): return self._private_key @@ -64,27 +77,9 @@ class PrivateKey(encoding.Encodable, six.StringFixer, object): :rtype: :class:`~nacl.public.PrivateKey` """ - pk = nacl.ffi.new("unsigned char[]", PublicKey.PUBLICKEY_SIZE) - sk = nacl.ffi.new("unsigned char[]", cls.PRIVATEKEY_SIZE) - - public_key = nacl.ffi.buffer(pk, PublicKey.PUBLICKEY_SIZE)[:] - private_key = nacl.ffi.buffer(sk, cls.PRIVATEKEY_SIZE)[:] - - if not nacl.lib.crypto_box_keypair(public_key, private_key): - raise CryptoError("Failed to generate key pair") - - sk = cls(private_key) - sk.public_key = public_key - - return sk - - @property - def public_key(self): - return self._public_key - - @public_key.setter - def public_key(self, value): - self._public_key = value + return cls(random(nacl.lib.nacl.lib.crypto_box_SECRETKEYBYTES), + encoder=encoding.RawEncoder, + ) class Box(encoding.Encodable, six.StringFixer, object): -- GitLab