aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2017-06-13 20:11:58 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2017-06-13 20:11:58 +0300
commit53e92c5355aca120eab8d59e6904282c9e3b4ab1 (patch)
tree62c6b65e52c01bbbfdac063ec8ba791a9d073203 /test
Initial commit of faster modular exponentiation model based on systolic architecture.
Diffstat (limited to 'test')
-rw-r--r--test/384.key8
-rw-r--r--test/384.txt1
-rw-r--r--test/512.key9
-rw-r--r--test/512.txt1
-rw-r--r--test/format_test_vectors.py302
-rw-r--r--test/modexp_fpga_model_vectors.h46
-rw-r--r--test/modexp_fpga_model_vectors.v68
-rw-r--r--test/regenerate_test_vectors.py85
8 files changed, 520 insertions, 0 deletions
diff --git a/test/384.key b/test/384.key
new file mode 100644
index 0000000..30d3170
--- /dev/null
+++ b/test/384.key
@@ -0,0 +1,8 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIHzAgEAAjEAsGtN4xAGIU+qPIyubFaEd7jI2LIIaEBwO5umdHOeDuyVCg2KtrdE
+Pf6+aQzigQCZAgMBAAECMQCtJKMMdm2Nw+IQCwIk0cSwu2pjQld9+b6Jux7D3DJZ
+8Bo0P5NXoSWZoyiuL/he9AECGQDprEz2A7LYCn8dCR5J1fGgrCrk/7+b83UCGQDB
+Ro8+xpCSMVpNdLpHezA/Sy4Q0R9E6BUCGGm2woaV+8YTUZiANIyw1oSa/zjknvnd
+tQIYHtqCt4S/Q3c5cS/3JL4Xn6MCwZCAq2FZAhkA4ixTus6Idmm9mEaxkVocycbi
+bXrEdV0q
+-----END RSA PRIVATE KEY-----
diff --git a/test/384.txt b/test/384.txt
new file mode 100644
index 0000000..3b13314
--- /dev/null
+++ b/test/384.txt
@@ -0,0 +1 @@
+00d1bda66c3babf4e418ec5b184354145ed5b8aa0b62f138845515191e94e6250901814a138eda0556b54f831cd7605d \ No newline at end of file
diff --git a/test/512.key b/test/512.key
new file mode 100644
index 0000000..d8a7271
--- /dev/null
+++ b/test/512.key
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOwIBAAJBAO94tO2u4cx4ZZuZNTnV9eGkfCspWjjoxIXiuEajVGFP3h+U7nRi
+uo+ZH/7DYXK8ehF4QVZXK25Boj+o0CV66PcCAwEAAQJBAMlobEO74o1mdY74vJt4
+KOUuwoBKt2dF3oP8u6Atnrp4IV9MwvSTh7OO0LncbBKSMZRDaL7b8tt5FjI8STTN
++AECIQD+3qiJl8/becyocHTlq82hO+IBxMQW/RXyEwkxYf9ZNwIhAPCIkUdapg+T
+uZJ9ho95XFyOmNzyrTqtdJRBWDqWfc5BAiAlBNQ3//vp5fwK7yKbhWO9qoP+O8U7
+jZEVcxxfttsu6wIhANMmX7outlY4TRBuxwAN/ml1+HUFR9KZ0BwRXN1ZnKjBAiAz
+fzOZ5j1T7BjEseAZPm/Xj73fu9vfFGDYWaKcPUY0Cw==
+-----END RSA PRIVATE KEY-----
diff --git a/test/512.txt b/test/512.txt
new file mode 100644
index 0000000..51cb7af
--- /dev/null
+++ b/test/512.txt
@@ -0,0 +1 @@
+005536b643ea651f2fd3c70aa83659cbd0c1f47ba803373029c6b0826db486136b4f769c6bf531ff247d6d76ea4ad050dc0e82ccedf5fd1ce07abb5192204551 \ No newline at end of file
diff --git a/test/format_test_vectors.py b/test/format_test_vectors.py
new file mode 100644
index 0000000..dd8670d
--- /dev/null
+++ b/test/format_test_vectors.py
@@ -0,0 +1,302 @@
+#
+# format_test_vectors.py
+# ------------------------------------------
+# Formats test vectors for modexp_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.
+#
+
+#
+# imports
+#
+import subprocess
+
+#
+# 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
+
+#
+# https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm
+#
+def egcd(a, b):
+ if a == 0:
+ return (b, 0, 1)
+ else:
+ (g, y, x) = egcd(b % a, a)
+ return (g, x - (b // a) * y, y)
+
+def modinv(a, m):
+ (g, x, y) = egcd(a, m)
+ if g != 1:
+ raise Exception("Can't invert a = " + a)
+ else:
+ return x % m
+
+#
+# format one test vector
+#
+def format_c_header(f, key, n, m, d, s):
+
+ # write all numbers in vector
+ format_c_array(f, n, "#define N_" + str(key) + " \\\n")
+ format_c_array(f, m, "#define M_" + str(key) + " \\\n")
+ format_c_array(f, d, "#define D_" + str(key) + " \\\n")
+ format_c_array(f, s, "#define S_" + str(key) + " \\\n")
+
+#
+# calculate Montgomery factor
+#
+def calc_montgomery_factor(k, n):
+
+ f = 1
+
+ for i in range(2 * k):
+ f1 = 2 * f
+ f2 = f1 - n
+ if f2 < 0:
+ f = f1
+ else:
+ f = f2
+
+ return f
+
+
+#
+# calculate Montgomery modulus-dependent helper coefficient
+#
+def calc_montgomery_n_coeff(k, n):
+
+ r = 1
+ b = 1 << k
+
+ nn = b - n
+
+ for i in range(k-1):
+ t = (r * nn) % b
+ mask = 1 << (i + 1)
+ if (t & mask) == mask:
+ r = r + (1 << (i + 1))
+
+ return r
+
+
+
+#
+# format one test vector
+#
+def format_verilog_include(f, key, n, m):
+
+ # calculate factor to bring message into Montgomery domain
+ factor = calc_montgomery_factor(int(key), n)
+
+ # calculate helper coefficient for Montgomery multiplication
+ n_coeff = calc_montgomery_n_coeff(int(key), n)
+
+ # 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_" + str(key) + " =\n")
+ format_verilog_concatenation(f, n, "localparam [" + str(int(key)-1) + ":0] N_" + str(key) + " =\n")
+ format_verilog_concatenation(f, n_coeff, "localparam [" + str(int(key)-1) + ":0] N_COEFF_" + str(key) + " =\n")
+ format_verilog_concatenation(f, factor, "localparam [" + str(int(key)-1) + ":0] FACTOR_" + str(key) + " =\n")
+ format_verilog_concatenation(f, coeff, "localparam [" + str(int(key)-1) + ":0] COEFF_" + str(key) + " =\n")
+ format_verilog_concatenation(f, m_factor, "localparam [" + str(int(key)-1) + ":0] M_FACTOR_" + str(key) + " =\n")
+
+
+#
+# nicely format multi-word integer into C array initializer
+#
+def format_c_array(f, n, s):
+
+ # print '#define 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 = ""
+
+ # 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")
+
+if __name__ == "__main__":
+
+ # list of key lengths to process
+ keys = ["384", "512"]
+
+ # open output files
+ file_h = open('modexp_fpga_model_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 key in keys:
+
+ # prepare all the numbers
+ modulus = int(read_modulus(key), 16) # read number n from .key file
+ message = int(read_message(key), 16) # read number m from .txt file
+ secret = int(read_secret(key), 16) # read number d from .key file
+ signature = pow(message, secret, modulus) # calculate signature
+
+ # print all the numbers
+ print("key = " + key)
+ print(" modulus = " + hex(modulus))
+ print(" message = " + hex(message))
+ print(" secret = " + hex(secret))
+ print(" signature = " + hex(signature))
+
+ # format numbers and write to file
+ format_c_header(file_h, key, modulus, message, secret, signature)
+ format_verilog_include(file_v, key, modulus, message)
+
+
+ # done
+ file_h.close()
+
+ # everything went just fine
+ print("Test vectors formatted.")
+
+#
+# End of file
+#
diff --git a/test/modexp_fpga_model_vectors.h b/test/modexp_fpga_model_vectors.h
new file mode 100644
index 0000000..d889ada
--- /dev/null
+++ b/test/modexp_fpga_model_vectors.h
@@ -0,0 +1,46 @@
+/* Generated automatically, do not edit. */
+
+#define N_384 \
+ {0xb06b4de3, 0x1006214f, 0xaa3c8cae, 0x6c568477, \
+ 0xb8c8d8b2, 0x08684070, 0x3b9ba674, 0x739e0eec, \
+ 0x950a0d8a, 0xb6b7443d, 0xfebe690c, 0xe2810099}
+
+#define M_384 \
+ {0x00d1bda6, 0x6c3babf4, 0xe418ec5b, 0x18435414, \
+ 0x5ed5b8aa, 0x0b62f138, 0x84551519, 0x1e94e625, \
+ 0x0901814a, 0x138eda05, 0x56b54f83, 0x1cd7605d}
+
+#define D_384 \
+ {0xad24a30c, 0x766d8dc3, 0xe2100b02, 0x24d1c4b0, \
+ 0xbb6a6342, 0x577df9be, 0x89bb1ec3, 0xdc3259f0, \
+ 0x1a343f93, 0x57a12599, 0xa328ae2f, 0xf85ef401}
+
+#define S_384 \
+ {0x65752d0f, 0x9a017293, 0x36bfa115, 0x4a7a81fc, \
+ 0xa76b945b, 0x49a3f645, 0x76801499, 0xb98e6a16, \
+ 0xd2467b6a, 0x75b7d614, 0x0fff0fde, 0xb31d1819}
+
+#define N_512 \
+ {0xef78b4ed, 0xaee1cc78, 0x659b9935, 0x39d5f5e1, \
+ 0xa47c2b29, 0x5a38e8c4, 0x85e2b846, 0xa354614f, \
+ 0xde1f94ee, 0x7462ba8f, 0x991ffec3, 0x6172bc7a, \
+ 0x11784156, 0x572b6e41, 0xa23fa8d0, 0x257ae8f7}
+
+#define M_512 \
+ {0x005536b6, 0x43ea651f, 0x2fd3c70a, 0xa83659cb, \
+ 0xd0c1f47b, 0xa8033730, 0x29c6b082, 0x6db48613, \
+ 0x6b4f769c, 0x6bf531ff, 0x247d6d76, 0xea4ad050, \
+ 0xdc0e82cc, 0xedf5fd1c, 0xe07abb51, 0x92204551}
+
+#define D_512 \
+ {0xc9686c43, 0xbbe28d66, 0x758ef8bc, 0x9b7828e5, \
+ 0x2ec2804a, 0xb76745de, 0x83fcbba0, 0x2d9eba78, \
+ 0x215f4cc2, 0xf49387b3, 0x8ed0b9dc, 0x6c129231, \
+ 0x944368be, 0xdbf2db79, 0x16323c49, 0x34cdf801}
+
+#define S_512 \
+ {0xcc2fc6b6, 0xe4849987, 0x75773499, 0xcb0792b0, \
+ 0xe79f4600, 0xb2d739c5, 0x1a661ac6, 0xd3bf2db5, \
+ 0xfd1e029d, 0xfe887387, 0x4312635f, 0xb2b54b8d, \
+ 0x5d3b379e, 0x161eaa4f, 0xedfd932b, 0x780f0203}
+
diff --git a/test/modexp_fpga_model_vectors.v b/test/modexp_fpga_model_vectors.v
new file mode 100644
index 0000000..7a2b8e9
--- /dev/null
+++ b/test/modexp_fpga_model_vectors.v
@@ -0,0 +1,68 @@
+/* Generated automatically, do not edit. */
+
+localparam [383:0] M_384 =
+ {32'h00d1bda6, 32'h6c3babf4, 32'he418ec5b, 32'h18435414,
+ 32'h5ed5b8aa, 32'h0b62f138, 32'h84551519, 32'h1e94e625,
+ 32'h0901814a, 32'h138eda05, 32'h56b54f83, 32'h1cd7605d};
+
+localparam [383:0] N_384 =
+ {32'hb06b4de3, 32'h1006214f, 32'haa3c8cae, 32'h6c568477,
+ 32'hb8c8d8b2, 32'h08684070, 32'h3b9ba674, 32'h739e0eec,
+ 32'h950a0d8a, 32'hb6b7443d, 32'hfebe690c, 32'he2810099};
+
+localparam [383:0] N_COEFF_384 =
+ {32'hd4511719, 32'h4d546bb2, 32'hdf614d49, 32'h81e00324,
+ 32'h07b0ccd5, 32'h44ccffdc, 32'h1d37c210, 32'h1733fb82,
+ 32'h35cf01cb, 32'hf7bf10e9, 32'h4238c3df, 32'h2712ac57};
+
+localparam [383:0] FACTOR_384 =
+ {32'h7643f0e6, 32'h7057fffc, 32'h92e27890, 32'h66a30c4a,
+ 32'ha6e3ef37, 32'h97d72f8a, 32'h0d4a5392, 32'heb5ad4a1,
+ 32'h0aa57383, 32'h1e3a5028, 32'h0cbaa40e, 32'hb17a468b};
+
+localparam [383:0] COEFF_384 =
+ {32'h9250be5e, 32'hc1e19afe, 32'h99341b1b, 32'hda823ac7,
+ 32'hcc46fbd2, 32'he7da1ff3, 32'he36e49fd, 32'hd593b36c,
+ 32'h09ae9f5e, 32'h7f44805d, 32'hf77c6019, 32'h45563ab6};
+
+localparam [383:0] M_FACTOR_384 =
+ {32'h8166125d, 32'h30aece3d, 32'h30d77d7e, 32'h8b0791ba,
+ 32'h91e92683, 32'hc483bb6c, 32'h0ee1571d, 32'h6e28c2f5,
+ 32'hff5e6b61, 32'h65fb6164, 32'hd3651e5a, 32'h746b8ca0};
+
+localparam [511:0] M_512 =
+ {32'h005536b6, 32'h43ea651f, 32'h2fd3c70a, 32'ha83659cb,
+ 32'hd0c1f47b, 32'ha8033730, 32'h29c6b082, 32'h6db48613,
+ 32'h6b4f769c, 32'h6bf531ff, 32'h247d6d76, 32'hea4ad050,
+ 32'hdc0e82cc, 32'hedf5fd1c, 32'he07abb51, 32'h92204551};
+
+localparam [511:0] N_512 =
+ {32'hef78b4ed, 32'haee1cc78, 32'h659b9935, 32'h39d5f5e1,
+ 32'ha47c2b29, 32'h5a38e8c4, 32'h85e2b846, 32'ha354614f,
+ 32'hde1f94ee, 32'h7462ba8f, 32'h991ffec3, 32'h6172bc7a,
+ 32'h11784156, 32'h572b6e41, 32'ha23fa8d0, 32'h257ae8f7};
+
+localparam [511:0] N_COEFF_512 =
+ {32'he20d94ee, 32'hee497b57, 32'h13d83f00, 32'h7445c269,
+ 32'h7258393f, 32'h5a725633, 32'hf7349437, 32'h83681b0a,
+ 32'h5a4be08f, 32'h7f49b1eb, 32'h09221d14, 32'h5bb82985,
+ 32'h2599e229, 32'h1a15218d, 32'h62f8803c, 32'haa5fa739};
+
+localparam [511:0] FACTOR_512 =
+ {32'h220ef9ff, 32'h55989a78, 32'h722c5c1e, 32'ha466c81c,
+ 32'h6e6e0423, 32'h1242da6d, 32'h1482351e, 32'h5d14212e,
+ 32'h8fc70923, 32'hb24cad26, 32'h3f3538a9, 32'h4f0a6bdf,
+ 32'h14ca36b9, 32'h819a72fc, 32'h9b5ea0ea, 32'h8b4fe28b};
+
+localparam [511:0] COEFF_512 =
+ {32'hd375442c, 32'h4e2dcb0d, 32'hcfd2f151, 32'hc694c180,
+ 32'h3781078f, 32'hf2647315, 32'hc5f685c2, 32'ha75c0e9d,
+ 32'h545f18cb, 32'hec66027f, 32'h229cb16f, 32'hc8613357,
+ 32'h8f92a4c4, 32'h50de0908, 32'h6d8a8d78, 32'h7011f42d};
+
+localparam [511:0] M_FACTOR_512 =
+ {32'h099cc6e8, 32'h778f03a1, 32'h329890e9, 32'ha0a86dd2,
+ 32'hd7354e49, 32'h00a2d28a, 32'h2b0848c6, 32'hb08915dc,
+ 32'h663032a3, 32'h70734b62, 32'h2d30c132, 32'hefa75cc6,
+ 32'h9f18b32a, 32'h97d6ddf8, 32'h2f6df2d0, 32'he9098874};
+
diff --git a/test/regenerate_test_vectors.py b/test/regenerate_test_vectors.py
new file mode 100644
index 0000000..dcd1bc8
--- /dev/null
+++ b/test/regenerate_test_vectors.py
@@ -0,0 +1,85 @@
+#
+# regenerate_test_vectors.py
+# ------------------------------------------------------
+# Generates a new test vectors set for modexp_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 new pair of test vectors. Every test vector contains
+# public and private keypair and a demo message.
+#
+
+#
+# imports
+#
+import time
+import hashlib
+import subprocess
+
+if __name__ == "__main__":
+
+ # generate two new keys
+ subprocess.call(["openssl", "genrsa", "-out", "384.key", "384"])
+ subprocess.call(["openssl", "genrsa", "-out", "512.key", "512"])
+
+ # get current date and time
+ dt_date = time.strftime("%Y-%m-%d")
+ dt_time = time.strftime("%H:%M:%S")
+
+ # format demo message
+ msg = dt_date + " " + dt_time;
+ print("msg = '" + msg + "'")
+
+ # get two hashes of different lengths
+ m384 = hashlib.sha384(msg.encode("utf-8")).hexdigest()
+ m512 = hashlib.sha512(msg.encode("utf-8")).hexdigest()
+
+ # zero out the leftmost byte of each hash to make sure, that its
+ # numerical value is smaller than the corresponding modulus
+ m384 = "00" + m384[2:]
+ m512 = "00" + m512[2:]
+
+ # save 384-bit message
+ with open("384.txt", "w") as file_txt:
+ file_txt.write(m384)
+
+ # save 512-bit message
+ with open("512.txt", "w") as file_txt:
+ file_txt.write(m512)
+
+ # everything went just fine
+ print("New random test vectors generated.")
+
+#
+# End of file
+#