diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h index 3ffb857d..b61c0f09 100644 --- a/include/opendht/crypto.h +++ b/include/opendht/crypto.h @@ -204,7 +204,13 @@ struct OPENDHT_PUBLIC PrivateKey * @param algo : the public key algorithm to use, GNUTLS_PK_RSA or GNUTLS_PK_RSA_OAEP */ static PrivateKey generate(unsigned key_length = 4096, gnutls_pk_algorithm_t algo = GNUTLS_PK_RSA); - static PrivateKey generateEC(); + + /** + * Generate a new EC key pair + * @param curve : the elliptic curve to use. If GNUTLS_ECC_CURVE_INVALID is provided, the default curve will be used + * (currently GNUTLS_ECC_CURVE_SECP384R1). + */ + static PrivateKey generateEC(gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID); gnutls_privkey_t key {}; gnutls_x509_privkey_t x509_key {}; @@ -272,7 +278,8 @@ public: * and incremented on subsequent ones. */ void sign(const PrivateKey&, const Certificate&, duration validity_period = {}, uint64_t number = 0); - void sign(const Identity& id, duration validity_period = {}, uint64_t number = 0) { + void sign(const Identity& id, duration validity_period = {}, uint64_t number = 0) + { sign(*id.first, *id.second, validity_period, number); } diff --git a/src/crypto.cpp b/src/crypto.cpp index 327cc6fc..709dc160 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -1294,14 +1294,16 @@ PrivateKey::generate(unsigned key_length, gnutls_pk_algorithm_t algo) } PrivateKey -PrivateKey::generateEC() +PrivateKey::generateEC(gnutls_ecc_curve_t curve) { gnutls_x509_privkey_t key; if (gnutls_x509_privkey_init(&key) != GNUTLS_E_SUCCESS) throw CryptoException("Unable to initialize private key."); int err = gnutls_x509_privkey_generate(key, GNUTLS_PK_EC, - gnutls_sec_param_to_pk_bits(GNUTLS_PK_EC, GNUTLS_SEC_PARAM_ULTRA), + curve == GNUTLS_ECC_CURVE_INVALID + ? gnutls_sec_param_to_pk_bits(GNUTLS_PK_EC, GNUTLS_SEC_PARAM_ULTRA) + : GNUTLS_CURVE_TO_BITS(curve), 0); if (err != GNUTLS_E_SUCCESS) { gnutls_x509_privkey_deinit(key); diff --git a/tests/test_crypto.cpp b/tests/test_crypto.cpp index 11a66235..48f51898 100644 --- a/tests/test_crypto.cpp +++ b/tests/test_crypto.cpp @@ -327,6 +327,16 @@ CryptoTester::testCertificateSerialNumber() } } +void +CryptoTester::testEcKeyCurve() +{ + auto key = dht::crypto::PrivateKey::generateEC(GNUTLS_ECC_CURVE_SECP256R1); + unsigned int bits = 0; + CPPUNIT_ASSERT_EQUAL(static_cast(GNUTLS_PK_EC), + gnutls_x509_privkey_get_pk_algorithm2(key.x509_key, &bits)); + CPPUNIT_ASSERT_EQUAL(256u, bits); +} + void CryptoTester::testOcsp() { diff --git a/tests/test_crypto.h b/tests/test_crypto.h index 35420e8d..c835a633 100644 --- a/tests/test_crypto.h +++ b/tests/test_crypto.h @@ -19,6 +19,7 @@ class CryptoTester : public CppUnit::TestFixture CPPUNIT_TEST(testRevocationListPartitionedNumber); CPPUNIT_TEST(testCertificateRequest); CPPUNIT_TEST(testCertificateSerialNumber); + CPPUNIT_TEST(testEcKeyCurve); CPPUNIT_TEST(testOcsp); CPPUNIT_TEST(testAesEncryption); CPPUNIT_TEST(testAesEncryptionWithMultipleKeySizes); @@ -68,6 +69,10 @@ public: * Test certificate serial number extraction */ void testCertificateSerialNumber(); + /** + * Test EC private key generation with an explicit curve + */ + void testEcKeyCurve(); /** * Test OCSP */