From a085acbadf829ac5b426323ca98058d6aa4048ba Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 2 Mar 2020 07:09:08 +0000 Subject: [PATCH] Support the new "ssh-ed448" key type. This is standardised by RFC 8709 at SHOULD level, and for us it's not too difficult (because we use general-purpose elliptic-curve code). So let's be up to date for a change, and add it. This implementation uses all the formats defined in the RFC. But we also have to choose a wire format for the public+private key blob sent to an agent, and since the OpenSSH agent protocol is the de facto standard but not (yet?) handled by the IETF, OpenSSH themselves get to say what the format for a key should or shouldn't be. So if they don't support a particular key method, what do you do? I checked with them, and they agreed that there's an obviously right format for Ed448 keys, which is to do them exactly like Ed25519 except that you have a 57-byte string everywhere Ed25519 had a 32-byte string. So I've done that. --- Recipe | 8 ++--- cmdgen.c | 4 ++- contrib/kh2reg.py | 14 +++++---- putty.h | 1 + settings.c | 1 + ssh.h | 2 ++ ssh2transport.h | 1 + sshecc.c | 74 +++++++++++++++++++++++++++++++++++++++++++++- sshpubk.c | 2 ++ test/cryptsuite.py | 60 +++++++++++++++++++++++++++++++++++++ test/eccref.py | 3 ++ testcrypt.c | 1 + 12 files changed, 159 insertions(+), 12 deletions(-) diff --git a/Recipe b/Recipe index 4e3e8e30..1fd302bb 100644 --- a/Recipe +++ b/Recipe @@ -348,13 +348,13 @@ pageant : [G] winpgnt pageant sshrsa sshpubk sshdes ARITH sshmd5 version + tree234 MISC sshaes sshsha winsecur winpgntc aqsync sshdss sshsh256 + sshsh512 winutils sshecc winmisc winmiscs winhelp conf pageant.res + sshauxcrypt sshhmac wincapi winnps winnpc winhsock errsock winnet - + winhandl callback be_misc winselgui winhandl LIBS + + winhandl callback be_misc winselgui winhandl sshsha3 LIBS puttygen : [G] winpgen KEYGEN SSHPRIME sshdes ARITH sshmd5 version + sshrand winnoise sshsha winstore MISC winctrls sshrsa sshdss winmisc + sshpubk sshaes sshsh256 sshsh512 IMPORT winutils puttygen.res + tree234 notiming winhelp winnojmp CONF LIBS wintime sshecc sshprng - + sshauxcrypt sshhmac winsecur winmiscs + + sshauxcrypt sshhmac winsecur winmiscs sshsha3 pterm : [X] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore + uxsignal CHARSET cmdline uxpterm version time xpmpterm xpmptcfg @@ -372,7 +372,7 @@ plink : [U] uxplink uxcons NONSSH UXSSH U_BE_ALL logging UXMISC uxsignal PUTTYGEN_UNIX = KEYGEN SSHPRIME sshdes ARITH sshmd5 version sshprng + sshrand uxnoise sshsha MISC sshrsa sshdss uxcons uxstore uxmisc + sshpubk sshaes sshsh256 sshsh512 IMPORT puttygen.res time tree234 - + uxgen notiming CONF sshecc uxnogtk sshauxcrypt sshhmac + + uxgen notiming CONF sshecc sshsha3 uxnogtk sshauxcrypt sshhmac + uxpoll uxutils puttygen : [U] cmdgen PUTTYGEN_UNIX cgtest : [UT] cgtest PUTTYGEN_UNIX @@ -386,7 +386,7 @@ pageant : [X] uxpgnt uxagentc aqsync pageant sshrsa sshpubk sshdes ARITH + sshmd5 version tree234 misc sshaes sshsha sshdss sshsh256 sshsh512 + sshecc CONF uxsignal nocproxy nogss be_none x11fwd ux_x11 uxcons + gtkask gtkmisc nullplug logging UXMISC uxagentsock utils memory - + sshauxcrypt sshhmac sshprng uxnoise uxcliloop + + sshauxcrypt sshhmac sshprng uxnoise uxcliloop sshsha3 ptermapp : [XT] GTKTERM uxmisc misc ldisc settings uxpty uxsel BE_NONE uxstore + uxsignal CHARSET uxpterm version time xpmpterm xpmptcfg diff --git a/cmdgen.c b/cmdgen.c index 11558598..53b427f4 100644 --- a/cmdgen.c +++ b/cmdgen.c @@ -116,7 +116,7 @@ void help(void) usage(false); printf(" -t specify key type when generating:\n" " eddsa, ecdsa, rsa, dsa, rsa1 use with -b\n" - " ed25519 special case of eddsa\n" + " ed25519, ed448 special cases of eddsa\n" " -b specify number of bits when generating key\n" " -C change or specify key comment\n" " -P change key passphrase\n" @@ -435,6 +435,8 @@ int main(int argc, char **argv) keytype = EDDSA, sshver = 2; else if (!strcmp(p, "ed25519")) keytype = EDDSA, bits = 255, sshver = 2; + else if (!strcmp(p, "ed448")) + keytype = EDDSA, bits = 448, sshver = 2; else { fprintf(stderr, "puttygen: unknown key type `%s'\n", p); diff --git a/contrib/kh2reg.py b/contrib/kh2reg.py index 272124d5..3f32f6cd 100755 --- a/contrib/kh2reg.py +++ b/contrib/kh2reg.py @@ -302,7 +302,7 @@ def handle_line(line, output_formatter, try_hosts): keyparams = [curvename, x, y] - elif sshkeytype == "ssh-ed25519": + elif sshkeytype in { "ssh-ed25519", "ssh-ed448" }: keytype = sshkeytype if len(subfields) != 2: @@ -314,12 +314,14 @@ def handle_line(line, output_formatter, try_hosts): x_parity = y >> 255 y &= ~(1 << 255) - # Standard Ed25519 parameters. - p = 2**255 - 19 - d = 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3 + # Curve parameters. + p, d, a = { + "ssh-ed25519": (2**255 - 19, 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3, -1), + "ssh-ed448": (2**448-2**224-1, -39081, +1), + }[sshkeytype] - # Recover x^2 = (y^2 - 1) / (d y^2 + 1). - xx = (y*y - 1) * invert(d*y*y + 1, p) % p + # Recover x^2 = (y^2 - 1) / (d y^2 - a). + xx = (y*y - 1) * invert(d*y*y - a, p) % p # Take the square root. x = SqrtModP.root(xx, p) diff --git a/putty.h b/putty.h index 5a288988..4a67ed14 100644 --- a/putty.h +++ b/putty.h @@ -311,6 +311,7 @@ enum { HK_DSA, HK_ECDSA, HK_ED25519, + HK_ED448, HK_MAX }; diff --git a/settings.c b/settings.c index 97bbc962..411c2faa 100644 --- a/settings.c +++ b/settings.c @@ -39,6 +39,7 @@ static const struct keyvalwhere kexnames[] = { static const struct keyvalwhere hknames[] = { { "ed25519", HK_ED25519, -1, +1 }, + { "ed448", HK_ED448, -1, +1 }, { "ecdsa", HK_ECDSA, -1, -1 }, { "dsa", HK_DSA, -1, -1 }, { "rsa", HK_RSA, -1, -1 }, diff --git a/ssh.h b/ssh.h index c0af005e..5eba5fd8 100644 --- a/ssh.h +++ b/ssh.h @@ -506,6 +506,7 @@ const ssh_keyalg *ec_alg_by_oid(int len, const void *oid, const struct ec_curve **curve); const unsigned char *ec_alg_oid(const ssh_keyalg *alg, int *oidlen); extern const int ec_nist_curve_lengths[], n_ec_nist_curve_lengths; +extern const int ec_ed_curve_lengths[], n_ec_ed_curve_lengths; bool ec_nist_alg_and_curve_by_bits(int bits, const struct ec_curve **curve, const ssh_keyalg **alg); @@ -995,6 +996,7 @@ extern const ssh_kexes ssh_ecdh_kex; extern const ssh_keyalg ssh_dss; extern const ssh_keyalg ssh_rsa; extern const ssh_keyalg ssh_ecdsa_ed25519; +extern const ssh_keyalg ssh_ecdsa_ed448; extern const ssh_keyalg ssh_ecdsa_nistp256; extern const ssh_keyalg ssh_ecdsa_nistp384; extern const ssh_keyalg ssh_ecdsa_nistp521; diff --git a/ssh2transport.h b/ssh2transport.h index 8dc23304..10d660ab 100644 --- a/ssh2transport.h +++ b/ssh2transport.h @@ -47,6 +47,7 @@ struct kexinit_algorithm { #define HOSTKEY_ALGORITHMS(X) \ X(HK_ED25519, ssh_ecdsa_ed25519) \ + X(HK_ED448, ssh_ecdsa_ed448) \ X(HK_ECDSA, ssh_ecdsa_nistp256) \ X(HK_ECDSA, ssh_ecdsa_nistp384) \ X(HK_ECDSA, ssh_ecdsa_nistp521) \ diff --git a/sshecc.c b/sshecc.c index f1b92988..8114aba6 100644 --- a/sshecc.c +++ b/sshecc.c @@ -7,7 +7,7 @@ * * Montgomery form curves are supported for DH. (Curve25519) * - * Edwards form curves are supported for DSA. (Ed25519) + * Edwards form curves are supported for DSA. (Ed25519, Ed448) */ /* @@ -284,6 +284,43 @@ static struct ec_curve *ec_ed25519(void) return &curve; } +static struct ec_curve *ec_ed448(void) +{ + static struct ec_curve curve = { 0 }; + static bool initialised = false; + + if (!initialised) + { + mp_int *p = MP_LITERAL(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff); + mp_int *d = MP_LITERAL(0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffff6756); /* = p - 39081 */ + mp_int *a = MP_LITERAL(0x1); + mp_int *G_x = MP_LITERAL(0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e); + mp_int *G_y = MP_LITERAL(0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14); + mp_int *G_order = MP_LITERAL(0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3); + mp_int *nonsquare_mod_p = mp_from_integer(7); + initialise_ecurve(&curve, p, d, a, nonsquare_mod_p, + G_x, G_y, G_order, 2); + mp_free(p); + mp_free(d); + mp_free(a); + mp_free(G_x); + mp_free(G_y); + mp_free(G_order); + mp_free(nonsquare_mod_p); + + /* This curve doesn't need a name, because it's never used in + * any format that embeds the curve name */ + curve.name = NULL; + + curve.textname = "Ed448"; + + /* Now initialised, no need to do it again */ + initialised = true; + } + + return &curve; +} + /* ---------------------------------------------------------------------- * Public point from private */ @@ -815,6 +852,10 @@ static ssh_key *eddsa_new_priv_openssh( * correct as well, otherwise the key we think we've imported * won't behave identically to the way OpenSSH would have treated * it. + * + * We assume that Ed448 will work the same way, as and when + * OpenSSH implements it, which at the time of writing this they + * had not. */ BinarySource subsrc[1]; BinarySource_BARE_INIT_PL(subsrc, privkey_extended_pl); @@ -1233,6 +1274,33 @@ const ssh_keyalg ssh_ecdsa_ed25519 = { 0, /* no supported flags */ }; +static const struct ecsign_extra sign_extra_ed448 = { + ec_ed448, &ssh_shake256_114bytes, + NULL, 0, PTRLEN_DECL_LITERAL("SigEd448\0\0"), +}; +const ssh_keyalg ssh_ecdsa_ed448 = { + eddsa_new_pub, + eddsa_new_priv, + eddsa_new_priv_openssh, + + eddsa_freekey, + ec_signkey_invalid, + eddsa_sign, + eddsa_verify, + eddsa_public_blob, + eddsa_private_blob, + eddsa_openssh_blob, + eddsa_cache_str, + eddsa_components, + + ec_shared_pubkey_bits, + + "ssh-ed448", + "ssh-ed448", + &sign_extra_ed448, + 0, /* no supported flags */ +}; + /* OID: 1.2.840.10045.3.1.7 (ansiX9p256r1) */ static const unsigned char nistp256_oid[] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 @@ -1629,6 +1697,9 @@ const unsigned char *ec_alg_oid(const ssh_keyalg *alg, const int ec_nist_curve_lengths[] = { 256, 384, 521 }; const int n_ec_nist_curve_lengths = lenof(ec_nist_curve_lengths); +const int ec_ed_curve_lengths[] = { 255, 448 }; +const int n_ec_ed_curve_lengths = lenof(ec_ed_curve_lengths); + bool ec_nist_alg_and_curve_by_bits( int bits, const struct ec_curve **curve, const ssh_keyalg **alg) { @@ -1647,6 +1718,7 @@ bool ec_ed_alg_and_curve_by_bits( { switch (bits) { case 255: case 256: *alg = &ssh_ecdsa_ed25519; break; + case 448: *alg = &ssh_ecdsa_ed448; break; default: return false; } *curve = ((struct ecsign_extra *)(*alg)->extra)->curve(); diff --git a/sshpubk.c b/sshpubk.c index cbf42c93..4675eec1 100644 --- a/sshpubk.c +++ b/sshpubk.c @@ -648,6 +648,8 @@ const ssh_keyalg *find_pubkey_alg_len(ptrlen name) return &ssh_ecdsa_nistp521; else if (ptrlen_eq_string(name, "ssh-ed25519")) return &ssh_ecdsa_ed25519; + else if (ptrlen_eq_string(name, "ssh-ed448")) + return &ssh_ecdsa_ed448; else return NULL; } diff --git a/test/cryptsuite.py b/test/cryptsuite.py index 5a075f89..c5ae042e 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -1765,6 +1765,7 @@ culpa qui officia deserunt mollit anim id est laborum. test_keys = [ ('ed25519', 'AAAAC3NzaC1lZDI1NTE5AAAAIM7jupzef6CD0ps2JYxJp9IlwY49oorOseV5z5JFDFKn', 'AAAAIAf4/WRtypofgdNF2vbZOUFE1h4hvjw4tkGJZyOzI7c3', 255, b'0xf4d6e7f6f4479c23f0764ef43cea1711dbfe02aa2b5a32ff925c7c1fbf0f0db,0x27520c4592cf79e5b1ce8aa23d8ec125d2a7498c25369bd283a07fde9cbae3ce', [(0, 'AAAAC3NzaC1lZDI1NTE5AAAAQN73EqfyA4WneqDhgZ98TlRj9V5Wg8zCrMxTLJN1UtyfAnPUJDtfG/U0vOsP8PrnQxd41DDDnxrAXuqJz8rOagc=')]), + ('ed448', 'AAAACXNzaC1lZDQ0OAAAADnRI0CQDym5IqUidLNDcSdHe54bYEwqjpjBlab8uKGoe6FRqqejha7+5U/VAHy7BmE23+ju26O9XgA=', 'AAAAObP9klqyiJSJsdFJf+xwZQdkbZGUqXE07K6e5plfRTGjYYkyWJFUNFH4jzIn9xH1TX9z9EGycPaXAA==', 448, b'0x4bf4a2b6586c60d8cdb52c2b45b897f6d2224bc37987489c0d70febb449e8c82964ed5785827be808e44d31dd31e6ff7c99f43e49f419928,0x5ebda3dbeee8df366106bb7c00d54fe5feae85a3a7aa51a17ba8a1b8fca695c1988e2a4c601b9e7b47277143b37422a522b9290f904023d1', [(0, 'AAAACXNzaC1lZDQ0OAAAAHLkSVioGMvLesZp3Tn+Z/sSK0Hl7RHsHP4q9flLzTpZG5h6JDH3VmZBEjTJ6iOLaa0v4FoNt0ng4wAB53WrlQC4h3iAusoGXnPMAKJLmqzplKOCi8HKXk8Xl8fsXbaoyhatv1OZpwJcffmh1x+x+LSgNQA=')]), ('p256', 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHkYQ0sQoq5LbJI1VMWhw3bV43TSYi3WVpqIgKcBKK91TcFFlAMZgceOHQ0xAFYcSczIttLvFu+xkcLXrRd4N7Q=', 'AAAAIQCV/1VqiCsHZm/n+bq7lHEHlyy7KFgZBEbzqYaWtbx48Q==', 256, b'nistp256,0x7918434b10a2ae4b6c923554c5a1c376d5e374d2622dd6569a8880a70128af75,0x4dc14594031981c78e1d0d3100561c49ccc8b6d2ef16efb191c2d7ad177837b4', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABIAAAAIAryzHDGi/TcCnbdxZkIYR5EGR6SNYXr/HlQRF8le+/IAAAAIERfzn6eHuBbqWIop2qL8S7DWRB3lenN1iyL10xYQPKw')]), ('p384', 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMYK8PUtfAlJwKaBTIGEuCzH0vqOMa4UbcjrBbTbkGVSUnfo+nuC80NCdj9JJMs1jvfF8GzKLc5z8H3nZyM741/BUFjV7rEHsQFDek4KyWvKkEgKiTlZid19VukNo1q2Hg==', 'AAAAMGsfTmdB4zHdbiQ2euTSdzM6UKEOnrVjMAWwHEYvmG5qUOcBnn62fJDRJy67L+QGdg==', 384, b'nistp384,0xc60af0f52d7c0949c0a6814c8184b82cc7d2fa8e31ae146dc8eb05b4db9065525277e8fa7b82f34342763f4924cb358e,0xf7c5f06cca2dce73f07de767233be35fc15058d5eeb107b101437a4e0ac96bca90480a89395989dd7d56e90da35ab61e', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAABpAAAAMDmHrtXCADzLvkkWG/duBAHlf6B1mVvdt6F0uzXfsf8Yub8WXNUNVnYq6ovrWPzLggAAADEA9izzwoUuFcXYRJeKcRLZEGMmSDDPzUZb7oZR0UgD1jsMQXs8UfpO31Qur/FDSCRK')]), ('p521', 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFrGthlKM152vu2Ghk+R7iO9/M6e+hTehNZ6+FBwof4HPkPB2/HHXj5+w5ynWyUrWiX5TI2riuJEIrJErcRH5LglADnJDX2w4yrKZ+wDHSz9lwh9p2F+B5R952es6gX3RJRkGA+qhKpKup8gKx78RMbleX8wgRtIu+4YMUnKb1edREiRg==', 'AAAAQgFh7VNJFUljWhhyAEiL0z+UPs/QggcMTd3Vv2aKDeBdCRl5di8r+BMm39L7bRzxRMEtW5NSKlDtE8MFEGdIE9khsw==', 521, b'nistp521,0x16b1ad86528cd79dafbb61a193e47b88ef7f33a7be8537a1359ebe141c287f81cf90f076fc71d78f9fb0e729d6c94ad6897e53236ae2b89108ac912b7111f92e094,0xe72435f6c38cab299fb00c74b3f65c21f69d85f81e51f79d9eb3a817dd125190603eaa12a92aea7c80ac7bf1131b95e5fcc2046d22efb860c52729bd5e75112246', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAACMAAAAQgCLgvftvwM3CUaigrW0yzmCHoYjC6GLtO+6S91itqpgMEtWPNlaTZH6QQqkgscijWdXx98dDkQao/gcAKVmOZKPXgAAAEIB1PIrsDF1y6poJ/czqujB7NSUWt31v+c2t6UA8m2gTA1ARuVJ9XBGLMdceOTB00Hi9psC2RYFLpaWREOGCeDa6ow=')]), @@ -2458,6 +2459,65 @@ class standard_test_vectors(MyTestBase): signature = unhex(words[3])[:64] vector(privkey, pubkey, message, signature) + def testEd448(self): + def vector(privkey, pubkey, message, signature): + x, y = ecc_edwards_get_affine(eddsa_public( + mp_from_bytes_le(privkey), 'ed448')) + self.assertEqual(int(y) | ((int(x) & 1) << 455), + int(mp_from_bytes_le(pubkey))) + pubblob = ssh_string(b"ssh-ed448") + ssh_string(pubkey) + privblob = ssh_string(privkey) + sigblob = ssh_string(b"ssh-ed448") + ssh_string(signature) + pubkey = ssh_key_new_pub('ed448', pubblob) + self.assertTrue(ssh_key_verify(pubkey, sigblob, message)) + privkey = ssh_key_new_priv('ed448', pubblob, privblob) + # Deterministic signature check as in Ed25519 + self.assertEqualBin(ssh_key_sign(privkey, message, 0), sigblob) + + # Source: RFC 8032 section 7.4 + + privkey = unhex('6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b') + pubkey = unhex('5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180') + message = b'' + signature = unhex('533a37f6bbe457251f023c0d88f976ae2dfb504a843e34d2074fd823d41a591f2b233f034f628281f2fd7a22ddd47d7828c59bd0a21bfd3980ff0d2028d4b18a9df63e006c5d1c2d345b925d8dc00b4104852db99ac5c7cdda8530a113a0f4dbb61149f05a7363268c71d95808ff2e652600') + vector(privkey, pubkey, message, signature) + + privkey = unhex('c4eab05d357007c632f3dbb48489924d552b08fe0c353a0d4a1f00acda2c463afbea67c5e8d2877c5e3bc397a659949ef8021e954e0a12274e') + pubkey = unhex('43ba28f430cdff456ae531545f7ecd0ac834a55d9358c0372bfa0c6c6798c0866aea01eb00742802b8438ea4cb82169c235160627b4c3a9480') + message = unhex('03') + signature = unhex('26b8f91727bd62897af15e41eb43c377efb9c610d48f2335cb0bd0087810f4352541b143c4b981b7e18f62de8ccdf633fc1bf037ab7cd779805e0dbcc0aae1cbcee1afb2e027df36bc04dcecbf154336c19f0af7e0a6472905e799f1953d2a0ff3348ab21aa4adafd1d234441cf807c03a00') + vector(privkey, pubkey, message, signature) + + privkey = unhex('cd23d24f714274e744343237b93290f511f6425f98e64459ff203e8985083ffdf60500553abc0e05cd02184bdb89c4ccd67e187951267eb328') + pubkey = unhex('dcea9e78f35a1bf3499a831b10b86c90aac01cd84b67a0109b55a36e9328b1e365fce161d71ce7131a543ea4cb5f7e9f1d8b00696447001400') + message = unhex('0c3e544074ec63b0265e0c') + signature = unhex('1f0a8888ce25e8d458a21130879b840a9089d999aaba039eaf3e3afa090a09d389dba82c4ff2ae8ac5cdfb7c55e94d5d961a29fe0109941e00b8dbdeea6d3b051068df7254c0cdc129cbe62db2dc957dbb47b51fd3f213fb8698f064774250a5028961c9bf8ffd973fe5d5c206492b140e00') + vector(privkey, pubkey, message, signature) + + privkey = unhex('258cdd4ada32ed9c9ff54e63756ae582fb8fab2ac721f2c8e676a72768513d939f63dddb55609133f29adf86ec9929dccb52c1c5fd2ff7e21b') + pubkey = unhex('3ba16da0c6f2cc1f30187740756f5e798d6bc5fc015d7c63cc9510ee3fd44adc24d8e968b6e46e6f94d19b945361726bd75e149ef09817f580') + message = unhex('64a65f3cdedcdd66811e2915') + signature = unhex('7eeeab7c4e50fb799b418ee5e3197ff6bf15d43a14c34389b59dd1a7b1b85b4ae90438aca634bea45e3a2695f1270f07fdcdf7c62b8efeaf00b45c2c96ba457eb1a8bf075a3db28e5c24f6b923ed4ad747c3c9e03c7079efb87cb110d3a99861e72003cbae6d6b8b827e4e6c143064ff3c00') + vector(privkey, pubkey, message, signature) + + privkey = unhex('d65df341ad13e008567688baedda8e9dcdc17dc024974ea5b4227b6530e339bff21f99e68ca6968f3cca6dfe0fb9f4fab4fa135d5542ea3f01') + pubkey = unhex('df9705f58edbab802c7f8363cfe5560ab1c6132c20a9f1dd163483a26f8ac53a39d6808bf4a1dfbd261b099bb03b3fb50906cb28bd8a081f00') + message = unhex('bd0f6a3747cd561bdddf4640a332461a4a30a12a434cd0bf40d766d9c6d458e5512204a30c17d1f50b5079631f64eb3112182da3005835461113718d1a5ef944') + signature = unhex('554bc2480860b49eab8532d2a533b7d578ef473eeb58c98bb2d0e1ce488a98b18dfde9b9b90775e67f47d4a1c3482058efc9f40d2ca033a0801b63d45b3b722ef552bad3b4ccb667da350192b61c508cf7b6b5adadc2c8d9a446ef003fb05cba5f30e88e36ec2703b349ca229c2670833900') + vector(privkey, pubkey, message, signature) + + privkey = unhex('2ec5fe3c17045abdb136a5e6a913e32ab75ae68b53d2fc149b77e504132d37569b7e766ba74a19bd6162343a21c8590aa9cebca9014c636df5') + pubkey = unhex('79756f014dcfe2079f5dd9e718be4171e2ef2486a08f25186f6bff43a9936b9bfe12402b08ae65798a3d81e22e9ec80e7690862ef3d4ed3a00') + message = unhex('15777532b0bdd0d1389f636c5f6b9ba734c90af572877e2d272dd078aa1e567cfa80e12928bb542330e8409f3174504107ecd5efac61ae7504dabe2a602ede89e5cca6257a7c77e27a702b3ae39fc769fc54f2395ae6a1178cab4738e543072fc1c177fe71e92e25bf03e4ecb72f47b64d0465aaea4c7fad372536c8ba516a6039c3c2a39f0e4d832be432dfa9a706a6e5c7e19f397964ca4258002f7c0541b590316dbc5622b6b2a6fe7a4abffd96105eca76ea7b98816af0748c10df048ce012d901015a51f189f3888145c03650aa23ce894c3bd889e030d565071c59f409a9981b51878fd6fc110624dcbcde0bf7a69ccce38fabdf86f3bef6044819de11') + signature = unhex('c650ddbb0601c19ca11439e1640dd931f43c518ea5bea70d3dcde5f4191fe53f00cf966546b72bcc7d58be2b9badef28743954e3a44a23f880e8d4f1cfce2d7a61452d26da05896f0a50da66a239a8a188b6d825b3305ad77b73fbac0836ecc60987fd08527c1a8e80d5823e65cafe2a3d00') + vector(privkey, pubkey, message, signature) + + privkey = unhex('872d093780f5d3730df7c212664b37b8a0f24f56810daa8382cd4fa3f77634ec44dc54f1c2ed9bea86fafb7632d8be199ea165f5ad55dd9ce8') + pubkey = unhex('a81b2e8a70a5ac94ffdbcc9badfc3feb0801f258578bb114ad44ece1ec0e799da08effb81c5d685c0c56f64eecaef8cdf11cc38737838cf400') + message = unhex('6ddf802e1aae4986935f7f981ba3f0351d6273c0a0c22c9c0e8339168e675412a3debfaf435ed651558007db4384b650fcc07e3b586a27a4f7a00ac8a6fec2cd86ae4bf1570c41e6a40c931db27b2faa15a8cedd52cff7362c4e6e23daec0fbc3a79b6806e316efcc7b68119bf46bc76a26067a53f296dafdbdc11c77f7777e972660cf4b6a9b369a6665f02e0cc9b6edfad136b4fabe723d2813db3136cfde9b6d044322fee2947952e031b73ab5c603349b307bdc27bc6cb8b8bbd7bd323219b8033a581b59eadebb09b3c4f3d2277d4f0343624acc817804728b25ab797172b4c5c21a22f9c7839d64300232eb66e53f31c723fa37fe387c7d3e50bdf9813a30e5bb12cf4cd930c40cfb4e1fc622592a49588794494d56d24ea4b40c89fc0596cc9ebb961c8cb10adde976a5d602b1c3f85b9b9a001ed3c6a4d3b1437f52096cd1956d042a597d561a596ecd3d1735a8d570ea0ec27225a2c4aaff26306d1526c1af3ca6d9cf5a2c98f47e1c46db9a33234cfd4d81f2c98538a09ebe76998d0d8fd25997c7d255c6d66ece6fa56f11144950f027795e653008f4bd7ca2dee85d8e90f3dc315130ce2a00375a318c7c3d97be2c8ce5b6db41a6254ff264fa6155baee3b0773c0f497c573f19bb4f4240281f0b1f4f7be857a4e59d416c06b4c50fa09e1810ddc6b1467baeac5a3668d11b6ecaa901440016f389f80acc4db977025e7f5924388c7e340a732e554440e76570f8dd71b7d640b3450d1fd5f0410a18f9a3494f707c717b79b4bf75c98400b096b21653b5d217cf3565c9597456f70703497a078763829bc01bb1cbc8fa04eadc9a6e3f6699587a9e75c94e5bab0036e0b2e711392cff0047d0d6b05bd2a588bc109718954259f1d86678a579a3120f19cfb2963f177aeb70f2d4844826262e51b80271272068ef5b3856fa8535aa2a88b2d41f2a0e2fda7624c2850272ac4a2f561f8f2f7a318bfd5caf9696149e4ac824ad3460538fdc25421beec2cc6818162d06bbed0c40a387192349db67a118bada6cd5ab0140ee273204f628aad1c135f770279a651e24d8c14d75a6059d76b96a6fd857def5e0b354b27ab937a5815d16b5fae407ff18222c6d1ed263be68c95f32d908bd895cd76207ae726487567f9a67dad79abec316f683b17f2d02bf07e0ac8b5bc6162cf94697b3c27cd1fea49b27f23ba2901871962506520c392da8b6ad0d99f7013fbc06c2c17a569500c8a7696481c1cd33e9b14e40b82e79a5f5db82571ba97bae3ad3e0479515bb0e2b0f3bfcd1fd33034efc6245eddd7ee2086ddae2600d8ca73e214e8c2b0bdb2b047c6a464a562ed77b73d2d841c4b34973551257713b753632efba348169abc90a68f42611a40126d7cb21b58695568186f7e569d2ff0f9e745d0487dd2eb997cafc5abf9dd102e62ff66cba87') + signature = unhex('e301345a41a39a4d72fff8df69c98075a0cc082b802fc9b2b6bc503f926b65bddf7f4c8f1cb49f6396afc8a70abe6d8aef0db478d4c6b2970076c6a0484fe76d76b3a97625d79f1ce240e7c576750d295528286f719b413de9ada3e8eb78ed573603ce30d8bb761785dc30dbc320869e1a00') + vector(privkey, pubkey, message, signature) + def testMontgomeryKex(self): # Unidirectional tests, consisting of an input random number # string and peer public value, giving the expected output diff --git a/test/eccref.py b/test/eccref.py index 9fdafc90..b1eb2b28 100644 --- a/test/eccref.py +++ b/test/eccref.py @@ -323,3 +323,6 @@ ed25519 = TwistedEdwardsCurve(2**255-19, 0x52036cee2b6ffe738cc740797779e89800700 ed25519.G = ed25519.point(0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a,0x6666666666666666666666666666666666666666666666666666666666666658) ed25519.G_order = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed +ed448 = TwistedEdwardsCurve(2**448-2**224-1, -39081, +1) +ed448.G = ed448.point(0x4f1970c66bed0ded221d15a622bf36da9e146570470f1767ea6de324a3d3a46412ae1af72ab66511433b80e18b00938e2626a82bc70cc05e,0x693f46716eb6bc248876203756c9c7624bea73736ca3984087789c1e05a0c2d73ad3ff1ce67c39c4fdbd132c4ed7c8ad9808795bf230fa14) +ed448.G_order = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3 diff --git a/testcrypt.c b/testcrypt.c index cbc1a027..3cde56af 100644 --- a/testcrypt.c +++ b/testcrypt.c @@ -263,6 +263,7 @@ static const ssh_keyalg *get_keyalg(BinarySource *in) {"dsa", &ssh_dss}, {"rsa", &ssh_rsa}, {"ed25519", &ssh_ecdsa_ed25519}, + {"ed448", &ssh_ecdsa_ed448}, {"p256", &ssh_ecdsa_nistp256}, {"p384", &ssh_ecdsa_nistp384}, {"p521", &ssh_ecdsa_nistp521},