[Cryptech-Commits] [user/shatov/curve25519_fpga_model] branch master updated: Added randomized test vector.

git at cryptech.is git at cryptech.is
Fri Nov 9 15:55:32 UTC 2018


This is an automated email from the git hooks/post-receive script.

meisterpaul1 at yandex.ru pushed a commit to branch master
in repository user/shatov/curve25519_fpga_model.

The following commit(s) were added to refs/heads/master by this push:
     new 800fc6c  Added randomized test vector.
800fc6c is described below

commit 800fc6c9b5d0c9c6706e5333101cc12af351a327
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Fri Nov 9 17:55:22 2018 +0300

    Added randomized test vector.
---
 ed25519/ed25519_fpga_model.cpp                     |  25 +-
 ed25519/ed25519_fpga_model.h                       |   3 +-
 vectors/ed25519/ed25519_test_vector_randomized.h   |  10 +
 vectors/ed25519/ed25519_test_vector_randomized.vh  |  10 +
 ...st_vectors.h => ed25519_test_vectors_rfc8032.h} |   0
 vectors/ed25519/format_test_vector.py              | 297 +++++++++++++++++++++
 vectors/ed25519/regenerate_test_vector.py          |  97 +++++++
 vectors/ed25519/test.key                           |   3 +
 8 files changed, 438 insertions(+), 7 deletions(-)

diff --git a/ed25519/ed25519_fpga_model.cpp b/ed25519/ed25519_fpga_model.cpp
index 69c184c..d0b5a25 100644
--- a/ed25519/ed25519_fpga_model.cpp
+++ b/ed25519/ed25519_fpga_model.cpp
@@ -40,7 +40,7 @@
 //------------------------------------------------------------------------------
 // Mode Switch
 //------------------------------------------------------------------------------
-#define USE_MICROCODE
+//#define USE_MICROCODE
 
 
 //------------------------------------------------------------------------------
@@ -63,11 +63,12 @@ static	FPGA_WORD	fpga_model_ed25519_bswap			(FPGA_WORD w);
 //------------------------------------------------------------------------------
 // Locals
 //------------------------------------------------------------------------------
-static FPGA_BUFFER ed25519_d_1, ed25519_q_y_1;
-static FPGA_BUFFER ed25519_d_2, ed25519_q_y_2;
-static FPGA_BUFFER ed25519_d_3, ed25519_q_y_3;
-static FPGA_BUFFER ed25519_d_4, ed25519_q_y_4;
-static FPGA_BUFFER ed25519_d_5, ed25519_q_y_5;
+static FPGA_BUFFER ed25519_d_1, ed25519_q_y_1;	// #1 from RFC
+static FPGA_BUFFER ed25519_d_2, ed25519_q_y_2;	// #2 from RFC
+static FPGA_BUFFER ed25519_d_3, ed25519_q_y_3;	// #3 from RFC
+static FPGA_BUFFER ed25519_d_4, ed25519_q_y_4;	// #4 from RFC
+static FPGA_BUFFER ed25519_d_5, ed25519_q_y_5;	// #5 from RFC
+static FPGA_BUFFER ed25519_d_6, ed25519_q_y_6;	// randomized
 
 
 //------------------------------------------------------------------------------
@@ -126,6 +127,14 @@ int main()
 	if (!ok) return EXIT_FAILURE;
 
 
+		//
+		// test base point multiplier: Q = d * G
+		//
+	printf("Trying to derive public key from private key...\n\n");
+	ok = test_ed25519_base_point_multiplier(&ed25519_d_6, &ed25519_q_y_6);
+	if (!ok) return EXIT_FAILURE;
+
+
 		//
 		// everything went just fine
 		//
@@ -144,12 +153,14 @@ static void fpga_model_ed25519_init()
 	FPGA_WORD tmp_d_3[FPGA_OPERAND_NUM_WORDS]	= ED25519_D_HASHED_LSB_3;
 	FPGA_WORD tmp_d_4[FPGA_OPERAND_NUM_WORDS]	= ED25519_D_HASHED_LSB_4;
 	FPGA_WORD tmp_d_5[FPGA_OPERAND_NUM_WORDS]	= ED25519_D_HASHED_LSB_5;
+	FPGA_WORD tmp_d_6[FPGA_OPERAND_NUM_WORDS]	= ED25519_D_HASHED_LSB_6;
 
 	FPGA_WORD tmp_q_y_1[FPGA_OPERAND_NUM_WORDS]	= ED25519_Q_Y_1;
 	FPGA_WORD tmp_q_y_2[FPGA_OPERAND_NUM_WORDS]	= ED25519_Q_Y_2;
 	FPGA_WORD tmp_q_y_3[FPGA_OPERAND_NUM_WORDS]	= ED25519_Q_Y_3;
 	FPGA_WORD tmp_q_y_4[FPGA_OPERAND_NUM_WORDS]	= ED25519_Q_Y_4;
 	FPGA_WORD tmp_q_y_5[FPGA_OPERAND_NUM_WORDS]	= ED25519_Q_Y_5;
+	FPGA_WORD tmp_q_y_6[FPGA_OPERAND_NUM_WORDS]	= ED25519_Q_Y_6;
 
 		/* fill buffers for large multi-word integers */
 	for (	w_src = 0, w_dst = FPGA_OPERAND_NUM_WORDS - 1;
@@ -161,6 +172,7 @@ static void fpga_model_ed25519_init()
 		ed25519_d_3.words[w_dst] = tmp_d_3[w_src];
 		ed25519_d_4.words[w_dst] = tmp_d_4[w_src];
 		ed25519_d_5.words[w_dst] = tmp_d_5[w_src];
+		ed25519_d_6.words[w_dst] = tmp_d_6[w_src];
 
 		// public key is in reverse order
 		ed25519_q_y_1.words[w_dst] = fpga_model_ed25519_bswap(tmp_q_y_1[w_dst]);
@@ -168,6 +180,7 @@ static void fpga_model_ed25519_init()
 		ed25519_q_y_3.words[w_dst] = fpga_model_ed25519_bswap(tmp_q_y_3[w_dst]);
 		ed25519_q_y_4.words[w_dst] = fpga_model_ed25519_bswap(tmp_q_y_4[w_dst]);
 		ed25519_q_y_5.words[w_dst] = fpga_model_ed25519_bswap(tmp_q_y_5[w_dst]);
+		ed25519_q_y_6.words[w_dst] = fpga_model_ed25519_bswap(tmp_q_y_6[w_dst]);
 	}
 }
 
diff --git a/ed25519/ed25519_fpga_model.h b/ed25519/ed25519_fpga_model.h
index edc554c..e5959e8 100644
--- a/ed25519/ed25519_fpga_model.h
+++ b/ed25519/ed25519_fpga_model.h
@@ -42,7 +42,8 @@
 //------------------------------------------------------------------------------
 #include "curve25519_fpga_model.h"
 #include "ed25519_fpga_curve.h"
-#include "ed25519_test_vectors.h"
+#include "ed25519_test_vectors_rfc8032.h"
+#include "ed25519_test_vector_randomized.h"
 
 
 //------------------------------------------------------------------------------
diff --git a/vectors/ed25519/ed25519_test_vector_randomized.h b/vectors/ed25519/ed25519_test_vector_randomized.h
new file mode 100644
index 0000000..a0b1be2
--- /dev/null
+++ b/vectors/ed25519/ed25519_test_vector_randomized.h
@@ -0,0 +1,10 @@
+/* Generated automatically, do not edit. */
+
+#define ED25519_D_HASHED_LSB_6 \
+	{0xd113a775, 0xbfac968b, 0x5bf260cc, 0x37789168, \
+	 0x05382510, 0x82f24eae, 0xbd117736, 0xa026eb91}
+
+#define ED25519_Q_Y_6 \
+	{0xd77e1772, 0x5eef1ad5, 0x47a37ed5, 0xc524d9b5, \
+	 0x3b52c180, 0x961658d5, 0x62b991b1, 0x1fc5a8f9}
+
diff --git a/vectors/ed25519/ed25519_test_vector_randomized.vh b/vectors/ed25519/ed25519_test_vector_randomized.vh
new file mode 100644
index 0000000..6200e13
--- /dev/null
+++ b/vectors/ed25519/ed25519_test_vector_randomized.vh
@@ -0,0 +1,10 @@
+/* Generated automatically, do not edit. */
+
+localparam [255:0] ED25519_D_HASHED_LSB_6 =
+	{32'hd113a775, 32'hbfac968b, 32'h5bf260cc, 32'h37789168, 
+	 32'h05382510, 32'h82f24eae, 32'hbd117736, 32'ha026eb91};
+
+localparam [255:0] ED25519_Q_Y_6          =
+	{32'hd77e1772, 32'h5eef1ad5, 32'h47a37ed5, 32'hc524d9b5, 
+	 32'h3b52c180, 32'h961658d5, 32'h62b991b1, 32'h1fc5a8f9};
+
diff --git a/vectors/ed25519/ed25519_test_vectors.h b/vectors/ed25519/ed25519_test_vectors_rfc8032.h
similarity index 100%
rename from vectors/ed25519/ed25519_test_vectors.h
rename to vectors/ed25519/ed25519_test_vectors_rfc8032.h
diff --git a/vectors/ed25519/format_test_vector.py b/vectors/ed25519/format_test_vector.py
new file mode 100644
index 0000000..e0173d3
--- /dev/null
+++ b/vectors/ed25519/format_test_vector.py
@@ -0,0 +1,297 @@
+#
+# format_test_vector.py
+# -----------------------------------------
+# Formats test vector for ed25519_fpga_model
+#
+# Author: Pavel Shatov
+# Copyright (c) 2017-2018, NORDUnet A/S
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+#   be used to endorse or promote products derived from this software
+#   without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+
+#
+USAGE = "USAGE: format_test_vector.py [openssl_binary]"
+#
+
+#
+# This script reads the test vector generated by regenerate_test_vector.py
+# and writes nicely formatted C header file and Verilog include file.
+#
+
+#
+# IMPORTANT: As far as I understand, this will only work with OpenSSL 1.1.1,
+# versions 1.1.0 and 1.0.2 don't seem to support the Ed25519 algoritm. If you
+# system library is the older version, you can pass the location of the
+# specific OpenSSL binary to use on the command line.
+#
+
+
+#
+# imports
+#
+import sys
+import subprocess
+import hashlib
+
+
+#
+# variables
+#
+OPENSSL = ""
+
+
+#
+# format one test vector
+#
+def format_c_header(f, d, qy):
+    
+        # write all numbers in vector
+    format_c_array(f, d,  "#define ED25519_D_HASHED_LSB_6" + " \\\n")
+    format_c_array(f, qy, "#define ED25519_Q_Y_6"          + " \\\n")
+
+    
+#
+# format one test vector
+#
+def format_verilog_include(f, d, qy):
+
+        # write all numbers in vector
+    format_verilog_concatenation(f, d,  "localparam [255:0] ED25519_D_HASHED_LSB_6 =\n")
+    format_verilog_concatenation(f, qy, "localparam [255:0] ED25519_Q_Y_6          =\n")
+
+
+#
+# nicely format multi-word integer into C array initializer
+#
+def format_c_array(f, n, s):
+
+        # print '#define XYZ \'
+    f.write(s)
+
+        # convert number to hex string and prepend it with zeroes if necessary
+    n_hex = hex(n).lstrip("0x").rstrip("L")
+    while (len(n_hex) % 8) > 0:
+        n_hex = "0" + n_hex
+    
+        # get number of 32-bit words
+    num_words = len(n_hex) // 8
+
+        # print all words in n
+    w = 0
+    while w < num_words:
+    
+        n_part = ""
+
+            # add tab for every new line
+        if w == 0:
+            n_part += "\t{"
+        elif (w % 4) == 0:
+            n_part += "\t "
+            
+            # add current word
+        n_part += "0x" + n_hex[8 * w : 8 * (w + 1)]
+        
+            # add separator or newline
+        if (w + 1) == num_words:
+            n_part += "}\n"
+        else:
+            n_part += ", "
+            if (w % 4) == 3:
+                n_part += "\\\n"        
+                
+        w += 1
+        
+            # write current part
+        f.write(n_part)
+    
+        # write final newline
+    f.write("\n")
+
+#
+# nicely format wide number into Verilog concatenation
+#
+def format_verilog_concatenation(f, n, s):
+
+        # print 'localparam ZZZ ='
+    f.write(s)
+    
+        # convert number to hex string and prepend it with zeroes if necessary
+    n_hex = hex(n).split("0x")[1]
+    while (len(n_hex) % 8) > 0:
+        n_hex = "0" + n_hex
+    
+        # get number of 32-bit words
+    num_words = len(n_hex) // 8
+
+        # print all words in n
+    w = 0
+    while w < num_words:
+    
+        n_part = ""
+        
+        if w == 0:
+            n_part += "\t{"
+        elif (w % 4) == 0:
+            n_part += "\t "
+            
+        n_part += "32'h" + n_hex[8 * w : 8 * (w + 1)]
+        
+        if (w + 1) == num_words:
+            n_part += "};\n"
+        else:
+            n_part += ", "
+            if (w % 4) == 3:
+                n_part += "\n"        
+        w += 1
+        
+        f.write(n_part)
+    
+    f.write("\n")
+
+
+    #
+    # returns d, qy where
+    # d is the private key and qy is the corresponding public key
+    #
+def get_key(openssl, party):
+
+        # generate private key filename
+    key_file = party + ".key"
+        
+        # retrieve key components using openssl
+    openssl_command = [openssl, "pkey", "-in", key_file, "-noout", "-text"] 
+    openssl_stdout = subprocess.check_output(openssl_command).decode("utf-8")
+    stdout_lines = openssl_stdout.splitlines()
+    
+    key_priv = ""
+    key_pub = ""
+
+    found_priv = False
+    found_pub = False
+    
+        # process lines looking for "priv:" and "pub:" markers
+    for line in stdout_lines:
+       
+            # found private key marker?
+        if line == "priv:":
+            found_priv = True
+            found_pub = False
+            continue
+            
+            # found public key marker?
+        if line == "pub:":
+            found_pub = True
+            found_priv = False
+            continue
+            
+            # found part of private key?
+        if found_priv:
+            if not line.startswith(" "):
+                found_priv = False
+                continue
+            else:
+                key_priv += line.strip()
+            
+            # found part of public key?
+        if found_pub:
+            if not line.startswith(" "):
+                found_pub = False
+                continue
+            else:
+                key_pub += line.strip()
+            
+        # do some cleanup and sanity checking on private key
+        #  * remove colons
+        #  * check length (256 bits)
+    key_priv = key_priv.replace(":", "")
+    if len(key_priv) != (256 / 4): sys.exit()
+    
+        # do some cleanup and sanity checking on public key
+        #  * remove colons
+        #  * check length (256 bits)
+    key_pub = key_pub.replace(":", "")
+    if len(key_pub) != (256 / 4): sys.exit()
+
+        # convert to byte arrays
+    key_priv_bytes = bytes.fromhex(key_priv)
+    key_pub_bytes = bytes.fromhex(key_pub)
+        
+        # hash private key
+    key_priv_hashed_bytes = hashlib.sha512(key_priv_bytes).digest()
+    
+        # take the lower half and reverse byte order
+    key_priv_hashed_lsb_bytes = key_priv_hashed_bytes[:32][::-1]
+            
+        # done
+    return key_priv_hashed_lsb_bytes, key_pub_bytes
+
+    
+if __name__ == "__main__":
+
+        # detect whether user requested some specific binary
+    if len(sys.argv) == 1:
+        OPENSSL = "openssl"
+        print("Using system OpenSSL library.")
+    elif len(sys.argv) == 2:
+        OPENSSL = sys.argv[1]
+        print("Using OpenSSL binary '" + OPENSSL + "'...")
+    else:
+        print(USAGE)
+
+    if len(OPENSSL) > 0:
+    
+            # open output files
+        file_h = open('ed25519_test_vector_randomized.h', 'w')
+        file_v = open('ed25519_test_vector_randomized.vh', 'w')
+        
+            # write headers
+        file_h.write("/* Generated automatically, do not edit. */\n\n")
+        file_v.write("/* Generated automatically, do not edit. */\n\n")
+        
+            # load keys
+        d, qy = get_key(OPENSSL, "test")
+
+            # convert to integers
+        d_int  = int(d.hex(), 16)
+        qy_int = int(qy.hex(), 16)
+        
+            # format numbers and write to file
+        format_c_header(file_h, d_int, qy_int)
+        format_verilog_include(file_v, d_int, qy_int)
+
+            # done
+        file_h.close()
+        file_v.close()
+        
+            # everything went just fine
+        print("Test vector formatted.")
+
+#
+# End of file
+#
diff --git a/vectors/ed25519/regenerate_test_vector.py b/vectors/ed25519/regenerate_test_vector.py
new file mode 100644
index 0000000..295fe33
--- /dev/null
+++ b/vectors/ed25519/regenerate_test_vector.py
@@ -0,0 +1,97 @@
+#
+# regenerate_test_vector.py
+# ------------------------------------------------------------
+# Generates a new randomized test vector for ed25519_fpga_model
+#
+# Author: Pavel Shatov
+# Copyright (c) 2017-2018, NORDUnet A/S
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# - Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+#
+# - Neither the name of the NORDUnet nor the names of its contributors may
+#   be used to endorse or promote products derived from this software
+#   without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+#
+USAGE = "USAGE: regenerate_test_vector.py [openssl_binary]"
+#
+
+#
+# This script generates a new randomized test vector that contains a
+# private key
+#
+
+#
+# IMPORTANT: As far as I understand, this will only work with OpenSSL 1.1.1,
+# versions 1.1.0 and 1.0.2 don't seem to support the Ed25519 algoritm. If you
+# system library is the older version, you can pass the location of the
+# specific OpenSSL binary to use on the command line.
+#
+
+#
+# imports
+#
+import sys
+import subprocess
+
+#
+# variables
+#
+SECRET_KEY = "test.key"
+
+OPENSSL = ""
+
+
+#
+# openssl_genpkey
+#
+def openssl_genpkey(binary, filename):
+		
+	subprocess.call([binary, "genpkey", "-algorithm", "Ed25519", "-out", filename])
+
+	
+#
+# __main__
+#
+if __name__ == "__main__":
+
+		# detect whether user requested some specific binary
+	if len(sys.argv) == 1:
+		OPENSSL = "openssl"
+		print("Using system OpenSSL library.")
+	elif len(sys.argv) == 2:
+		OPENSSL = sys.argv[1]
+		print("Using OpenSSL binary '" + OPENSSL + "'...")
+	else:
+		print(USAGE)
+		
+		# generate two new private keys
+	if len(OPENSSL) > 0:
+		openssl_genpkey(OPENSSL, SECRET_KEY)
+
+
+#
+# End of file
+#
diff --git a/vectors/ed25519/test.key b/vectors/ed25519/test.key
new file mode 100644
index 0000000..518de37
--- /dev/null
+++ b/vectors/ed25519/test.key
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIHqdYrc9RO2uJhy+P7QWTIcmkYtG/8tNhP9ieVB5OqWP
+-----END PRIVATE KEY-----

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Commits mailing list