diff options
author | Christian Kandeler <[email protected]> | 2015-07-22 16:26:05 +0200 |
---|---|---|
committer | Christian Kandeler <[email protected]> | 2015-07-27 13:08:44 +0000 |
commit | ac0e66d9e04e196f4b3a46cd709cb76aafbd45fe (patch) | |
tree | 7ced42883d1e6fd411eb2ab94808978593e42a84 | |
parent | 8f5618c3ecc0daf971b19780646cc14a6db12931 (diff) |
SSH: Support creation of ECDSA keys.
Change-Id: Id5b5ed289a3fd86bd8b84e6429c18f417ca793a7
Reviewed-by: Leena Miettinen <[email protected]>
Reviewed-by: Joerg Bornemann <[email protected]>
-rw-r--r-- | src/libs/ssh/sshcryptofacility.cpp | 14 | ||||
-rw-r--r-- | src/libs/ssh/sshkeycreationdialog.cpp | 17 | ||||
-rw-r--r-- | src/libs/ssh/sshkeycreationdialog.ui | 26 | ||||
-rw-r--r-- | src/libs/ssh/sshkeygenerator.cpp | 49 | ||||
-rw-r--r-- | src/libs/ssh/sshkeygenerator.h | 2 |
5 files changed, 72 insertions, 36 deletions
diff --git a/src/libs/ssh/sshcryptofacility.cpp b/src/libs/ssh/sshcryptofacility.cpp index 227c8df3ab5..4dc27929f86 100644 --- a/src/libs/ssh/sshcryptofacility.cpp +++ b/src/libs/ssh/sshcryptofacility.cpp @@ -256,19 +256,23 @@ bool SshEncryptionFacility::createAuthenticationKeyFromPKCS8(const QByteArray &p try { Pipe pipe; pipe.process_msg(convertByteArray(privKeyFileContents), privKeyFileContents.size()); - Private_Key * const key = PKCS8::load_key(pipe, m_rng, SshKeyPasswordRetriever()); - if (DSA_PrivateKey * const dsaKey = dynamic_cast<DSA_PrivateKey *>(key)) { + m_authKey.reset(PKCS8::load_key(pipe, m_rng, SshKeyPasswordRetriever())); + if (auto * const dsaKey = dynamic_cast<DSA_PrivateKey *>(m_authKey.data())) { m_authKeyAlgoName = SshCapabilities::PubKeyDss; - m_authKey.reset(dsaKey); pubKeyParams << dsaKey->group_p() << dsaKey->group_q() << dsaKey->group_g() << dsaKey->get_y(); allKeyParams << pubKeyParams << dsaKey->get_x(); - } else if (RSA_PrivateKey * const rsaKey = dynamic_cast<RSA_PrivateKey *>(key)) { + } else if (auto * const rsaKey = dynamic_cast<RSA_PrivateKey *>(m_authKey.data())) { m_authKeyAlgoName = SshCapabilities::PubKeyRsa; - m_authKey.reset(rsaKey); pubKeyParams << rsaKey->get_e() << rsaKey->get_n(); allKeyParams << pubKeyParams << rsaKey->get_p() << rsaKey->get_q() << rsaKey->get_d(); + } else if (auto * const ecdsaKey = dynamic_cast<ECDSA_PrivateKey *>(m_authKey.data())) { + const BigInt value = ecdsaKey->private_value(); + m_authKeyAlgoName = SshCapabilities::ecdsaPubKeyAlgoForKeyWidth(value.bytes()); + pubKeyParams << ecdsaKey->public_point().get_affine_x() + << ecdsaKey->public_point().get_affine_y(); + allKeyParams << pubKeyParams << value; } else { qWarning("%s: Unexpected code flow, expected success or exception.", Q_FUNC_INFO); return false; diff --git a/src/libs/ssh/sshkeycreationdialog.cpp b/src/libs/ssh/sshkeycreationdialog.cpp index 80118cde5ac..348a8423649 100644 --- a/src/libs/ssh/sshkeycreationdialog.cpp +++ b/src/libs/ssh/sshkeycreationdialog.cpp @@ -64,6 +64,7 @@ SshKeyCreationDialog::SshKeyCreationDialog(QWidget *parent) this, &SshKeyCreationDialog::handleBrowseButtonClicked); connect(m_ui->generateButton, &QPushButton::clicked, this, &SshKeyCreationDialog::generateKeys); + keyTypeChanged(); } SshKeyCreationDialog::~SshKeyCreationDialog() @@ -74,8 +75,16 @@ SshKeyCreationDialog::~SshKeyCreationDialog() void SshKeyCreationDialog::keyTypeChanged() { - m_ui->comboBox->setCurrentIndex(0); - m_ui->comboBox->setEnabled(m_ui->rsa->isChecked()); + m_ui->comboBox->clear(); + QStringList keySizes; + if (m_ui->rsa->isChecked()) + keySizes << QLatin1String("1024") << QLatin1String("2048") << QLatin1String("4096"); + else if (m_ui->ecdsa->isChecked()) + keySizes << QLatin1String("256") << QLatin1String("384") << QLatin1String("521"); + m_ui->comboBox->addItems(keySizes); + if (!keySizes.isEmpty()) + m_ui->comboBox->setCurrentIndex(0); + m_ui->comboBox->setEnabled(!keySizes.isEmpty()); } void SshKeyCreationDialog::generateKeys() @@ -84,8 +93,8 @@ void SshKeyCreationDialog::generateKeys() return; const SshKeyGenerator::KeyType keyType = m_ui->rsa->isChecked() - ? SshKeyGenerator::Rsa - : SshKeyGenerator::Dsa; + ? SshKeyGenerator::Rsa : m_ui->dsa->isChecked() + ? SshKeyGenerator::Dsa : SshKeyGenerator::Ecdsa; if (!m_keyGenerator) m_keyGenerator = new SshKeyGenerator; diff --git a/src/libs/ssh/sshkeycreationdialog.ui b/src/libs/ssh/sshkeycreationdialog.ui index d49681e65b9..eb3347e8ee8 100644 --- a/src/libs/ssh/sshkeycreationdialog.ui +++ b/src/libs/ssh/sshkeycreationdialog.ui @@ -9,8 +9,8 @@ <rect> <x>0</x> <y>0</y> - <width>295</width> - <height>223</height> + <width>380</width> + <height>231</height> </rect> </property> <property name="sizePolicy"> @@ -68,6 +68,13 @@ </widget> </item> <item> + <widget class="QRadioButton" name="ecdsa"> + <property name="text"> + <string>ECDSA</string> + </property> + </widget> + </item> + <item> <spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -102,21 +109,6 @@ <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <widget class="QComboBox" name="comboBox"> - <item> - <property name="text"> - <string notr="true">1024</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">2048</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">4096</string> - </property> - </item> </widget> </item> <item> diff --git a/src/libs/ssh/sshkeygenerator.cpp b/src/libs/ssh/sshkeygenerator.cpp index d70819e97e4..1c6e22db038 100644 --- a/src/libs/ssh/sshkeygenerator.cpp +++ b/src/libs/ssh/sshkeygenerator.cpp @@ -32,6 +32,7 @@ #include "sshbotanconversions_p.h" #include "sshcapabilities_p.h" +#include "ssh_global.h" #include "sshinit_p.h" #include "sshpacket_p.h" @@ -61,10 +62,19 @@ bool SshKeyGenerator::generateKeys(KeyType type, PrivateKeyFormat format, int ke try { AutoSeeded_RNG rng; KeyPtr key; - if (m_type == Rsa) + switch (m_type) { + case Rsa: key = KeyPtr(new RSA_PrivateKey(rng, keySize)); - else + break; + case Dsa: key = KeyPtr(new DSA_PrivateKey(rng, DL_Group(rng, DL_Group::DSA_Kosherizer, keySize))); + break; + case Ecdsa: { + const QByteArray algo = SshCapabilities::ecdsaPubKeyAlgoForKeyWidth(keySize / 8); + key = KeyPtr(new ECDSA_PrivateKey(rng, EC_Group(SshCapabilities::oid(algo)))); + break; + } + } switch (format) { case Pkcs8: generatePkcs8KeyStrings(key, rng); @@ -125,19 +135,35 @@ void SshKeyGenerator::generateOpenSslPublicKeyString(const KeyPtr &key) { QList<BigInt> params; QByteArray keyId; - if (m_type == Rsa) { + QByteArray q; + switch (m_type) { + case Rsa: { const QSharedPointer<RSA_PrivateKey> rsaKey = key.dynamicCast<RSA_PrivateKey>(); params << rsaKey->get_e() << rsaKey->get_n(); keyId = SshCapabilities::PubKeyRsa; - } else { + break; + } + case Dsa: { const QSharedPointer<DSA_PrivateKey> dsaKey = key.dynamicCast<DSA_PrivateKey>(); params << dsaKey->group_p() << dsaKey->group_q() << dsaKey->group_g() << dsaKey->get_y(); keyId = SshCapabilities::PubKeyDss; + break; + } + case Ecdsa: { + const auto ecdsaKey = key.dynamicCast<ECDSA_PrivateKey>(); + q = convertByteArray(EC2OSP(ecdsaKey->public_point(), PointGFp::UNCOMPRESSED)); + keyId = SshCapabilities::ecdsaPubKeyAlgoForKeyWidth(ecdsaKey->private_value().bytes()); + break; + } } QByteArray publicKeyBlob = AbstractSshPacket::encodeString(keyId); foreach (const BigInt &b, params) publicKeyBlob += AbstractSshPacket::encodeMpInt(b); + if (!q.isEmpty()) { + publicKeyBlob += AbstractSshPacket::encodeString(keyId.mid(11)); // Without "ecdsa-sha2-" prefix. + publicKeyBlob += AbstractSshPacket::encodeString(q); + } publicKeyBlob = publicKeyBlob.toBase64(); const QByteArray id = "QtCreator/" + QDateTime::currentDateTime().toString(Qt::ISODate).toUtf8(); @@ -147,9 +173,9 @@ void SshKeyGenerator::generateOpenSslPublicKeyString(const KeyPtr &key) void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key) { QList<BigInt> params; - QByteArray keyId; const char *label; - if (m_type == Rsa) { + switch (m_type) { + case Rsa: { const QSharedPointer<RSA_PrivateKey> rsaKey = key.dynamicCast<RSA_PrivateKey>(); params << rsaKey->get_n() << rsaKey->get_e() << rsaKey->get_d() << rsaKey->get_p() @@ -158,14 +184,19 @@ void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key) const BigInt dmq1 = rsaKey->get_d() % (rsaKey->get_q() - 1); const BigInt iqmp = inverse_mod(rsaKey->get_q(), rsaKey->get_p()); params << dmp1 << dmq1 << iqmp; - keyId = SshCapabilities::PubKeyRsa; label = "RSA PRIVATE KEY"; - } else { + break; + } + case Dsa: { const QSharedPointer<DSA_PrivateKey> dsaKey = key.dynamicCast<DSA_PrivateKey>(); params << dsaKey->group_p() << dsaKey->group_q() << dsaKey->group_g() << dsaKey->get_y() << dsaKey->get_x(); - keyId = SshCapabilities::PubKeyDss; label = "DSA PRIVATE KEY"; + break; + } + case Ecdsa: + params << key.dynamicCast<ECDSA_PrivateKey>()->private_value(); + label = "EC PRIVATE KEY"; } DER_Encoder encoder; diff --git a/src/libs/ssh/sshkeygenerator.h b/src/libs/ssh/sshkeygenerator.h index 7092eceb12c..df9ac41518a 100644 --- a/src/libs/ssh/sshkeygenerator.h +++ b/src/libs/ssh/sshkeygenerator.h @@ -47,7 +47,7 @@ class QSSH_EXPORT SshKeyGenerator { Q_DECLARE_TR_FUNCTIONS(SshKeyGenerator) public: - enum KeyType { Rsa, Dsa }; + enum KeyType { Rsa, Dsa, Ecdsa }; enum PrivateKeyFormat { Pkcs8, OpenSsl, Mixed }; enum EncryptionMode { DoOfferEncryption, DoNotOfferEncryption }; // Only relevant for Pkcs8 format. |