svnno****@sourc*****
svnno****@sourc*****
2011年 2月 20日 (日) 00:37:07 JST
Revision: 4325 http://sourceforge.jp/projects/ttssh2/svn/view?view=rev&revision=4325 Author: maya Date: 2011-02-20 00:37:07 +0900 (Sun, 20 Feb 2011) Log Message: ----------- ECDSA ã®éµãä½ããããã«ãã Modified Paths: -------------- trunk/doc/en/html/menu/setup-sshkeygenerator.html trunk/doc/ja/html/menu/setup-sshkeygenerator.html trunk/ttssh2/ttxssh/key.h trunk/ttssh2/ttxssh/resource.h trunk/ttssh2/ttxssh/ttxssh.c trunk/ttssh2/ttxssh/ttxssh.rc -------------- next part -------------- Modified: trunk/doc/en/html/menu/setup-sshkeygenerator.html =================================================================== --- trunk/doc/en/html/menu/setup-sshkeygenerator.html 2011-02-19 11:07:05 UTC (rev 4324) +++ trunk/doc/en/html/menu/setup-sshkeygenerator.html 2011-02-19 15:37:07 UTC (rev 4325) @@ -29,6 +29,15 @@ <dt>DSA</dt> <dd>Generate SSH2 DSA key.</dd> + + <dt>ECDSA-256</dt> + <dd>Generate SSH2 ECDSA(256bit) key.</dd> + + <dt>ECDSA-384</dt> + <dd>Generate SSH2 ECDSA(384bit) key.</dd> + + <dt>ECDSA-521</dt> + <dd>Generate SSH2 ECDSA(521bit) key.</dd> </dl> </dd> Modified: trunk/doc/ja/html/menu/setup-sshkeygenerator.html =================================================================== --- trunk/doc/ja/html/menu/setup-sshkeygenerator.html 2011-02-19 11:07:05 UTC (rev 4324) +++ trunk/doc/ja/html/menu/setup-sshkeygenerator.html 2011-02-19 15:37:07 UTC (rev 4325) @@ -29,6 +29,15 @@ <dt>DSA</dt> <dd>SSH2p DSA®ð¶¬µÜ·B</dd> + + <dt>ECDSA-256</dt> + <dd>SSH2p ECDSA(256bit)®ð¶¬µÜ·B</dd> + + <dt>ECDSA-384</dt> + <dd>SSH2p ECDSA(384bit)®ð¶¬µÜ·B</dd> + + <dt>ECDSA-521</dt> + <dd>SSH2p ECDSA(521bit)®ð¶¬µÜ·B</dd> </dl> </dd> Modified: trunk/ttssh2/ttxssh/key.h =================================================================== --- trunk/ttssh2/ttxssh/key.h 2011-02-19 11:07:05 UTC (rev 4324) +++ trunk/ttssh2/ttxssh/key.h 2011-02-19 15:37:07 UTC (rev 4325) @@ -41,6 +41,7 @@ char *get_sshname_from_keytype(enum ssh_keytype type); char *get_sshname_from_key(Key *key); enum hostkey_type get_keytype_from_name(char *name); +char *curve_keytype_to_name(enum ssh_keytype type); void key_free(Key *key); int key_to_blob(Key *key, char **blobp, int *lenp); Modified: trunk/ttssh2/ttxssh/resource.h =================================================================== --- trunk/ttssh2/ttxssh/resource.h 2011-02-19 11:07:05 UTC (rev 4324) +++ trunk/ttssh2/ttxssh/resource.h 2011-02-19 15:37:07 UTC (rev 4325) @@ -94,11 +94,14 @@ #define IDC_SAVE_PRIBATE_KEY 1066 #define IDC_SAVE_PRIVATE_KEY 1066 #define IDC_ZLIB_VERSION 1067 +#define IDC_ECDSA256_TYPE 1067 #define IDC_HISTORY_LABEL 1068 +#define IDC_ECDSA384_TYPE 1068 #define IDC_EDIT1 1069 #define IDC_FINGER_PRINT 1069 #define IDC_SENDFILE_EDIT 1069 #define IDC_PASSWD 1069 +#define IDC_ECDSA521_TYPE 1069 #define IDC_STATIC1 1070 #define IDC_COMPRESSLABEL 1070 #define IDC_SSHVERSIONS 1070 Modified: trunk/ttssh2/ttxssh/ttxssh.c =================================================================== --- trunk/ttssh2/ttxssh/ttxssh.c 2011-02-19 11:07:05 UTC (rev 4324) +++ trunk/ttssh2/ttxssh/ttxssh.c 2011-02-19 15:37:07 UTC (rev 4325) @@ -2861,18 +2861,20 @@ typedef struct { RSA *rsa; DSA *dsa; + EC_KEY *ecdsa; enum ssh_keytype type; } ssh_private_key_t; -static ssh_private_key_t private_key = {NULL, NULL, KEY_UNSPEC}; +static ssh_private_key_t private_key = {NULL, NULL, NULL, KEY_UNSPEC}; typedef struct { RSA *rsa; DSA *dsa; + EC_KEY *ecdsa; enum ssh_keytype type; } ssh_public_key_t; -static ssh_public_key_t public_key = {NULL, NULL, KEY_UNSPEC}; +static ssh_public_key_t public_key = {NULL, NULL, NULL, KEY_UNSPEC}; static void free_ssh_key(void) { @@ -2887,6 +2889,11 @@ RSA_free(public_key.rsa); public_key.rsa = NULL; + EC_KEY_free(private_key.ecdsa); + private_key.ecdsa = NULL; + EC_KEY_free(public_key.ecdsa); + public_key.ecdsa = NULL; + private_key.type = KEY_UNSPEC; public_key.type = KEY_UNSPEC; } @@ -2896,7 +2903,10 @@ // if SSH key already is generated, should free the resource. free_ssh_key(); - if (type == KEY_RSA1 || type == KEY_RSA) { + switch (type) { + case KEY_RSA1: + case KEY_RSA: + { RSA *priv = NULL; RSA *pub = NULL; @@ -2918,8 +2928,11 @@ BN_copy(pub->n, priv->n); BN_copy(pub->e, priv->e); public_key.rsa = pub; - - } else if (type == KEY_DSA) { + break; + } + + case KEY_DSA: + { DSA *priv = NULL; DSA *pub = NULL; @@ -2951,8 +2964,51 @@ BN_copy(pub->g, priv->g); BN_copy(pub->pub_key, priv->pub_key); public_key.dsa = pub; + break; + } - } else { + case KEY_ECDSA256: + case KEY_ECDSA384: + case KEY_ECDSA521: + { + EC_KEY *priv = NULL; + EC_KEY *pub = NULL; + + switch (type) { + case KEY_ECDSA256: + priv = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + pub = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + break; + case KEY_ECDSA384: + priv = EC_KEY_new_by_curve_name(NID_secp384r1); + pub = EC_KEY_new_by_curve_name(NID_secp384r1); + break; + case KEY_ECDSA521: + priv = EC_KEY_new_by_curve_name(NID_secp521r1); + pub = EC_KEY_new_by_curve_name(NID_secp521r1); + break; + } + if (priv == NULL || pub == NULL) { + goto error; + } + + // private key + if (EC_KEY_generate_key(priv) != 1) { + goto error; + } + EC_KEY_set_asn1_flag(priv, OPENSSL_EC_NAMED_CURVE); + private_key.ecdsa = priv; + + // public key + if (EC_KEY_set_public_key(pub, EC_KEY_get0_public_key(priv)) != 1) { + goto error; + } + public_key.ecdsa = pub; + + break; + } + + default: goto error; } @@ -3480,6 +3536,9 @@ SendDlgItemMessage(dlg, IDC_RSA1_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); SendDlgItemMessage(dlg, IDC_RSA_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); SendDlgItemMessage(dlg, IDC_DSA_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); + SendDlgItemMessage(dlg, IDC_ECDSA256_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); + SendDlgItemMessage(dlg, IDC_ECDSA384_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); + SendDlgItemMessage(dlg, IDC_ECDSA521_TYPE, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); SendDlgItemMessage(dlg, IDC_KEYBITS_LABEL, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); SendDlgItemMessage(dlg, IDC_KEYBITS, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); SendDlgItemMessage(dlg, IDC_KEY_LABEL, WM_SETFONT, (WPARAM)DlgKeygenFont, MAKELPARAM(TRUE,0)); @@ -3526,6 +3585,31 @@ cbarg.type = key_type; cbarg.dlg = dlg; + bits = GetDlgItemInt(dlg, IDC_KEYBITS, NULL, FALSE); + + switch (key_type) { + case KEY_RSA1: + case KEY_RSA: + case KEY_DSA: + if (bits < ((key_type==KEY_DSA)?SSH_DSA_MINIMUM_KEY_SIZE:SSH_RSA_MINIMUM_KEY_SIZE)) { + UTIL_get_lang_msg("MSG_KEYBITS_MIN_ERROR", pvar, + "The key bits is too small."); + MessageBox(dlg, pvar->ts->UIMsg, + "Tera Term", MB_OK | MB_ICONEXCLAMATION); + return TRUE; + } + break; + case KEY_ECDSA256: + SetDlgItemInt(dlg, IDC_KEYBITS, 256, FALSE); + break; + case KEY_ECDSA384: + SetDlgItemInt(dlg, IDC_KEYBITS, 384, FALSE); + break; + case KEY_ECDSA521: + SetDlgItemInt(dlg, IDC_KEYBITS, 521, FALSE); + break; + } + // passphrase edit box disabled(default) EnableWindow(GetDlgItem(dlg, IDC_KEY_EDIT), FALSE); EnableWindow(GetDlgItem(dlg, IDC_CONFIRM_EDIT), FALSE); @@ -3537,20 +3621,13 @@ EnableWindow(GetDlgItem(dlg, IDC_RSA1_TYPE), FALSE); EnableWindow(GetDlgItem(dlg, IDC_RSA_TYPE), FALSE); EnableWindow(GetDlgItem(dlg, IDC_DSA_TYPE), FALSE); + EnableWindow(GetDlgItem(dlg, IDC_ECDSA256_TYPE), FALSE); + EnableWindow(GetDlgItem(dlg, IDC_ECDSA384_TYPE), FALSE); + EnableWindow(GetDlgItem(dlg, IDC_ECDSA521_TYPE), FALSE); EnableWindow(GetDlgItem(dlg, IDC_KEYBITS), FALSE); EnableWindow(GetDlgItem(dlg, IDOK), FALSE); EnableWindow(GetDlgItem(dlg, IDCANCEL), FALSE); - bits = GetDlgItemInt(dlg, IDC_KEYBITS, NULL, FALSE); - - if (bits < ((key_type==KEY_DSA)?SSH_DSA_MINIMUM_KEY_SIZE:SSH_RSA_MINIMUM_KEY_SIZE)) { - UTIL_get_lang_msg("MSG_KEYBITS_MIN_ERROR", pvar, - "The key bits is too small."); - MessageBox(dlg, pvar->ts->UIMsg, - "Tera Term", MB_OK | MB_ICONEXCLAMATION); - return TRUE; - } - if (generate_ssh_key(key_type, bits, keygen_progress, &cbarg)) { MSG msg; int c = 0; @@ -3574,6 +3651,9 @@ EnableWindow(GetDlgItem(dlg, IDC_RSA1_TYPE), TRUE); EnableWindow(GetDlgItem(dlg, IDC_RSA_TYPE), TRUE); EnableWindow(GetDlgItem(dlg, IDC_DSA_TYPE), TRUE); + EnableWindow(GetDlgItem(dlg, IDC_ECDSA256_TYPE), TRUE); + EnableWindow(GetDlgItem(dlg, IDC_ECDSA384_TYPE), TRUE); + EnableWindow(GetDlgItem(dlg, IDC_ECDSA521_TYPE), TRUE); EnableWindow(GetDlgItem(dlg, IDC_KEYBITS), TRUE); EnableWindow(GetDlgItem(dlg, IDOK), TRUE); EnableWindow(GetDlgItem(dlg, IDCANCEL), TRUE); @@ -3606,6 +3686,21 @@ key_type = KEY_DSA; break; + case IDC_ECDSA256_TYPE | (BN_CLICKED << 16): + key_type = KEY_ECDSA256; + SetDlgItemInt(dlg, IDC_KEYBITS, 256, FALSE); + break; + + case IDC_ECDSA384_TYPE | (BN_CLICKED << 16): + key_type = KEY_ECDSA384; + SetDlgItemInt(dlg, IDC_KEYBITS, 384, FALSE); + break; + + case IDC_ECDSA521_TYPE | (BN_CLICKED << 16): + key_type = KEY_ECDSA521; + SetDlgItemInt(dlg, IDC_KEYBITS, 521, FALSE); + break; + // saving public key file case IDC_SAVE_PUBLIC_KEY: { @@ -3621,24 +3716,37 @@ ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = dlg; - if (public_key.type == KEY_RSA1) { + switch (public_key.type) { + case KEY_RSA1: UTIL_get_lang_msg("FILEDLG_SAVE_PUBLICKEY_RSA1_FILTER", pvar, "SSH1 RSA key(identity.pub)\\0identity.pub\\0All Files(*.*)\\0*.*\\0\\0"); memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg)); ofn.lpstrFilter = uimsg; strncpy_s(filename, sizeof(filename), "identity.pub", _TRUNCATE); - } else if (public_key.type == KEY_RSA) { + break; + case KEY_RSA: UTIL_get_lang_msg("FILEDLG_SAVE_PUBLICKEY_RSA_FILTER", pvar, "SSH2 RSA key(id_rsa.pub)\\0id_rsa.pub\\0All Files(*.*)\\0*.*\\0\\0"); memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg)); ofn.lpstrFilter = uimsg; strncpy_s(filename, sizeof(filename), "id_rsa.pub", _TRUNCATE); - } else { + break; + case KEY_DSA: UTIL_get_lang_msg("FILEDLG_SAVE_PUBLICKEY_DSA_FILTER", pvar, "SSH2 DSA key(id_dsa.pub)\\0id_dsa.pub\\0All Files(*.*)\\0*.*\\0\\0"); memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg)); ofn.lpstrFilter = uimsg; strncpy_s(filename, sizeof(filename), "id_dsa.pub", _TRUNCATE); + break; + case KEY_ECDSA256: + case KEY_ECDSA384: + case KEY_ECDSA521: + UTIL_get_lang_msg("FILEDLG_SAVE_PUBLICKEY_ECDSA_FILTER", pvar, + "SSH2 ECDSA key(id_ecdsa.pub)\\0id_ecdsa.pub\\0All Files(*.*)\\0*.*\\0\\0"); + memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg)); + ofn.lpstrFilter = uimsg; + strncpy_s(filename, sizeof(filename), "id_ecdsa.pub", _TRUNCATE); + break; } ofn.lpstrFile = filename; ofn.nMaxFile = sizeof(filename); @@ -3679,11 +3787,12 @@ fprintf(fp, " %s", buf); OPENSSL_free(buf); - } else { // SSH2 RSA, DSA + } else { // SSH2 RSA, DSA, ECDSA buffer_t *b; - char *keyname; + char *keyname, *s; DSA *dsa = public_key.dsa; RSA *rsa = public_key.rsa; + EC_KEY *ecdsa = public_key.ecdsa; int len; char *blob; char *uuenc; // uuencode data @@ -3693,19 +3802,33 @@ if (b == NULL) goto public_error; - if (public_key.type == KEY_DSA) { // DSA + switch (public_key.type) { + case KEY_DSA: // DSA keyname = "ssh-dss"; buffer_put_string(b, keyname, strlen(keyname)); buffer_put_bignum2(b, dsa->p); buffer_put_bignum2(b, dsa->q); buffer_put_bignum2(b, dsa->g); buffer_put_bignum2(b, dsa->pub_key); + break; - } else { // RSA + case KEY_RSA: // RSA keyname = "ssh-rsa"; buffer_put_string(b, keyname, strlen(keyname)); buffer_put_bignum2(b, rsa->e); buffer_put_bignum2(b, rsa->n); + break; + + case KEY_ECDSA256: // ECDSA + case KEY_ECDSA384: + case KEY_ECDSA521: + keyname = get_sshname_from_keytype(public_key.type); + buffer_put_string(b, keyname, strlen(keyname)); + s = curve_keytype_to_name(public_key.type); + buffer_put_string(b, s, strlen(s)); + buffer_put_ecpoint(b, EC_KEY_get0_group(ecdsa), + EC_KEY_get0_public_key(ecdsa)); + break; } blob = buffer_ptr(b); @@ -3773,24 +3896,37 @@ ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = dlg; - if (private_key.type == KEY_RSA1) { + switch (private_key.type) { + case KEY_RSA1: UTIL_get_lang_msg("FILEDLG_SAVE_PRIVATEKEY_RSA1_FILTER", pvar, "SSH1 RSA key(identity)\\0identity\\0All Files(*.*)\\0*.*\\0\\0"); memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg)); ofn.lpstrFilter = uimsg; strncpy_s(filename, sizeof(filename), "identity", _TRUNCATE); - } else if (private_key.type == KEY_RSA) { + break; + case KEY_RSA: UTIL_get_lang_msg("FILEDLG_SAVE_PRIVATEKEY_RSA_FILTER", pvar, "SSH2 RSA key(id_rsa)\\0id_rsa\\0All Files(*.*)\\0*.*\\0\\0"); memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg)); ofn.lpstrFilter = uimsg; strncpy_s(filename, sizeof(filename), "id_rsa", _TRUNCATE); - } else { + break; + case KEY_DSA: UTIL_get_lang_msg("FILEDLG_SAVE_PRIVATEKEY_DSA_FILTER", pvar, "SSH2 DSA key(id_dsa)\\0id_dsa\\0All Files(*.*)\\0*.*\\0\\0"); memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg)); ofn.lpstrFilter = uimsg; strncpy_s(filename, sizeof(filename), "id_dsa", _TRUNCATE); + break; + case KEY_ECDSA256: + case KEY_ECDSA384: + case KEY_ECDSA521: + UTIL_get_lang_msg("FILEDLG_SAVE_PRIVATEKEY_ECDSA_FILTER", pvar, + "SSH2 ECDSA key(id_ecdsa)\\0id_ecdsa\\0All Files(*.*)\\0*.*\\0\\0"); + memcpy(uimsg, pvar->ts->UIMsg, sizeof(uimsg)); + ofn.lpstrFilter = uimsg; + strncpy_s(filename, sizeof(filename), "id_ecdsa", _TRUNCATE); + break; } ofn.lpstrFile = filename; ofn.nMaxFile = sizeof(filename); @@ -3920,7 +4056,7 @@ buffer_free(b); buffer_free(enc); - } else { // SSH2 RSA, DSA + } else { // SSH2 RSA, DSA, ECDSA int len; FILE *fp; const EVP_CIPHER *cipher; @@ -3942,11 +4078,19 @@ MessageBox(dlg, uimsg, pvar->ts->UIMsg, MB_OK | MB_ICONEXCLAMATION); break; } - - if (key_type == KEY_RSA) { // RSA + + switch (key_type) { + case KEY_RSA: // RSA ret = PEM_write_RSAPrivateKey(fp, private_key.rsa, cipher, buf, len, NULL, NULL); - } else { // DSA + break; + case KEY_DSA: // DSA ret = PEM_write_DSAPrivateKey(fp, private_key.dsa, cipher, buf, len, NULL, NULL); + break; + case KEY_ECDSA256: // ECDSA + case KEY_ECDSA384: + case KEY_ECDSA521: + ret = PEM_write_ECPrivateKey(fp, private_key.ecdsa, cipher, buf, len, NULL, NULL); + break; } if (ret == 0) { UTIL_get_lang_msg("MSG_SAVE_KEY_WRITEFILE_ERROR", pvar, Modified: trunk/ttssh2/ttxssh/ttxssh.rc =================================================================== --- trunk/ttssh2/ttxssh/ttxssh.rc 2011-02-19 11:07:05 UTC (rev 4324) +++ trunk/ttssh2/ttxssh/ttxssh.rc 2011-02-19 15:37:07 UTC (rev 4325) @@ -295,19 +295,22 @@ BEGIN DEFPUSHBUTTON "&Generate",IDOK,199,7,50,14 PUSHBUTTON "Cancel",IDCANCEL,199,24,50,14 - GROUPBOX "Key type",IDC_KEYTYPE,11,7,104,26 - CONTROL "RS&A1",IDC_RSA1_TYPE,"Button",BS_AUTORADIOBUTTON,17,18,30,10 - CONTROL "&RSA",IDC_RSA_TYPE,"Button",BS_AUTORADIOBUTTON,52,18,25,10 - CONTROL "&DSA",IDC_DSA_TYPE,"Button",BS_AUTORADIOBUTTON,82,18,25,10 - RTEXT "Key &Bits:",IDC_KEYBITS_LABEL,120,18,40,10,NOT WS_GROUP - EDITTEXT IDC_KEYBITS,165,16,25,12,ES_AUTOHSCROLL | ES_NUMBER | WS_GROUP - LTEXT "",IDC_KEYGEN_PROGRESS_LABEL,40,40,172,8 - RTEXT "Key passphrase:",IDC_KEY_LABEL,14,58,80,8 - RTEXT "Confirm passphrase:",IDC_CONFIRM_LABEL,14,76,80,8 - EDITTEXT IDC_KEY_EDIT,100,56,108,12,ES_PASSWORD | ES_AUTOHSCROLL - EDITTEXT IDC_CONFIRM_EDIT,100,74,108,12,ES_PASSWORD | ES_AUTOHSCROLL - PUSHBUTTON "Save publi&c key",IDC_SAVE_PUBLIC_KEY,49,96,68,14 - PUSHBUTTON "Save &private key",IDC_SAVE_PRIVATE_KEY,133,96,68,14 + GROUPBOX "Key type",IDC_KEYTYPE,11,7,115,47 + CONTROL "RS&A1",IDC_RSA1_TYPE,"Button",BS_AUTORADIOBUTTON,17,17,30,10 + CONTROL "&RSA",IDC_RSA_TYPE,"Button",BS_AUTORADIOBUTTON,52,17,25,10 + CONTROL "&DSA",IDC_DSA_TYPE,"Button",BS_AUTORADIOBUTTON,82,17,25,10 + CONTROL "ECDSA-&256",IDC_ECDSA256_TYPE,"Button",BS_AUTORADIOBUTTON,17,29,50,10 + CONTROL "ECDSA-&384",IDC_ECDSA384_TYPE,"Button",BS_AUTORADIOBUTTON,70,29,50,10 + CONTROL "ECDSA-&521",IDC_ECDSA521_TYPE,"Button",BS_AUTORADIOBUTTON,17,41,50,10 + RTEXT "Key &Bits:",IDC_KEYBITS_LABEL,143,14,40,10,NOT WS_GROUP + EDITTEXT IDC_KEYBITS,155,26,25,12,ES_AUTOHSCROLL | ES_NUMBER | WS_GROUP + LTEXT "",IDC_KEYGEN_PROGRESS_LABEL,40,56,172,8 + RTEXT "Key passphrase:",IDC_KEY_LABEL,14,71,80,8 + RTEXT "Confirm passphrase:",IDC_CONFIRM_LABEL,14,86,80,8 + EDITTEXT IDC_KEY_EDIT,100,69,108,12,ES_PASSWORD | ES_AUTOHSCROLL + EDITTEXT IDC_CONFIRM_EDIT,100,85,108,12,ES_PASSWORD | ES_AUTOHSCROLL + PUSHBUTTON "Save publi&c key",IDC_SAVE_PUBLIC_KEY,49,103,68,14 + PUSHBUTTON "Save &private key",IDC_SAVE_PRIVATE_KEY,133,103,68,14 END IDD_SSHSCP DIALOGEX 0, 0, 279, 125