diff --git a/src/nacl/_lib/crypto_scalarmult.h b/src/nacl/_lib/crypto_scalarmult.h index dee5e84928e2f2271df849d898f5a2d4bc4ab138..e7990389cd5dc36c1368f7459cc184a593d1828a 100644 --- a/src/nacl/_lib/crypto_scalarmult.h +++ b/src/nacl/_lib/crypto_scalarmult.h @@ -17,3 +17,4 @@ size_t crypto_scalarmult_bytes(); size_t crypto_scalarmult_scalarbytes(); int crypto_scalarmult_base(unsigned char *q, const unsigned char *n); +int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p); diff --git a/src/nacl/c/__init__.py b/src/nacl/c/__init__.py index 48b369a40ed57d6dcdc27b31d19be77d17987c71..0a73a5ba09a14b3676803a30e548a7238e106a57 100644 --- a/src/nacl/c/__init__.py +++ b/src/nacl/c/__init__.py @@ -25,7 +25,7 @@ from nacl.c.crypto_hash import ( ) from nacl.c.crypto_scalarmult import ( crypto_scalarmult_BYTES, crypto_scalarmult_SCALARBYTES, - crypto_scalarmult_base, + crypto_scalarmult, crypto_scalarmult_base, ) from nacl.c.crypto_secretbox import ( crypto_secretbox_KEYBYTES, crypto_secretbox_NONCEBYTES, @@ -63,6 +63,7 @@ __all__ = [ "crypto_scalarmult_BYTES", "crypto_scalarmult_SCALARBYTES", + "crypto_scalarmult", "crypto_scalarmult_base", "crypto_secretbox_KEYBYTES", diff --git a/src/nacl/c/crypto_scalarmult.py b/src/nacl/c/crypto_scalarmult.py index b94841e49879f3ff19e2b9d2eccca20bc48227bc..f5ba2bacece2c78b0fef2fe261ebc196b4c93b65 100644 --- a/src/nacl/c/crypto_scalarmult.py +++ b/src/nacl/c/crypto_scalarmult.py @@ -36,3 +36,21 @@ def crypto_scalarmult_base(n): "An error occurred while computing the scalar product") return lib.ffi.buffer(q, crypto_scalarmult_SCALARBYTES)[:] + + +def crypto_scalarmult(n, p): + """ + Computes and returns the scalar product of the given group element and an + integer ``n``. + + :param p: bytes + :param n: bytes + :rtype: bytes + """ + q = lib.ffi.new("unsigned char[]", crypto_scalarmult_BYTES) + + if lib.crypto_scalarmult(q, n, p) != 0: + raise CryptoError( + "An error occurred while computing the scalar product") + + return lib.ffi.buffer(q, crypto_scalarmult_SCALARBYTES)[:] diff --git a/tests/test_raw.py b/tests/test_raw.py index a3a0ed4f75c6fa2591cc87d6c21d87872fe5b7d4..2a608749f6ffa98bd90baaa4fc2306168cb2ea5d 100644 --- a/tests/test_raw.py +++ b/tests/test_raw.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from binascii import hexlify +from binascii import hexlify, unhexlify from nacl import c import hashlib @@ -108,6 +108,21 @@ def test_scalarmult(): x, xpub = secret_scalar() assert len(x) == 32 y, ypub = secret_scalar() - - bx = c.crypto_scalarmult_base(x) - assert tohex(bx) == tohex(xpub) + # the Curve25519 base point (generator) + base = unhexlify(b"09" + b"00"*31) + + bx1 = c.crypto_scalarmult_base(x) + bx2 = c.crypto_scalarmult(x, base) + assert tohex(bx1) == tohex(bx2) + assert tohex(bx1) == tohex(xpub) + + xby = c.crypto_scalarmult(x, c.crypto_scalarmult_base(y)) + ybx = c.crypto_scalarmult(y, c.crypto_scalarmult_base(x)) + assert tohex(xby) == tohex(ybx) + + z = unhexlify(b"10"*32) + bz1 = c.crypto_scalarmult_base(z) + assert tohex(bz1) == ("781faab908430150daccdd6f9d6c5086" + "e34f73a93ebbaa271765e5036edfc519") + bz2 = c.crypto_scalarmult(z, base) + assert tohex(bz1) == tohex(bz2)