forked from qt-creator/qt-creator
SSH: Support creation of ECDSA keys.
Change-Id: Id5b5ed289a3fd86bd8b84e6429c18f417ca793a7 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com> Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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">
|
||||
@@ -67,6 +67,13 @@
|
||||
</property>
|
||||
</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">
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user