diff --git a/ChangeLog b/ChangeLog index d4fcc1db..d4f8e66c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ * Version 1.0.12 + - Ed25519ph was implemented, adding a multi-part signature API +(`crypto_sign_init()`, `crypto_sign_update()`, `crypto_sign_final_*()`). - New constants and related accessors have been added for Scrypt and Argon2. - XChaCha20 has been implemented. Like XSalsa20, this construction diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj b/builds/msvc/vs2010/libsodium/libsodium.vcxproj index b42b0840..d161bc20 100644 --- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj @@ -218,6 +218,7 @@ + diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters index 7da75fa8..dfc0aba1 100644 --- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters @@ -440,6 +440,9 @@ crypto_shorthash\siphash24\ref + + crypto_sign\ed25519\ref10 + crypto_stream\aes128ctr\nacl diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj b/builds/msvc/vs2012/libsodium/libsodium.vcxproj index 3fecbf0f..3f75c276 100644 --- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj @@ -218,6 +218,7 @@ + diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters index 7da75fa8..dfc0aba1 100644 --- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters @@ -440,6 +440,9 @@ crypto_shorthash\siphash24\ref + + crypto_sign\ed25519\ref10 + crypto_stream\aes128ctr\nacl diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj b/builds/msvc/vs2013/libsodium/libsodium.vcxproj index 7eef8095..18a10d48 100644 --- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj @@ -218,6 +218,7 @@ + diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters index 7da75fa8..dfc0aba1 100644 --- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters @@ -440,6 +440,9 @@ crypto_shorthash\siphash24\ref + + crypto_sign\ed25519\ref10 + crypto_stream\aes128ctr\nacl diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj b/builds/msvc/vs2015/libsodium/libsodium.vcxproj index 25c4f16f..fe7bd093 100644 --- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj +++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj @@ -218,6 +218,7 @@ + diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters index 7da75fa8..dfc0aba1 100644 --- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters +++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters @@ -440,6 +440,9 @@ crypto_shorthash\siphash24\ref + + crypto_sign\ed25519\ref10 + crypto_stream\aes128ctr\nacl diff --git a/libsodium.vcxproj b/libsodium.vcxproj index 05d25462..1aa5d6b6 100644 --- a/libsodium.vcxproj +++ b/libsodium.vcxproj @@ -456,6 +456,7 @@ + diff --git a/libsodium.vcxproj.filters b/libsodium.vcxproj.filters index 9b608392..10e1df2a 100644 --- a/libsodium.vcxproj.filters +++ b/libsodium.vcxproj.filters @@ -434,6 +434,9 @@ Header Files + + Header Files + Header Files diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am index 04f33bad..30c18a24 100644 --- a/src/libsodium/Makefile.am +++ b/src/libsodium/Makefile.am @@ -73,6 +73,7 @@ libsodium_la_SOURCES = \ crypto_shorthash/siphash24/ref/shorthash_siphash_ref.h \ crypto_sign/crypto_sign.c \ crypto_sign/ed25519/sign_ed25519.c \ + crypto_sign/ed25519/ref10/ed25519_ref10.h \ crypto_sign/ed25519/ref10/keypair.c \ crypto_sign/ed25519/ref10/open.c \ crypto_sign/ed25519/ref10/sign.c \ diff --git a/src/libsodium/crypto_sign/crypto_sign.c b/src/libsodium/crypto_sign/crypto_sign.c index b5508fb8..b93fa0ef 100644 --- a/src/libsodium/crypto_sign/crypto_sign.c +++ b/src/libsodium/crypto_sign/crypto_sign.c @@ -1,6 +1,12 @@ #include "crypto_sign.h" +size_t +crypto_sign_statebytes(void) +{ + return sizeof(crypto_sign_state); +} + size_t crypto_sign_bytes(void) { @@ -74,3 +80,30 @@ crypto_sign_verify_detached(const unsigned char *sig, const unsigned char *m, { return crypto_sign_ed25519_verify_detached(sig, m, mlen, pk); } + +int +crypto_sign_init(crypto_sign_state *state) +{ + return crypto_sign_ed25519ph_init(state); +} + +int +crypto_sign_update(crypto_sign_state *state, const unsigned char *m, + unsigned long long mlen) +{ + return crypto_sign_ed25519ph_update(state, m, mlen); +} + +int +crypto_sign_final_create(crypto_sign_state *state, unsigned char *sig, + unsigned long long *siglen_p, const unsigned char *sk) +{ + return crypto_sign_ed25519ph_final_create(state, sig, siglen_p, sk); +} + +int +crypto_sign_final_verify(crypto_sign_state *state, unsigned char *sig, + const unsigned char *pk) +{ + return crypto_sign_ed25519ph_final_verify(state, sig, pk); +} diff --git a/src/libsodium/crypto_sign/ed25519/ref10/open.c b/src/libsodium/crypto_sign/ed25519/ref10/open.c index 5cf8cd64..95e55d2d 100644 --- a/src/libsodium/crypto_sign/ed25519/ref10/open.c +++ b/src/libsodium/crypto_sign/ed25519/ref10/open.c @@ -6,6 +6,7 @@ #include "crypto_hash_sha512.h" #include "crypto_sign_ed25519.h" #include "crypto_verify_32.h" +#include "ed25519_ref10.h" #include "private/curve25519_ref10.h" #include "utils.h" @@ -107,10 +108,11 @@ small_order(const unsigned char R[32]) #endif int -crypto_sign_ed25519_verify_detached(const unsigned char *sig, - const unsigned char *m, - unsigned long long mlen, - const unsigned char *pk) +_crypto_sign_ed25519_verify_detached(const unsigned char *sig, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *pk, + int prehashed) { crypto_hash_sha512_state hs; unsigned char h[64]; @@ -138,7 +140,7 @@ crypto_sign_ed25519_verify_detached(const unsigned char *sig, if (d == 0) { return -1; } - crypto_hash_sha512_init(&hs); + _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); crypto_hash_sha512_update(&hs, sig, 32); crypto_hash_sha512_update(&hs, pk, 32); crypto_hash_sha512_update(&hs, m, mlen); @@ -152,6 +154,15 @@ crypto_sign_ed25519_verify_detached(const unsigned char *sig, sodium_memcmp(sig, rcheck, 32); } +int +crypto_sign_ed25519_verify_detached(const unsigned char *sig, + const unsigned char *m, + unsigned long long mlen, + const unsigned char *pk) +{ + return _crypto_sign_ed25519_verify_detached(sig, m, mlen, pk, 0); +} + int crypto_sign_ed25519_open(unsigned char *m, unsigned long long *mlen_p, const unsigned char *sm, unsigned long long smlen, diff --git a/src/libsodium/crypto_sign/ed25519/ref10/sign.c b/src/libsodium/crypto_sign/ed25519/ref10/sign.c index 66f0c0ff..f9d47fdc 100644 --- a/src/libsodium/crypto_sign/ed25519/ref10/sign.c +++ b/src/libsodium/crypto_sign/ed25519/ref10/sign.c @@ -3,13 +3,30 @@ #include "crypto_hash_sha512.h" #include "crypto_sign_ed25519.h" +#include "ed25519_ref10.h" #include "private/curve25519_ref10.h" #include "utils.h" +void +_crypto_sign_ed25519_ref10_hinit(crypto_hash_sha512_state *hs, int prehashed) +{ + static const unsigned char DOM2PREFIX[32 + 2] = { + 'S', 'i', 'g', 'E', 'd', '2', '5', '5', '1', '9', ' ', + 'n', 'o', ' ', + 'E', 'd', '2', '5', '5', '1', '9', ' ', + 'c', 'o', 'l', 'l', 'i', 's', 'i', 'o', 'n', 's', 1, 0 + }; + + crypto_hash_sha512_init(hs); + if (prehashed) { + crypto_hash_sha512_update(hs, DOM2PREFIX, sizeof DOM2PREFIX); + } +} + int -crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p, - const unsigned char *m, unsigned long long mlen, - const unsigned char *sk) +_crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sk, int prehashed) { crypto_hash_sha512_state hs; unsigned char az[64]; @@ -22,7 +39,7 @@ crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p, az[31] &= 63; az[31] |= 64; - crypto_hash_sha512_init(&hs); + _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); crypto_hash_sha512_update(&hs, az + 32, 32); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, nonce); @@ -33,7 +50,7 @@ crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p, ge_scalarmult_base(&R, nonce); ge_p3_tobytes(sig, &R); - crypto_hash_sha512_init(&hs); + _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); crypto_hash_sha512_update(&hs, sig, 64); crypto_hash_sha512_update(&hs, m, mlen); crypto_hash_sha512_final(&hs, hram); @@ -49,6 +66,14 @@ crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p, return 0; } +int +crypto_sign_ed25519_detached(unsigned char *sig, unsigned long long *siglen_p, + const unsigned char *m, unsigned long long mlen, + const unsigned char *sk) +{ + return _crypto_sign_ed25519_detached(sig, siglen_p, m, mlen, sk, 0); +} + int crypto_sign_ed25519(unsigned char *sm, unsigned long long *smlen_p, const unsigned char *m, unsigned long long mlen, diff --git a/src/libsodium/crypto_sign/ed25519/sign_ed25519.c b/src/libsodium/crypto_sign/ed25519/sign_ed25519.c index 591db5ef..9ec477a1 100644 --- a/src/libsodium/crypto_sign/ed25519/sign_ed25519.c +++ b/src/libsodium/crypto_sign/ed25519/sign_ed25519.c @@ -1,7 +1,15 @@ #include +#include "crypto_hash_sha512.h" #include "crypto_sign_ed25519.h" +#include "ref10/ed25519_ref10.h" + +size_t +crypto_sign_ed25519ph_statebytes(void) +{ + return sizeof(crypto_sign_ed25519ph_state); +} size_t crypto_sign_ed25519_bytes(void) @@ -42,3 +50,42 @@ crypto_sign_ed25519_sk_to_pk(unsigned char *pk, const unsigned char *sk) crypto_sign_ed25519_PUBLICKEYBYTES); return 0; } + +int +crypto_sign_ed25519ph_init(crypto_sign_ed25519ph_state *state) +{ + crypto_hash_sha512_init(&state->hs); + return 0; +} + +int +crypto_sign_ed25519ph_update(crypto_sign_ed25519ph_state *state, + const unsigned char *m, unsigned long long mlen) +{ + return crypto_hash_sha512_update(&state->hs, m, mlen); +} + +int +crypto_sign_ed25519ph_final_create(crypto_sign_ed25519ph_state *state, + unsigned char *sig, + unsigned long long *siglen_p, + const unsigned char *sk) +{ + unsigned char ph[crypto_hash_sha512_BYTES]; + + crypto_hash_sha512_final(&state->hs, ph); + + return _crypto_sign_ed25519_detached(sig, siglen_p, ph, sizeof ph, sk, 1); +} + +int +crypto_sign_ed25519ph_final_verify(crypto_sign_ed25519ph_state *state, + unsigned char *sig, + const unsigned char *pk) +{ + unsigned char ph[crypto_hash_sha512_BYTES]; + + crypto_hash_sha512_final(&state->hs, ph); + + return _crypto_sign_ed25519_verify_detached(sig, ph, sizeof ph, pk, 1); +} diff --git a/src/libsodium/include/sodium/crypto_sign.h b/src/libsodium/include/sodium/crypto_sign.h index 5d7ea3a7..b0335bf2 100644 --- a/src/libsodium/include/sodium/crypto_sign.h +++ b/src/libsodium/include/sodium/crypto_sign.h @@ -20,6 +20,11 @@ extern "C" { #endif +typedef crypto_sign_ed25519ph_state crypto_sign_state; + +SODIUM_EXPORT +size_t crypto_sign_statebytes(void); + #define crypto_sign_BYTES crypto_sign_ed25519_BYTES SODIUM_EXPORT size_t crypto_sign_bytes(void); @@ -70,6 +75,23 @@ int crypto_sign_verify_detached(const unsigned char *sig, const unsigned char *pk) __attribute__ ((warn_unused_result)); +SODIUM_EXPORT +int crypto_sign_init(crypto_sign_state *state); + +SODIUM_EXPORT +int crypto_sign_update(crypto_sign_state *state, + const unsigned char *m, unsigned long long mlen); + +SODIUM_EXPORT +int crypto_sign_final_create(crypto_sign_state *state, unsigned char *sig, + unsigned long long *siglen_p, + const unsigned char *sk); + +SODIUM_EXPORT +int crypto_sign_final_verify(crypto_sign_state *state, unsigned char *sig, + const unsigned char *pk) + __attribute__ ((warn_unused_result)); + #ifdef __cplusplus } #endif diff --git a/src/libsodium/include/sodium/crypto_sign_ed25519.h b/src/libsodium/include/sodium/crypto_sign_ed25519.h index ee89db8b..17c150f2 100644 --- a/src/libsodium/include/sodium/crypto_sign_ed25519.h +++ b/src/libsodium/include/sodium/crypto_sign_ed25519.h @@ -2,6 +2,7 @@ #define crypto_sign_ed25519_H #include +#include "crypto_hash_sha512.h" #include "export.h" #ifdef __cplusplus @@ -11,6 +12,13 @@ extern "C" { #endif +typedef struct crypto_sign_ed25519ph_state { + crypto_hash_sha512_state hs; +} crypto_sign_ed25519ph_state; + +SODIUM_EXPORT +size_t crypto_sign_ed25519ph_statebytes(void); + #define crypto_sign_ed25519_BYTES 64U SODIUM_EXPORT size_t crypto_sign_ed25519_bytes(void); @@ -75,6 +83,26 @@ int crypto_sign_ed25519_sk_to_seed(unsigned char *seed, SODIUM_EXPORT int crypto_sign_ed25519_sk_to_pk(unsigned char *pk, const unsigned char *sk); +SODIUM_EXPORT +int crypto_sign_ed25519ph_init(crypto_sign_ed25519ph_state *state); + +SODIUM_EXPORT +int crypto_sign_ed25519ph_update(crypto_sign_ed25519ph_state *state, + const unsigned char *m, + unsigned long long mlen); + +SODIUM_EXPORT +int crypto_sign_ed25519ph_final_create(crypto_sign_ed25519ph_state *state, + unsigned char *sig, + unsigned long long *siglen_p, + const unsigned char *sk); + +SODIUM_EXPORT +int crypto_sign_ed25519ph_final_verify(crypto_sign_ed25519ph_state *state, + unsigned char *sig, + const unsigned char *pk) + __attribute__ ((warn_unused_result)); + #ifdef __cplusplus } #endif diff --git a/test/default/sign.c b/test/default/sign.c index eea0c99e..814f9672 100644 --- a/test/default/sign.c +++ b/test/default/sign.c @@ -1061,21 +1061,23 @@ static void add_l(unsigned char * const S) int main(void) { - unsigned char extracted_seed[crypto_sign_ed25519_SEEDBYTES]; - unsigned char extracted_pk[crypto_sign_ed25519_PUBLICKEYBYTES]; - unsigned char sig[crypto_sign_BYTES]; - unsigned char sm[1024 + crypto_sign_BYTES]; - unsigned char m[1024]; - unsigned char skpk[crypto_sign_SECRETKEYBYTES]; - unsigned char pk[crypto_sign_PUBLICKEYBYTES]; - unsigned char sk[crypto_sign_SECRETKEYBYTES]; - char pk_hex[crypto_sign_PUBLICKEYBYTES * 2 + 1]; - char sk_hex[crypto_sign_SECRETKEYBYTES * 2 + 1]; + crypto_sign_state st; + unsigned char extracted_seed[crypto_sign_ed25519_SEEDBYTES]; + unsigned char extracted_pk[crypto_sign_ed25519_PUBLICKEYBYTES]; + unsigned char sig[crypto_sign_BYTES]; + unsigned char sm[1024 + crypto_sign_BYTES]; + unsigned char m[1024]; + unsigned char skpk[crypto_sign_SECRETKEYBYTES]; + unsigned char pk[crypto_sign_PUBLICKEYBYTES]; + unsigned char sk[crypto_sign_SECRETKEYBYTES]; + char sig_hex[crypto_sign_BYTES * 2 + 1]; + char pk_hex[crypto_sign_PUBLICKEYBYTES * 2 + 1]; + char sk_hex[crypto_sign_SECRETKEYBYTES * 2 + 1]; unsigned long long siglen; unsigned long long smlen; unsigned long long mlen; - unsigned int i; - unsigned int j; + unsigned int i; + unsigned int j; memset(sig, 0, sizeof sig); for (i = 0U; i < (sizeof test_data) / (sizeof test_data[0]); i++) { @@ -1134,7 +1136,7 @@ int main(void) continue; } if (siglen == 0U || siglen > crypto_sign_BYTES) { - printf("detached signature has an unexpected length"); + printf("detached signature has an unexpected length: [%u]\n", i); continue; } if (memcmp(test_data[i].sig, sig, crypto_sign_BYTES) != 0) { @@ -1189,6 +1191,60 @@ int main(void) printf("detached signature verification should have failed\n"); } + if (crypto_sign_seed_keypair(pk, sk, keypair_seed) != 0) { + printf("crypto_sign_seed_keypair() failure\n"); + return -1; + } + crypto_sign_init(&st); + crypto_sign_update(&st, (const unsigned char *)test_data[i].m, i); + crypto_sign_final_create(&st, sig, NULL, sk); + sodium_bin2hex(sig_hex, sizeof sig_hex, sig, sizeof sig); + printf("ed25519ph sig: [%s]\n", sig_hex); + + crypto_sign_init(&st); + crypto_sign_update(&st, (const unsigned char *)test_data[i].m, i); + if (crypto_sign_final_verify(&st, sig, pk) != 0) { + printf("ed5519ph verification failed\n"); + } + crypto_sign_init(&st); + crypto_sign_update(&st, (const unsigned char *)test_data[i].m, 0); + crypto_sign_update(&st, (const unsigned char *)test_data[i].m, i / 2); + crypto_sign_update(&st, ((const unsigned char *)test_data[i].m) + i / 2, + i - i / 2); + if (crypto_sign_final_verify(&st, sig, pk) != 0) { + printf("ed5519ph verification failed\n"); + } + sig[0]++; + if (crypto_sign_final_verify(&st, sig, pk) != -1) { + printf("ed5519ph verification could be forged\n"); + } + sig[0]--; + pk[0]++; + if (crypto_sign_final_verify(&st, sig, pk) != -1) { + printf("ed5519ph verification could be forged\n"); + } + sodium_hex2bin(sk, crypto_sign_SECRETKEYBYTES, + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", + 2 * crypto_sign_SECRETKEYBYTES , NULL, NULL, NULL); + sodium_hex2bin(pk, crypto_sign_PUBLICKEYBYTES, + "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", + 2 * crypto_sign_PUBLICKEYBYTES, NULL, NULL, NULL); + memcpy(sk + crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES, + pk, crypto_sign_PUBLICKEYBYTES); + crypto_sign_init(&st); + crypto_sign_update(&st, (const unsigned char *) "abc", 3); + crypto_sign_final_create(&st, sig, &siglen, sk); + if (siglen == 0U || siglen > crypto_sign_BYTES) { + printf("ed25519ph signature has an unexpected length\n"); + } + sodium_bin2hex(sig_hex, sizeof sig_hex, sig, sizeof sig); + printf("ed25519ph tv sig: [%s]\n", sig_hex); + + crypto_sign_init(&st); + crypto_sign_update(&st, (const unsigned char *) "abc", 3); + if (crypto_sign_final_verify(&st, sig, pk) != 0) { + printf("ed25519ph verification failed\n"); + } if (crypto_sign_keypair(pk, sk) != 0) { printf("crypto_sign_keypair() failure\n"); } @@ -1222,6 +1278,7 @@ int main(void) == crypto_sign_ed25519_publickeybytes()); assert(crypto_sign_secretkeybytes() == crypto_sign_ed25519_secretkeybytes()); + assert(crypto_sign_statebytes() == crypto_sign_ed25519ph_statebytes()); return 0; } diff --git a/test/default/sign.exp b/test/default/sign.exp index 04bf6536..1c4285f5 100644 --- a/test/default/sign.exp +++ b/test/default/sign.exp @@ -1,3 +1,5 @@ 1024 tests +ed25519ph sig: [10c5411e40bd10170fb890d4dfdb6d338c8cb11d2764a216ee54df10977dcdefd8ff755b1eeb3f16fce80e40e7aafc99083dbff43d5031baf04157b48423960d] +ed25519ph tv sig: [98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae4131f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406] pk: [b5076a8474a832daee4dd5b4040983b6623b5f344aca57d4d6ee4baf3f259e6e] sk: [421151a459faeade3d247115f94aedae42318124095afabe4d1451a559faedeeb5076a8474a832daee4dd5b4040983b6623b5f344aca57d4d6ee4baf3f259e6e]