From 068e8820d6f43c410d456dce0c2d730202df99ed Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@lothar.com>
Date: Fri, 20 Jun 2014 16:01:20 -0700
Subject: [PATCH] expose and test crypto_scalarmult

fixes #65
---
 src/nacl/_lib/crypto_scalarmult.h |  1 +
 src/nacl/c/__init__.py            |  3 ++-
 src/nacl/c/crypto_scalarmult.py   | 18 ++++++++++++++++++
 tests/test_raw.py                 | 23 +++++++++++++++++++----
 4 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/src/nacl/_lib/crypto_scalarmult.h b/src/nacl/_lib/crypto_scalarmult.h
index dee5e849..e7990389 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 48b369a4..0a73a5ba 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 b94841e4..f5ba2bac 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 a3a0ed4f..2a608749 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)
-- 
GitLab