[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Passphrase not working for ssh_pki_export_privkey_file
[Thread Prev] | [Thread Next]
- Subject: Re: Passphrase not working for ssh_pki_export_privkey_file
- From: Julian Lunz <git@xxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Sun, 8 Feb 2015 11:17:39 +0100
- To: libssh@xxxxxxxxxx
On Fri, 06 Feb 2015 09:35:56 +0100 Andreas Schneider <asn@xxxxxxxxxxxxxx> wrote: > On Thursday 05 February 2015 16:21:03 Julian Lunz wrote: > > I had time to dig a bit further. > > > > The function pki_private_key_to_pem in src/pki_crypto.c +554 > > is missing a cipher in case of passphrase != NULL. > > > > ssh-keygen uses AES-128-CBC therefore this is used in the attached > > patch. > > > > Is the mailing list the preferred way for patches or better via > > Redmine? > > > > Thank you very much for your contribution. It is fine to send patches > to the mailing list. > > However to add the patch to the libssh repository we also need a test > for it! > > Please take a look at tests/unittests/torture_pki.c and add a test. > You get the unit tests if you install cmocka [1] and run 'cmake > -DUNIT_TESTING=ON ..' > > > Cheers, > > > -- andreas > > > > [1] http://cmocka.org > > Sure, please find attached a patch series with tests included. # 0001-Fix-pki_private_key_to_pem-by-adding-cipher.patch Contains the fix which adds cipher to ssh_string pki_private_key_to_pem. # 0002-tests-Add-encrypted-keys-export-for-rsa-dsa-ecdsa.patch Contains updated test for torture_pki_write_privkey_[rsa,dsa,ecdsa] + added private keys for ecdsa. I changed the existing calls to ssh_pki_export_privkey_file which had "" as a passhrase since NULL != "". If PEM_write_bio_RSAPrivateKey has no cipher set, as it was before 0001, keys are always written in unencrypted form. The documentation for ssh_pki_export_privkey_file says: passphrase The passphrase to use to encrypt the key with or NULL. An empty string means no passphrase. If this should behave like that a check for an empty string in addition to check for NULL is needed. Julian
From 05ea65c9f554b85b5dce6cbd176d0f8ab9910ab8 Mon Sep 17 00:00:00 2001 From: Julian Lunz <git@xxxxxxxx> Date: Thu, 5 Feb 2015 16:12:28 +0100 Subject: [PATCH 1/3] Fix pki_private_key_to_pem by adding cipher --- src/pki_crypto.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pki_crypto.c b/src/pki_crypto.c index b53bba2..77fa14c 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -586,7 +586,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key, } else { rc = PEM_write_bio_DSAPrivateKey(mem, key->dsa, - NULL, /* cipher */ + EVP_aes_128_cbc(), /* cipher */ NULL, /* kstr */ 0, /* klen */ NULL, /* auth_fn */ @@ -611,7 +611,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key, } else { rc = PEM_write_bio_RSAPrivateKey(mem, key->rsa, - NULL, /* cipher */ + EVP_aes_128_cbc(), /* cipher */ NULL, /* kstr */ 0, /* klen */ NULL, /* auth_fn */ @@ -636,7 +636,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key, } else { rc = PEM_write_bio_ECPrivateKey(mem, key->ecdsa, - NULL, /* cipher */ + EVP_aes_128_cbc(), /* cipher */ NULL, /* kstr */ 0, /* klen */ NULL, /* auth_fn */ -- 2.2.2
From b949b7c61f2f020cfe7cad6e9917f3c3c24cdfec Mon Sep 17 00:00:00 2001 From: Julian Lunz <git@xxxxxxxx> Date: Sun, 8 Feb 2015 10:31:05 +0100 Subject: [PATCH 2/3] tests: Add encrypted keys export for rsa, dsa, ecdsa --- tests/torture.c | 39 +++++++++++- tests/unittests/torture_pki.c | 138 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 6 deletions(-) diff --git a/tests/torture.c b/tests/torture.c index c139f6a..d886638 100644 --- a/tests/torture.c +++ b/tests/torture.c @@ -169,6 +169,16 @@ static const char torture_ecdsa256_testkey_pub[] = "YAAABBBMfvbnfPEORlrS3fsjLWGmqQvOYPtmS6e1bRRwNBGzR6gVEMaIfiJPPTJa+w" "FMXBT3fpAqPjROsqv5jUHC+xOok= aris@kalix86\n"; +static const char torture_ecdsa256_testkey_pp[] = + "-----BEGIN EC PRIVATE KEY-----\n" + "Proc-Type: 4,ENCRYPTED\n" + "DEK-Info: AES-128-CBC,319046776365CE0CA7347018E955A5E7\n" + "\n" + "x7p+v1SWYSdbWVsmnteZp7TgQnCFICGT/2s6rYhLlanKUxNaQ97INwaDvVzcCv1P\n" + "qD6wpAMn4Ohiq2hLeYnGCGX75Qu3rixmn+c3NdIV11vyRgM7FkwmhPKuj41fHWqM\n" + "0ZCPhjAaYAUK6p5KlDwvZBLiCmQKXAAZEHBudVfNhTw=\n" + "-----END EC PRIVATE KEY-----\n"; + static const char torture_ecdsa384_testkey[] = "-----BEGIN EC PRIVATE KEY-----\n" "MIGkAgEBBDBY8jEa5DtRy4AVeTWhPJ/TK257behiC3uafEi6YA2oHORibqX55EDN\n" @@ -183,6 +193,17 @@ static const char torture_ecdsa384_testkey_pub[] = "0sB3/DunsMkt3O0nRtijJPhXcHdmpH1HIarqZgKOReVzlhtgeO54FunSh41eqxcc0B" "ZBmg== aris@kalix86"; +static const char torture_ecdsa384_testkey_pp[] = + "-----BEGIN EC PRIVATE KEY-----\n" + "Proc-Type: 4,ENCRYPTED\n" + "DEK-Info: AES-128-CBC,B46262FD09E7221B1C74F9657EC7C206\n" + "\n" + "gM/6WGF4YiaVdUeuMOFl0vWGl1K3nT8OpSKncpFoXRhuoumaF5Ky/4Ko+1B42JHZ\n" + "i0tyzHy56TVpwlD2UitGdpqm7vhODVvgkqo+Af6hT/2jWUYDMXrr+hNYU9t98Yzx\n" + "PwLB0/QI9lyidXjBLY5j3r8mpWZ1V6ssZ1FM23+4uvSJ7xyxKpz4OQAidWAOa2Ru\n" + "WvtfZL6RmPfYrJ9ptJpM7XDsDD3pNDhDCc5OGRn69kI=\n" + "-----END EC PRIVATE KEY-----\n"; + static const char torture_ecdsa521_testkey[] = "-----BEGIN EC PRIVATE KEY-----\n" "MIHbAgEBBEG83nSJ2SLoiBvEku1JteQKWx/Xt6THksgC7rrIaTUmNzk+60f0sCCm\n" @@ -198,6 +219,18 @@ static const char torture_ecdsa521_testkey_pub[] = "V262vIC+AE3fXUJ7sJ/CkFIdk/8/gQEY1jyoXB3Bsee16VwhJGsMzGGh1FJ0XXhRJj" "UbG18qbH9JiSgE1N4fIM0zJG68fAyUxRxCI1wUobOOB7EmFZd18g== aris@kalix86"; +static const char torture_ecdsa521_testkey_pp[] = + "-----BEGIN EC PRIVATE KEY-----\n" + "Proc-Type: 4,ENCRYPTED\n" + "DEK-Info: AES-128-CBC,7D4323D6296E2B75E5A4FC6C98D8B04D\n" + "\n" + "XRh464kGFiM7D+8szR5TAe87p1JQfDkzJ37MuD/QwXWuPXq6fODWwibwS9S3yQBL\n" + "KEfzZQMBWEZJPabJF8YO2GA80/Djh80N4R+iOQqqdblP+QxrTiHNPlqBknbqYgDQ\n" + "yepy1YE5gSKLbm/zBCosJlw9kfUfZTqijlDJSiJBJotVcm5NdewZEKb/0Pv3a8hu\n" + "BjDnZNuQd9TqELR96UwMIHwd2Rg8rLIkHTf2PPpWUcOF0Ss3lvc/t8fP6HxoX+QX\n" + "u7i0NdbQ1weZfqNCHSY0gT2MLNGJsE4xLbj7X/LbsYY=\n" + "-----END EC PRIVATE KEY-----\n"; + static const char torture_ed25519_testkey[]= "-----BEGIN OPENSSH PRIVATE KEY-----\n" "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n" @@ -599,14 +632,14 @@ static const char *torture_get_testkey_internal(enum ssh_keytypes_e type, if (pubkey) { return torture_ecdsa521_testkey_pub; } else if (with_passphrase) { - return NULL; + return torture_ecdsa521_testkey_pp; } return torture_ecdsa521_testkey; } else if (bits == 384) { if (pubkey) { return torture_ecdsa384_testkey_pub; } else if (with_passphrase){ - return NULL; + return torture_ecdsa384_testkey_pp; } return torture_ecdsa384_testkey; } @@ -614,7 +647,7 @@ static const char *torture_get_testkey_internal(enum ssh_keytypes_e type, if (pubkey) { return torture_ecdsa256_testkey_pub; } else if (with_passphrase){ - return NULL; + return torture_ecdsa256_testkey_pp; } return torture_ecdsa256_testkey; case SSH_KEYTYPE_ED25519: diff --git a/tests/unittests/torture_pki.c b/tests/unittests/torture_pki.c index 027322a..bc93a3e 100644 --- a/tests/unittests/torture_pki.c +++ b/tests/unittests/torture_pki.c @@ -6,9 +6,13 @@ #include <fcntl.h> #define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa" +#define LIBSSH_RSA_TESTKEY_PASSPHRASE "libssh_testkey.id_rsa_passphrase" #define LIBSSH_DSA_TESTKEY "libssh_testkey.id_dsa" +#define LIBSSH_DSA_TESTKEY_PASSPHRASE "libssh_testkey.id_dsa_passphrase" #define LIBSSH_ECDSA_TESTKEY "libssh_testkey.id_ecdsa" +#define LIBSSH_ECDSA_TESTKEY_PASSPHRASE "libssh_testkey.id_ecdsa_passphrase" #define LIBSSH_ED25519_TESTKEY "libssh_testkey.id_ed25519" +#define LIBSSH_ED25519_TESTKEY_PASSPHRASE "libssh_testkey.id_ed25519_passphrase" const unsigned char HASH[] = "12345678901234567890"; @@ -17,11 +21,14 @@ static void setup_rsa_key(void **state) { unlink(LIBSSH_RSA_TESTKEY); unlink(LIBSSH_RSA_TESTKEY ".pub"); + unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE); torture_write_file(LIBSSH_RSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_RSA, 0, 0)); torture_write_file(LIBSSH_RSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_RSA, 0)); + torture_write_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, + torture_get_testkey(SSH_KEYTYPE_RSA, 0, 1)); } static void setup_dsa_key(void **state) { @@ -29,11 +36,14 @@ static void setup_dsa_key(void **state) { unlink(LIBSSH_DSA_TESTKEY); unlink(LIBSSH_DSA_TESTKEY ".pub"); + unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE); torture_write_file(LIBSSH_DSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_DSS, 0, 0)); torture_write_file(LIBSSH_DSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_DSS, 0)); + torture_write_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, + torture_get_testkey(SSH_KEYTYPE_DSS, 0, 1)); } #ifdef HAVE_OPENSSL_ECC @@ -43,11 +53,14 @@ static void setup_ecdsa_key(void **state, int ecdsa_bits) { unlink(LIBSSH_ECDSA_TESTKEY); unlink(LIBSSH_ECDSA_TESTKEY ".pub"); + unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE); torture_write_file(LIBSSH_ECDSA_TESTKEY, torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 0)); torture_write_file(LIBSSH_ECDSA_TESTKEY ".pub", torture_get_testkey_pub(SSH_KEYTYPE_ECDSA, ecdsa_bits)); + torture_write_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, + torture_get_testkey(SSH_KEYTYPE_ECDSA, ecdsa_bits, 1)); } static void setup_ecdsa_key_521(void **state) { @@ -88,12 +101,16 @@ static void teardown(void **state) { unlink(LIBSSH_DSA_TESTKEY); unlink(LIBSSH_DSA_TESTKEY ".pub"); + unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE); unlink(LIBSSH_RSA_TESTKEY); unlink(LIBSSH_RSA_TESTKEY ".pub"); + unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE); + unlink(LIBSSH_ECDSA_TESTKEY); unlink(LIBSSH_ECDSA_TESTKEY ".pub"); + unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE); } static char *read_file(const char *filename) { @@ -1228,10 +1245,11 @@ static void torture_pki_write_privkey_rsa(void **state) unlink(LIBSSH_RSA_TESTKEY); rc = ssh_pki_export_privkey_file(origkey, - "", + NULL, NULL, NULL, LIBSSH_RSA_TESTKEY); + assert_true(rc == 0); rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY, @@ -1244,6 +1262,44 @@ static void torture_pki_write_privkey_rsa(void **state) rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); + /* Test with passphrase */ + ssh_key_free(origkey); + ssh_key_free(privkey); + rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, + torture_get_testkey_passphrase(), + NULL, + NULL, + &origkey); + assert_true(rc == 0); + + unlink(LIBSSH_RSA_TESTKEY_PASSPHRASE); + rc = ssh_pki_export_privkey_file(origkey, + torture_get_testkey_passphrase(), + NULL, + NULL, + LIBSSH_RSA_TESTKEY_PASSPHRASE); + + assert_true(rc == 0); + + /* Test if import fails with invalid passwort */ + /* libcrypto asks for a passphrase if it is NULL so use invalid phrase */ + rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, + "wrong passphrase !!", + NULL, + NULL, + &privkey); + /* expect fail */ + assert_true(rc == SSH_ERROR); + + rc = ssh_pki_import_privkey_file(LIBSSH_RSA_TESTKEY_PASSPHRASE, + torture_get_testkey_passphrase(), + NULL, + NULL, + &privkey); + + rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); + assert_true(rc == 0); + ssh_key_free(origkey); ssh_key_free(privkey); } @@ -1268,7 +1324,7 @@ static void torture_pki_write_privkey_dsa(void **state) unlink(LIBSSH_DSA_TESTKEY); rc = ssh_pki_export_privkey_file(origkey, - "", + NULL, NULL, NULL, LIBSSH_DSA_TESTKEY); @@ -1284,6 +1340,44 @@ static void torture_pki_write_privkey_dsa(void **state) rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); + /* Test with passphrase */ + ssh_key_free(origkey); + ssh_key_free(privkey); + rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, + torture_get_testkey_passphrase(), + NULL, + NULL, + &origkey); + assert_true(rc == 0); + + unlink(LIBSSH_DSA_TESTKEY_PASSPHRASE); + rc = ssh_pki_export_privkey_file(origkey, + torture_get_testkey_passphrase(), + NULL, + NULL, + LIBSSH_DSA_TESTKEY_PASSPHRASE); + + assert_true(rc == 0); + + /* Test if import fails with invalid passwort */ + /* libcrypto asks for a passphrase if it is NULL so use invalid phrase */ + rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, + "wrong passphrase !!", + NULL, + NULL, + &privkey); + /* expect fail */ + assert_true(rc == SSH_ERROR); + + rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY_PASSPHRASE, + torture_get_testkey_passphrase(), + NULL, + NULL, + &privkey); + + rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); + assert_true(rc == 0); + ssh_key_free(origkey); ssh_key_free(privkey); } @@ -1309,7 +1403,7 @@ static void torture_pki_write_privkey_ecdsa(void **state) unlink(LIBSSH_ECDSA_TESTKEY); rc = ssh_pki_export_privkey_file(origkey, - "", + NULL, NULL, NULL, LIBSSH_ECDSA_TESTKEY); @@ -1325,6 +1419,44 @@ static void torture_pki_write_privkey_ecdsa(void **state) rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); + /* Test with passphrase */ + ssh_key_free(origkey); + ssh_key_free(privkey); + rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, + torture_get_testkey_passphrase(), + NULL, + NULL, + &origkey); + assert_true(rc == 0); + + unlink(LIBSSH_ECDSA_TESTKEY_PASSPHRASE); + rc = ssh_pki_export_privkey_file(origkey, + torture_get_testkey_passphrase(), + NULL, + NULL, + LIBSSH_ECDSA_TESTKEY_PASSPHRASE); + + assert_true(rc == 0); + + /* Test if import fails with invalid passwort */ + /* libcrypto asks for a passphrase if it is NULL so use invalid phrase */ + rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, + "wrong passphrase !!", + NULL, + NULL, + &privkey); + /* expect fail */ + assert_true(rc == SSH_ERROR); + + rc = ssh_pki_import_privkey_file(LIBSSH_ECDSA_TESTKEY_PASSPHRASE, + torture_get_testkey_passphrase(), + NULL, + NULL, + &privkey); + + rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); + assert_true(rc == 0); + ssh_key_free(origkey); ssh_key_free(privkey); } -- 2.2.2
From 3af5b7e3193eb3007162b0ac2fbd1e3cc8fbda9d Mon Sep 17 00:00:00 2001 From: Julian Lunz <git@xxxxxxxx> Date: Sun, 8 Feb 2015 09:56:36 +0100 Subject: [PATCH 3/3] Fix typo --- src/pki_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pki_crypto.c b/src/pki_crypto.c index 77fa14c..5b2c53c 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -542,7 +542,7 @@ int pki_key_compare(const ssh_key k1, } #endif case SSH_KEYTYPE_ED25519: - /* ed25519 keys handled globaly */ + /* ed25519 keys handled globally */ case SSH_KEYTYPE_UNKNOWN: default: return 1; -- 2.2.2
Re: Passphrase not working for ssh_pki_export_privkey_file | Julian Lunz <git@xxxxxxxx> |
Re: Passphrase not working for ssh_pki_export_privkey_file | Andreas Schneider <asn@xxxxxxxxxxxxxx> |