[Cryptech-Commits] [user/shatov/ecdsa_fpga_model] 01/01: Added scripts to generate randomized test vectors for ECDH mode.

git at cryptech.is git at cryptech.is
Sun Dec 10 20:19:40 UTC 2017


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

meisterpaul1 at yandex.ru pushed a commit to branch ecdh
in repository user/shatov/ecdsa_fpga_model.

commit e72aeeef63933e3b4e8bb639f82cc31e1f6ad0f8
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Sun Dec 10 23:17:52 2017 +0300

    Added scripts to generate randomized test vectors for ECDH mode.
---
 ecdh_test_vectors/alice_p256.key                  |   8 +
 ecdh_test_vectors/alice_p384.key                  |   9 +
 ecdh_test_vectors/bob_p256.key                    |   8 +
 ecdh_test_vectors/bob_p384.key                    |   9 +
 ecdh_test_vectors/ecdsa_fpga_model_ecdh_vectors.h |  74 ++++
 ecdh_test_vectors/format_test_vectors.py          | 450 ++++++++++++++++++++++
 ecdh_test_vectors/regenerate_test_vectors.py      |  71 ++++
 7 files changed, 629 insertions(+)

diff --git a/ecdh_test_vectors/alice_p256.key b/ecdh_test_vectors/alice_p256.key
new file mode 100644
index 0000000..ae4ebb1
--- /dev/null
+++ b/ecdh_test_vectors/alice_p256.key
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIEBNSvo4ZaPW+SHMtHzepOknbD1FboTRlmMyTa+MXi9EoAoGCCqGSM49
+AwEHoUQDQgAEbzthrz150bZ8EoNpH+joct6B4XoGtdThru3NVwm/HRvRNFvMoCLq
+iVOwTC0R/CT4Czt/hHt53u7ZLsQw2Ow8mA==
+-----END EC PRIVATE KEY-----
diff --git a/ecdh_test_vectors/alice_p384.key b/ecdh_test_vectors/alice_p384.key
new file mode 100644
index 0000000..04aba40
--- /dev/null
+++ b/ecdh_test_vectors/alice_p384.key
@@ -0,0 +1,9 @@
+-----BEGIN EC PARAMETERS-----
+BgUrgQQAIg==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDDnM9nbuIZ7Vzy7wL2JnIjbZpMi6AQ1waTisN2xXnVzcfaEpZUF2SPI
+v5bcEcOuUFqgBwYFK4EEACKhZANiAASLhScIGDEffx7y8E2zjmiyPACL+xTiDLA3
+76Qhw8PfbaN8SE6FXamB2oZlgHID/zbXSPUV738mcgzopw4ggnKWjuaomq7M2Pth
+s1Nkxw37SOtcaFyBC9nLLRhPsQlqsw8=
+-----END EC PRIVATE KEY-----
diff --git a/ecdh_test_vectors/bob_p256.key b/ecdh_test_vectors/bob_p256.key
new file mode 100644
index 0000000..f1e17bc
--- /dev/null
+++ b/ecdh_test_vectors/bob_p256.key
@@ -0,0 +1,8 @@
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIHFZpDvoMiRxGf6usnqSRm4rB8jfKbvX6tMjKvhEmVqVoAoGCCqGSM49
+AwEHoUQDQgAEBRRgjcLcaiF0sITWFoqtE0rNP1JuSdwyv5hyqqS+mdlySvp1TGcr
+ceh8m9rh4rFfeE9ID+tiBA4oGVO96jgpRg==
+-----END EC PRIVATE KEY-----
diff --git a/ecdh_test_vectors/bob_p384.key b/ecdh_test_vectors/bob_p384.key
new file mode 100644
index 0000000..7e5b303
--- /dev/null
+++ b/ecdh_test_vectors/bob_p384.key
@@ -0,0 +1,9 @@
+-----BEGIN EC PARAMETERS-----
+BgUrgQQAIg==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDBWAYINcFIkpd1t2xPgoV52hp5qvje6IjV5Kvn2qb8RStH9MZ3YGB4G
+RPFUSE5zp1qgBwYFK4EEACKhZANiAAQ3q1VtBlLGueNSxkNFAr4Zn7nFDyreBJsG
+5QwwzasGc2nv4MBuEUp28TOBddtPSYIhzdrg8Re2VnydR3vB/F0kOyZlHhQG8e6z
+QYVSc5yTlWd0yE0gztwVkv1d4Eu/mK0=
+-----END EC PRIVATE KEY-----
diff --git a/ecdh_test_vectors/ecdsa_fpga_model_ecdh_vectors.h b/ecdh_test_vectors/ecdsa_fpga_model_ecdh_vectors.h
new file mode 100644
index 0000000..7fbb746
--- /dev/null
+++ b/ecdh_test_vectors/ecdsa_fpga_model_ecdh_vectors.h
@@ -0,0 +1,74 @@
+/* Generated automatically, do not edit. */
+
+#define P_256_DA \
+	{0x404d4afa, 0x3865a3d6, 0xf921ccb4, 0x7cdea4e9, \
+	 0x276c3d45, 0x6e84d196, 0x63324daf, 0x8c5e2f44}
+
+#define P_256_QA_X \
+	{0x6f3b61af, 0x3d79d1b6, 0x7c128369, 0x1fe8e872, \
+	 0xde81e17a, 0x06b5d4e1, 0xaeedcd57, 0x09bf1d1b}
+
+#define P_256_QA_Y \
+	{0xd1345bcc, 0xa022ea89, 0x53b04c2d, 0x11fc24f8, \
+	 0x0b3b7f84, 0x7b79deee, 0xd92ec430, 0xd8ec3c98}
+
+#define P_256_DB \
+	{0x7159a43b, 0xe8322471, 0x19feaeb2, 0x7a92466e, \
+	 0x2b07c8df, 0x29bbd7ea, 0xd3232af8, 0x44995a95}
+
+#define P_256_QB_X \
+	{0x0514608d, 0xc2dc6a21, 0x74b084d6, 0x168aad13, \
+	 0x4acd3f52, 0x6e49dc32, 0xbf9872aa, 0xa4be99d9}
+
+#define P_256_QB_Y \
+	{0x724afa75, 0x4c672b71, 0xe87c9bda, 0xe1e2b15f, \
+	 0x784f480f, 0xeb62040e, 0x281953bd, 0xea382946}
+
+#define P_256_S_X \
+	{0xa001c11b, 0x0d04b6c3, 0xbe99551e, 0x9115b811, \
+	 0x0a41a0b7, 0x59c3e3f2, 0xfb636df1, 0xeb0e9a42}
+
+#define P_256_S_Y \
+	{0x14ed5674, 0x62b6ba27, 0x2ba0e01b, 0x2647d725, \
+	 0x5919bf5e, 0xcbb542f7, 0x659d40de, 0x324524ac}
+
+#define P_384_DA \
+	{0xe733d9db, 0xb8867b57, 0x3cbbc0bd, 0x899c88db, \
+	 0x669322e8, 0x0435c1a4, 0xe2b0ddb1, 0x5e757371, \
+	 0xf684a595, 0x05d923c8, 0xbf96dc11, 0xc3ae505a}
+
+#define P_384_QA_X \
+	{0x8b852708, 0x18311f7f, 0x1ef2f04d, 0xb38e68b2, \
+	 0x3c008bfb, 0x14e20cb0, 0x37efa421, 0xc3c3df6d, \
+	 0xa37c484e, 0x855da981, 0xda866580, 0x7203ff36}
+
+#define P_384_QA_Y \
+	{0xd748f515, 0xef7f2672, 0x0ce8a70e, 0x20827296, \
+	 0x8ee6a89a, 0xaeccd8fb, 0x61b35364, 0xc70dfb48, \
+	 0xeb5c685c, 0x810bd9cb, 0x2d184fb1, 0x096ab30f}
+
+#define P_384_DB \
+	{0x5601820d, 0x705224a5, 0xdd6ddb13, 0xe0a15e76, \
+	 0x869e6abe, 0x37ba2235, 0x792af9f6, 0xa9bf114a, \
+	 0xd1fd319d, 0xd8181e06, 0x44f15448, 0x4e73a75a}
+
+#define P_384_QB_X \
+	{0x37ab556d, 0x0652c6b9, 0xe352c643, 0x4502be19, \
+	 0x9fb9c50f, 0x2ade049b, 0x06e50c30, 0xcdab0673, \
+	 0x69efe0c0, 0x6e114a76, 0xf1338175, 0xdb4f4982}
+
+#define P_384_QB_Y \
+	{0x21cddae0, 0xf117b656, 0x7c9d477b, 0xc1fc5d24, \
+	 0x3b26651e, 0x1406f1ee, 0xb3418552, 0x739c9395, \
+	 0x6774c84d, 0x20cedc15, 0x92fd5de0, 0x4bbf98ad}
+
+#define P_384_S_X \
+	{0x15ac62cb, 0xbb51e1ed, 0xd41d489f, 0xdfa05d45, \
+	 0x115f4ef2, 0x269fbd26, 0x3f6c7364, 0x673f0b19, \
+	 0x489e8a7b, 0xdfad6d40, 0x277edf9f, 0x62220c51}
+
+#define P_384_S_Y \
+	{0xa0b846fe, 0xa76973b4, 0x12dfae76, 0x2b3b6587, \
+	 0xf62be0a3, 0x73da36ef, 0x8992e7c9, 0x6cf7619d, \
+	 0xa2d6c0a2, 0xd31ad05d, 0xb3a16a95, 0x0cb7055f}
+
diff --git a/ecdh_test_vectors/format_test_vectors.py b/ecdh_test_vectors/format_test_vectors.py
new file mode 100644
index 0000000..a49b34b
--- /dev/null
+++ b/ecdh_test_vectors/format_test_vectors.py
@@ -0,0 +1,450 @@
+#
+# format_test_vectors.py
+# ------------------------------------------
+# Formats test vectors for ecdsa_fpga_model
+#
+# Author: Pavel Shatov
+# Copyright (c) 2017, 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.
+#
+
+#
+# This script reads the test vectors generated by regenerate_test_vectors.py
+# and writes nicely formatted C header file and Verilog include file.
+#
+
+#
+# imports
+#
+import sys
+import subprocess
+from fastecdsa.curve import P256
+from fastecdsa.curve import P384
+from fastecdsa.point import Point
+
+# list of curve names of interest
+CURVE_P256 = "p256"
+CURVE_P384 = "p384"
+
+# the base point for p-256
+P256_GX = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
+P256_GY = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
+
+# the base point for p-384
+P384_GX = 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7
+P384_GY = 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f  
+
+
+#
+# get part of string between two markers
+#
+#def string_between(s, s_left, s_right):
+#	s_begin = s.index(s_left) + len(s_left)
+#	s_end = s.index(s_right, s_begin)
+#	return s[s_begin:s_end]
+
+#
+# load message from file
+#
+#def read_message(key):
+#	with open(key + ".txt", "r") as f:
+#		return f.readlines()[0]
+#	
+#
+# read modulus from file
+#
+#def read_modulus(key):
+#	openssl_command = ["openssl", "rsa", "-in", key + ".key", "-noout", "-modulus"]
+#	openssl_stdout = subprocess.check_output(openssl_command).decode("utf-8")
+#	return openssl_stdout.strip().split("=")[1]
+
+#
+# read private exponent from file
+#
+#def read_secret(key):
+#	openssl_command = ["openssl", "rsa", "-in", key + ".key", "-noout", "-text"]
+#	openssl_stdout = subprocess.check_output(openssl_command).decode("utf-8")
+#	openssl_secret = string_between(openssl_stdout, "privateExponent", "prime1")
+#	openssl_secret = openssl_secret.replace(":", "")
+#	openssl_secret = openssl_secret.replace("\n", "")
+#	openssl_secret = openssl_secret.replace(" ", "")	
+#	return openssl_secret
+
+#
+# read part of private key from file
+#
+#def read_prime1(key):
+#	openssl_command = ["openssl", "rsa", "-in", key + ".key", "-noout", "-text"]
+#	openssl_stdout = subprocess.check_output(openssl_command).decode("utf-8")
+#	openssl_secret = string_between(openssl_stdout, "prime1", "prime2")
+#	openssl_secret = openssl_secret.replace(":", "")
+#	openssl_secret = openssl_secret.replace("\n", "")
+#	openssl_secret = openssl_secret.replace(" ", "")	
+#	return openssl_secret
+#def read_prime2(key):
+#	openssl_command = ["openssl", "rsa", "-in", key + ".key", "-noout", "-text"]
+#	openssl_stdout = subprocess.check_output(openssl_command).decode("utf-8")
+#	openssl_secret = string_between(openssl_stdout, "prime2", "exponent1")
+#	openssl_secret = openssl_secret.replace(":", "")
+#	openssl_secret = openssl_secret.replace("\n", "")
+#	openssl_secret = openssl_secret.replace(" ", "")	
+#	return openssl_secret
+
+#
+# read prive exponent from file
+#
+#def read_exponent1(key):
+#	openssl_command = ["openssl", "rsa", "-in", key + ".key", "-noout", "-text"]
+#	openssl_stdout = subprocess.check_output(openssl_command).decode("utf-8")
+#	openssl_secret = string_between(openssl_stdout, "exponent1", "exponent2")
+#	openssl_secret = openssl_secret.replace(":", "")
+#	openssl_secret = openssl_secret.replace("\n", "")
+#	openssl_secret = openssl_secret.replace(" ", "")	
+#	return openssl_secret
+#def read_exponent2(key):
+#	openssl_command = ["openssl", "rsa", "-in", key + ".key", "-noout", "-text"]
+#	openssl_stdout = subprocess.check_output(openssl_command).decode("utf-8")
+#	openssl_secret = string_between(openssl_stdout, "exponent2", "coefficient")
+#	openssl_secret = openssl_secret.replace(":", "")
+#	openssl_secret = openssl_secret.replace("\n", "")
+#	openssl_secret = openssl_secret.replace(" ", "")	
+#	return openssl_secret
+
+#
+# format one test vector
+#
+def format_c_header(f, curve, da, qax, qay, db, qbx, qby, sx, sy):
+
+	if curve == CURVE_P256: curve_str = "P_256"
+	if curve == CURVE_P384: curve_str = "P_384"
+	
+		# write all numbers in vector
+	format_c_array(f, da,  "#define " + curve_str + "_DA"   + " \\\n")
+	format_c_array(f, qax, "#define " + curve_str + "_QA_X" + " \\\n")
+	format_c_array(f, qay, "#define " + curve_str + "_QA_Y" + " \\\n")
+	
+	format_c_array(f, db,  "#define " + curve_str + "_DB"   + " \\\n")
+	format_c_array(f, qbx, "#define " + curve_str + "_QB_X" + " \\\n")
+	format_c_array(f, qby, "#define " + curve_str + "_QB_Y" + " \\\n")
+
+	format_c_array(f, sx,  "#define " + curve_str + "_S_X"  + " \\\n")
+	format_c_array(f, sy,  "#define " + curve_str + "_S_Y"  + " \\\n")
+	
+
+#
+# format one test vector
+#
+#def format_verilog_include(f, key, n, m, d, s, p, q, dp, dq, mp, mq):
+#
+#		# calculate factor to bring message into Montgomery domain
+#	factor = calc_montgomery_factor(int(key), n)
+#	factor_p = calc_montgomery_factor(int(key)//2, p);
+#	factor_q = calc_montgomery_factor(int(key)//2, q);
+#	
+#		# calculate helper coefficients for Montgomery multiplication
+#	n_coeff = calc_montgomery_n_coeff(int(key), n)
+#	p_coeff = calc_montgomery_n_coeff(int(key)//2, p)
+#	q_coeff = calc_montgomery_n_coeff(int(key)//2, q)
+#			
+#		# calculate the extra coefficient Montgomery multiplication brings in
+#	coeff = modinv(1 << int(key), n)
+#	
+#		# convert m into Montgomery representation
+#	m_factor = (m * factor * coeff) % n
+#		
+#		# write all numbers
+#	format_verilog_concatenation(f, m,        "localparam [" + str(int(key)-1) + ":0] M_"        + key + " =\n")
+#	format_verilog_concatenation(f, n,        "localparam [" + str(int(key)-1) + ":0] N_"        + key + " =\n")
+#	format_verilog_concatenation(f, n_coeff,  "localparam [" + str(int(key)-1) + ":0] N_COEFF_"  + key + " =\n")
+#	format_verilog_concatenation(f, factor,   "localparam [" + str(int(key)-1) + ":0] FACTOR_"   + key + " =\n")
+#	format_verilog_concatenation(f, coeff,    "localparam [" + str(int(key)-1) + ":0] COEFF_"    + key + " =\n")
+#	format_verilog_concatenation(f, m_factor, "localparam [" + str(int(key)-1) + ":0] M_FACTOR_" + key + " =\n")
+#	format_verilog_concatenation(f, d,        "localparam [" + str(int(key)-1) + ":0] D_"        + key + " =\n")
+#	format_verilog_concatenation(f, s,        "localparam [" + str(int(key)-1) + ":0] S_"        + key + " =\n")
+#	
+#	format_verilog_concatenation(f, p,        "localparam [" + str(int(key)//2-1) + ":0] P_"        + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, q,        "localparam [" + str(int(key)//2-1) + ":0] Q_"        + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, p_coeff,  "localparam [" + str(int(key)//2-1) + ":0] P_COEFF_"  + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, q_coeff,  "localparam [" + str(int(key)//2-1) + ":0] Q_COEFF_"  + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, factor_p, "localparam [" + str(int(key)//2-1) + ":0] FACTOR_P_" + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, factor_q, "localparam [" + str(int(key)//2-1) + ":0] FACTOR_Q_" + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, dp,       "localparam [" + str(int(key)//2-1) + ":0] DP_"       + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, dq,       "localparam [" + str(int(key)//2-1) + ":0] DQ_"       + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, mp,       "localparam [" + str(int(key)//2-1) + ":0] MP_"       + str(int(key)//2) + " =\n")
+#	format_verilog_concatenation(f, mq,       "localparam [" + str(int(key)//2-1) + ":0] MQ_"       + str(int(key)//2) + " =\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")
+
+
+#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, qx, qy, where
+	# d is private key and qx, qy is the corresponding public key
+	#
+def get_key(party, curve):
+
+		# generate private key filename
+	key_file = party + "_" + curve + ".key"
+		
+		# retrieve key components using openssl
+	openssl_command = ["openssl", "ec", "-in", key_file, "-noout", "-text"]	
+	openssl_stdout = subprocess.check_output(openssl_command).decode("utf-8")
+	stdout_lines = openssl_stdout.splitlines()
+	
+	found_priv = False
+	found_pub = False
+	
+	key_priv = ""
+	key_pub = ""
+	
+		# process lines looking for "priv:" and "pub:" markers
+	for line in stdout_lines:
+	
+			# found private key marker?
+		if line.strip() == "priv:":
+			found_priv = True
+			found_pub = False
+			continue
+			
+			# found public key marker?
+		if line.strip() == "pub:":		# openssl 1.0.2g prints 'pub: ' (extra space before newline),
+			found_pub = True			# so we need compare against line.strip(), not just line
+			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 extra leading zero byte if present
+		#  * remove colons
+		#  * check length (256 bits or 384 bits)
+	while key_priv.startswith("00"):
+		key_priv = key_priv[2:]
+		
+	key_priv = key_priv.replace(":", "")
+		
+	if curve == CURVE_P256 and len(key_priv) != 256 / 4: sys.exit()
+	if curve == CURVE_P384 and len(key_priv) != 384 / 4: sys.exit()
+	
+		# do some cleanup and sanity checking on public key
+		#  * make sure, that uncompressed form marker (0x04) is present and
+		#    then remove it
+		#  * remove colons
+		#  * check length (2x256 or 2x384 bits)
+	if not key_pub.startswith("04"): sys.exit()
+		
+	key_pub = key_pub[2:]
+	key_pub = key_pub.replace(":", "")
+
+	if curve == CURVE_P256 and len(key_pub) != 2 * 256 / 4: sys.exit()
+	if curve == CURVE_P384 and len(key_pub) != 2 * 384 / 4: sys.exit()
+	
+		# split public key into parts
+	if curve == CURVE_P256:
+		key_pub_x = key_pub[  0: 64]
+		key_pub_y = key_pub[ 64:128]
+	
+	if curve == CURVE_P384:
+		key_pub_x = key_pub[  0: 96]
+		key_pub_y = key_pub[ 96:192]
+	
+		# convert from strings to integers
+	key_priv = int(key_priv, 16)
+	key_pub_x = int(key_pub_x, 16)
+	key_pub_y = int(key_pub_y, 16)
+	
+		# another sanity check (make sure, that Q is actually d * G)
+	if curve == CURVE_P256:
+		G = Point(P256_GX, P256_GY, curve=P256)
+		Q = Point(key_pub_x, key_pub_y, curve=P256)
+
+	if curve == CURVE_P384:
+		G = Point(P384_GX, P384_GY, curve=P384)
+		Q = Point(key_pub_x, key_pub_y, curve=P384)
+	
+		# multiply using fastecdsa
+	R = key_priv * G
+
+	if R.x != Q.x: sys.exit()
+	if R.y != Q.y: sys.exit()
+		
+		# done
+	return key_priv, key_pub_x, key_pub_y
+
+	
+if __name__ == "__main__":
+
+		# list of curves to process
+	curves = [CURVE_P256, CURVE_P384]
+
+		# open output files
+	file_h = open('ecdsa_fpga_model_ecdh_vectors.h', 'w')
+#	file_v = open('modexp_fpga_model_vectors.v', 'w')
+	
+		# write headers
+	file_h.write("/* Generated automatically, do not edit. */\n\n")
+#	file_v.write("/* Generated automatically, do not edit. */\n\n")
+	
+		# process all the keys
+	for curve in curves:
+
+			# load keys
+		da, qax, qay = get_key("alice", curve)
+		db, qbx, qby = get_key("bob",   curve)
+		
+			# Alice's public key
+		if (curve == CURVE_P256): QA = Point(qax, qay, curve=P256)
+		if (curve == CURVE_P384): QA = Point(qax, qay, curve=P384)
+
+			# Bob's public key
+		if (curve == CURVE_P256): QB = Point(qbx, qby, curve=P256)
+		if (curve == CURVE_P384): QB = Point(qbx, qby, curve=P384)
+		
+			# we derive the shared secret two different ways (from Alice's and
+			# from Bob's perspective, they must be identical of course
+		QAB = da * QB	# Alice's secret
+		QBA = db * QA	# Bob's secret
+		
+		if (QAB.x != QBA.x): sys.exit()
+		if (QBA.y != QAB.y): sys.exit()
+		
+		print("Derived shared secret.");
+
+			# format numbers and write to file
+		format_c_header(file_h, curve, da, qax, qay, db, qbx, qby, QAB.x, QBA.y)
+#		format_verilog_include(file_v, key, modulus, message, secret, signature, prime1, prime2, exponent1, exponent2, message1, message2)
+
+		# done
+	file_h.close()
+#	file_v.close()
+	
+		# everything went just fine
+	print("Test vectors formatted.")
+
+#
+# End of file
+#
diff --git a/ecdh_test_vectors/regenerate_test_vectors.py b/ecdh_test_vectors/regenerate_test_vectors.py
new file mode 100644
index 0000000..f734854
--- /dev/null
+++ b/ecdh_test_vectors/regenerate_test_vectors.py
@@ -0,0 +1,71 @@
+#
+# regenerate_test_vectors.py
+# -------------------------------------------------------------------
+# Generates a new set of randomized test vectors for ecdsa_fpga_model
+#
+# Author: Pavel Shatov
+# Copyright (c) 2017, 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.
+#
+
+#
+# This script generates a pair of test vectors. Each test vector contains two
+# private keys. One test vector is for P-256, the other one is for P-384.
+#
+
+#
+# imports
+#
+import subprocess
+
+CURVE_P256 = "prime256v1"
+CURVE_P384 = "secp384r1"
+
+SECRET_ALICE_256 = "alice_p256.key"
+SECRET_ALICE_384 = "alice_p384.key"
+
+SECRET_BOB_256 = "bob_p256.key"
+SECRET_BOB_384 = "bob_p384.key"
+
+def openssl_ecparam_genkey(curve, file):
+	subprocess.call(["openssl", "ecparam", "-genkey", "-name", curve, "-out", file])
+
+if __name__ == "__main__":
+
+		# generate two new private keys for P-256 curve
+	openssl_ecparam_genkey(CURVE_P256, SECRET_ALICE_256)
+	openssl_ecparam_genkey(CURVE_P256, SECRET_BOB_256)
+	
+		# generate two new private keys for P-384 curve
+	openssl_ecparam_genkey(CURVE_P384, SECRET_ALICE_384)
+	openssl_ecparam_genkey(CURVE_P384, SECRET_BOB_384)
+
+#
+# End of file
+#



More information about the Commits mailing list