mirror of
https://github.com/chris2511/xca.git
synced 2026-09-14 11:06:19 +05:00
Add support for SSH2 ED25519 private key export
Encrypting the SSH2 private keys is not supported, yet.
This commit is contained in:
parent
241abffaad
commit
45de747461
@ -216,12 +216,15 @@ exportType::etype db_key::clipboardFormat(QModelIndexList indexes) const
|
||||
if (ssh2compatible)
|
||||
types << exportType(exportType::SSH2_public,
|
||||
"pub", tr("SSH2 public"));
|
||||
if (allPriv)
|
||||
if (allPriv) {
|
||||
types << exportType(exportType::PEM_private, "pem",
|
||||
tr("PEM private"))
|
||||
<< exportType(exportType::PKCS8, "pk8",
|
||||
"PKCS#8");
|
||||
|
||||
if (ssh2compatible)
|
||||
types << exportType(exportType::SSH2_private,
|
||||
"", tr("SSH2 private"));
|
||||
}
|
||||
ExportDialog *dlg = new ExportDialog(NULL,
|
||||
tr("Export keys to Clipboard"), QString(), NULL,
|
||||
QPixmap(":keyImg"), types);
|
||||
@ -241,7 +244,7 @@ void db_key::store(QModelIndex index)
|
||||
const EVP_CIPHER *algo = NULL, *encrypt = EVP_aes_256_cbc();
|
||||
QString title = tr("Export public key [%1]");
|
||||
QList<exportType> types;
|
||||
bool pvk = false;
|
||||
bool pvk = false, ed25519 = false;
|
||||
|
||||
pki_key *key = fromIndex<pki_key>(index);
|
||||
pki_evp *privkey = dynamic_cast<pki_evp *>(key);
|
||||
@ -253,6 +256,10 @@ void db_key::store(QModelIndex index)
|
||||
int keytype = key->getKeyType();
|
||||
if (keytype == EVP_PKEY_RSA || keytype == EVP_PKEY_DSA)
|
||||
pvk = true;
|
||||
#ifdef EVP_PKEY_ED25519
|
||||
if (keytype == EVP_PKEY_ED25519)
|
||||
ed25519 = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
types <<
|
||||
@ -264,12 +271,13 @@ void db_key::store(QModelIndex index)
|
||||
"pub", tr("SSH2 public"));
|
||||
if (!key->isPubKey() && !key->isToken()) {
|
||||
QList<exportType> usual;
|
||||
if (!ed25519)
|
||||
types << exportType(exportType::PEM_private_encrypt,
|
||||
"pem", tr("PEM encryped"));
|
||||
types <<
|
||||
exportType(exportType::DER_private, "der",
|
||||
tr("DER private")) <<
|
||||
exportType(exportType::PEM_private_encrypt, "pem",
|
||||
tr("PEM encryped")) <<
|
||||
exportType(exportType::PKCS8, "pk8", "PKCS#8");
|
||||
exportType(exportType::DER_private, "der",
|
||||
tr("DER private")) <<
|
||||
exportType(exportType::PKCS8, "pk8", "PKCS#8");
|
||||
|
||||
if (pvk) {
|
||||
types <<
|
||||
@ -278,11 +286,14 @@ void db_key::store(QModelIndex index)
|
||||
exportType(exportType::PVK_encrypt, "pvk",
|
||||
tr("PVK encrypted"));
|
||||
}
|
||||
usual <<
|
||||
exportType(exportType::PEM_private, "pem",
|
||||
tr("PEM private")) <<
|
||||
exportType(exportType::PKCS8_encrypt, "pk8",
|
||||
if (!ed25519)
|
||||
usual << exportType(exportType::PEM_private, "pem",
|
||||
tr("PEM private"));
|
||||
usual << exportType(exportType::PKCS8_encrypt, "pk8",
|
||||
tr("PKCS#8 encrypted"));
|
||||
if (key->SSH2_compatible())
|
||||
usual << exportType(exportType::SSH2_private, "",
|
||||
tr("SSH2 private"));
|
||||
title = tr("Export private key [%1]");
|
||||
types = usual << exportType() << types;
|
||||
}
|
||||
@ -338,6 +349,9 @@ void db_key::store(QModelIndex index)
|
||||
case exportType::SSH2_public:
|
||||
key->writeSSH2public(file);
|
||||
break;
|
||||
case exportType::SSH2_private:
|
||||
key->writeSSH2private(file, PwDialog::pwCallback);
|
||||
break;
|
||||
case exportType::PVK_private:
|
||||
privkey->writePVKprivate(file, NULL);
|
||||
break;
|
||||
|
||||
@ -105,6 +105,7 @@ static inline void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline EVP_CIPHER_CTX *EVP_CIPHER_CTX_new()
|
||||
{
|
||||
return (EVP_CIPHER_CTX*)OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX));
|
||||
@ -115,6 +116,7 @@ static inline void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
|
||||
EVP_CIPHER_CTX_cleanup(ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -92,9 +92,10 @@ QByteArray pki_key::i2d() const
|
||||
return i2d_bytearray(I2D_VOID(i2d_PUBKEY), key);
|
||||
}
|
||||
|
||||
void pki_key::write_SSH2_ed25519_private(BioByteArray &b,
|
||||
void pki_key::write_SSH2_ed25519_private(BIO *b,
|
||||
const EVP_PKEY *pkey, const EVP_CIPHER *enc) const
|
||||
{
|
||||
#ifndef OPENSSL_NO_EC
|
||||
static const char data0001[] = { 0, 0, 0, 1};
|
||||
char buf_nonce[8];
|
||||
QByteArray data, priv, pubfull;
|
||||
@ -118,6 +119,7 @@ void pki_key::write_SSH2_ed25519_private(BioByteArray &b,
|
||||
PEM_write_bio(b, PEM_STRING_OPENSSH_KEY, (char*)"",
|
||||
(unsigned char*)(data.data()), data.size());
|
||||
pki_openssl_error();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool pki_key::pem(BioByteArray &b, int format)
|
||||
@ -131,6 +133,7 @@ bool pki_key::pem(BioByteArray &b, int format)
|
||||
b += SSH2publicQByteArray();
|
||||
break;
|
||||
case exportType::PEM_private:
|
||||
case exportType::SSH2_private:
|
||||
pkey = decryptKey();
|
||||
keytype = EVP_PKEY_id(pkey);
|
||||
switch (keytype) {
|
||||
@ -152,6 +155,8 @@ bool pki_key::pem(BioByteArray &b, int format)
|
||||
break;
|
||||
#ifdef EVP_PKEY_ED25519
|
||||
case EVP_PKEY_ED25519:
|
||||
if (format == exportType::PEM_private)
|
||||
return false;
|
||||
write_SSH2_ed25519_private(b, pkey, NULL);
|
||||
break;
|
||||
#endif
|
||||
@ -173,6 +178,19 @@ bool pki_key::pem(BioByteArray &b, int format)
|
||||
return true;
|
||||
}
|
||||
|
||||
void pki_key::writeSSH2private(XFile &file, pem_password_cb *cb) const
|
||||
{
|
||||
(void)cb;
|
||||
// pass_info p(XCA_TITLE, tr("Please enter the password protecting the SSH2 private key '%1'").arg(getIntName()));
|
||||
|
||||
EVP_PKEY *pkey = decryptKey();
|
||||
if (!pkey) {
|
||||
pki_openssl_error();
|
||||
return;
|
||||
}
|
||||
write_SSH2_ed25519_private(file.bio(), pkey, NULL);
|
||||
}
|
||||
|
||||
QString pki_key::length() const
|
||||
{
|
||||
bool dsa_unset = false;
|
||||
@ -355,18 +373,17 @@ QString pki_key::ecPubKey() const
|
||||
return pub;
|
||||
}
|
||||
|
||||
#ifdef EVP_PKEY_ED25519
|
||||
static QByteArray ed25519Key(int(*EVP_PKEY_get_raw)
|
||||
(const EVP_PKEY*, unsigned char *, size_t *),
|
||||
const EVP_PKEY *pkey)
|
||||
{
|
||||
#ifdef EVP_PKEY_ED25519
|
||||
unsigned char k[ED25519_KEYLEN];
|
||||
size_t len = sizeof k;
|
||||
|
||||
if (EVP_PKEY_id(pkey) == EVP_PKEY_ED25519 &&
|
||||
EVP_PKEY_get_raw(pkey, k, &len))
|
||||
return QByteArray((char*)k, len);
|
||||
#endif
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
@ -379,6 +396,19 @@ QByteArray pki_key::ed25519PrivKey(const EVP_PKEY *pkey) const
|
||||
{
|
||||
return ed25519Key(EVP_PKEY_get_raw_private_key, pkey);
|
||||
}
|
||||
#else
|
||||
|
||||
QByteArray pki_key::ed25519PubKey() const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray pki_key::ed25519PrivKey(const EVP_PKEY *) const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
QList<int> pki_key::possibleHashNids()
|
||||
|
||||
@ -236,9 +236,10 @@ class pki_key: public pki_base
|
||||
QByteArray i2d() const;
|
||||
EVP_PKEY *load_ssh2_key(XFile &file);
|
||||
void writeSSH2public(XFile &file) const;
|
||||
void writeSSH2private(XFile &file, pem_password_cb *cb) const;
|
||||
QString fingerprint(const QString &format) const;
|
||||
bool SSH2_compatible() const;
|
||||
void write_SSH2_ed25519_private(BioByteArray &b,
|
||||
void write_SSH2_ed25519_private(BIO *b,
|
||||
const EVP_PKEY *pkey, const EVP_CIPHER *enc) const;
|
||||
void print(BioByteArray &b, enum print_opt opt) const;
|
||||
void resetUcount()
|
||||
|
||||
@ -21,7 +21,7 @@ class exportType {
|
||||
PEM_key, PEM_private, PEM_private_encrypt, DER_private,
|
||||
DER_key, PKCS8, PKCS8_encrypt, SSH2_public,
|
||||
PEM_selected, PKCS7_selected, Index, vcalendar, vcalendar_ca,
|
||||
PVK_private, PVK_encrypt, ETYPE_max };
|
||||
PVK_private, PVK_encrypt, SSH2_private, ETYPE_max };
|
||||
enum etype type;
|
||||
QString desc;
|
||||
QString extension;
|
||||
@ -41,6 +41,7 @@ class exportType {
|
||||
case PEM_private:
|
||||
case PEM_private_encrypt:
|
||||
case PEM_selected:
|
||||
case SSH2_private:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user