⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sshpubk.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* * Magic error return value for when the passphrase is wrong. */const struct ssh2_userkey ssh2_wrong_passphrase = {    NULL, NULL, NULL};const struct ssh_signkey *find_pubkey_alg(const char *name){    if (!strcmp(name, "ssh-rsa"))	return &ssh_rsa;    else if (!strcmp(name, "ssh-dss"))	return &ssh_dss;    else	return NULL;}struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,				       char *passphrase, const char **errorstr){    FILE *fp;    char header[40], *b, *encryption, *comment, *mac;    const struct ssh_signkey *alg;    struct ssh2_userkey *ret;    int cipher, cipherblk;    unsigned char *public_blob, *private_blob;    int public_blob_len, private_blob_len;    int i, is_mac, old_fmt;    int passlen = passphrase ? strlen(passphrase) : 0;    const char *error = NULL;    ret = NULL;			       /* return NULL for most errors */    encryption = comment = mac = NULL;    public_blob = private_blob = NULL;    fp = f_open(*filename, "rb");    if (!fp) {	error = "can't open file";	goto error;    }    /* Read the first header line which contains the key type. */    if (!read_header(fp, header))	goto error;    if (0 == strcmp(header, "PuTTY-User-Key-File-2")) {	old_fmt = 0;    } else if (0 == strcmp(header, "PuTTY-User-Key-File-1")) {	/* this is an old key file; warn and then continue */	old_keyfile_warning();	old_fmt = 1;    } else {	error = "not a PuTTY SSH-2 private key";	goto error;    }    error = "file format error";    if ((b = read_body(fp)) == NULL)	goto error;    /* Select key algorithm structure. */    alg = find_pubkey_alg(b);    if (!alg) {	sfree(b);	goto error;    }    sfree(b);    /* Read the Encryption header line. */    if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))	goto error;    if ((encryption = read_body(fp)) == NULL)	goto error;    if (!strcmp(encryption, "aes256-cbc")) {	cipher = 1;	cipherblk = 16;    } else if (!strcmp(encryption, "none")) {	cipher = 0;	cipherblk = 1;    } else {	sfree(encryption);	goto error;    }    /* Read the Comment header line. */    if (!read_header(fp, header) || 0 != strcmp(header, "Comment"))	goto error;    if ((comment = read_body(fp)) == NULL)	goto error;    /* Read the Public-Lines header line and the public blob. */    if (!read_header(fp, header) || 0 != strcmp(header, "Public-Lines"))	goto error;    if ((b = read_body(fp)) == NULL)	goto error;    i = atoi(b);    sfree(b);    if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL)	goto error;    /* Read the Private-Lines header line and the Private blob. */    if (!read_header(fp, header) || 0 != strcmp(header, "Private-Lines"))	goto error;    if ((b = read_body(fp)) == NULL)	goto error;    i = atoi(b);    sfree(b);    if ((private_blob = read_blob(fp, i, &private_blob_len)) == NULL)	goto error;    /* Read the Private-MAC or Private-Hash header line. */    if (!read_header(fp, header))	goto error;    if (0 == strcmp(header, "Private-MAC")) {	if ((mac = read_body(fp)) == NULL)	    goto error;	is_mac = 1;    } else if (0 == strcmp(header, "Private-Hash") &&			   alg == &ssh_rsa && old_fmt) {	if ((mac = read_body(fp)) == NULL)	    goto error;	is_mac = 0;    } else	goto error;    fclose(fp);    fp = NULL;    /*     * Decrypt the private blob.     */    if (cipher) {	unsigned char key[40];	SHA_State s;	if (!passphrase)	    goto error;	if (private_blob_len % cipherblk)	    goto error;	SHA_Init(&s);	SHA_Bytes(&s, "\0\0\0\0", 4);	SHA_Bytes(&s, passphrase, passlen);	SHA_Final(&s, key + 0);	SHA_Init(&s);	SHA_Bytes(&s, "\0\0\0\1", 4);	SHA_Bytes(&s, passphrase, passlen);	SHA_Final(&s, key + 20);	aes256_decrypt_pubkey(key, private_blob, private_blob_len);    }    /*     * Verify the MAC.     */    {	char realmac[41];	unsigned char binary[20];	unsigned char *macdata;	int maclen;	int free_macdata;	if (old_fmt) {	    /* MAC (or hash) only covers the private blob. */	    macdata = private_blob;	    maclen = private_blob_len;	    free_macdata = 0;	} else {	    unsigned char *p;	    int namelen = strlen(alg->name);	    int enclen = strlen(encryption);	    int commlen = strlen(comment);	    maclen = (4 + namelen +		      4 + enclen +		      4 + commlen +		      4 + public_blob_len +		      4 + private_blob_len);	    macdata = snewn(maclen, unsigned char);	    p = macdata;#define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)	    DO_STR(alg->name, namelen);	    DO_STR(encryption, enclen);	    DO_STR(comment, commlen);	    DO_STR(public_blob, public_blob_len);	    DO_STR(private_blob, private_blob_len);	    free_macdata = 1;	}	if (is_mac) {	    SHA_State s;	    unsigned char mackey[20];	    char header[] = "putty-private-key-file-mac-key";	    SHA_Init(&s);	    SHA_Bytes(&s, header, sizeof(header)-1);	    if (cipher && passphrase)		SHA_Bytes(&s, passphrase, passlen);	    SHA_Final(&s, mackey);	    hmac_sha1_simple(mackey, 20, macdata, maclen, binary);	    memset(mackey, 0, sizeof(mackey));	    memset(&s, 0, sizeof(s));	} else {	    SHA_Simple(macdata, maclen, binary);	}	if (free_macdata) {	    memset(macdata, 0, maclen);	    sfree(macdata);	}	for (i = 0; i < 20; i++)	    sprintf(realmac + 2 * i, "%02x", binary[i]);	if (strcmp(mac, realmac)) {	    /* An incorrect MAC is an unconditional Error if the key is	     * unencrypted. Otherwise, it means Wrong Passphrase. */	    if (cipher) {		error = "wrong passphrase";		ret = SSH2_WRONG_PASSPHRASE;	    } else {		error = "MAC failed";		ret = NULL;	    }	    goto error;	}    }    sfree(mac);    /*     * Create and return the key.     */    ret = snew(struct ssh2_userkey);    ret->alg = alg;    ret->comment = comment;    ret->data = alg->createkey(public_blob, public_blob_len,			       private_blob, private_blob_len);    if (!ret->data) {	sfree(ret->comment);	sfree(ret);	ret = NULL;	error = "createkey failed";	goto error;    }    sfree(public_blob);    sfree(private_blob);    sfree(encryption);    if (errorstr)	*errorstr = NULL;    return ret;    /*     * Error processing.     */  error:    if (fp)	fclose(fp);    if (comment)	sfree(comment);    if (encryption)	sfree(encryption);    if (mac)	sfree(mac);    if (public_blob)	sfree(public_blob);    if (private_blob)	sfree(private_blob);    if (errorstr)	*errorstr = error;    return ret;}char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,			   int *pub_blob_len, const char **errorstr){    FILE *fp;    char header[40], *b;    const struct ssh_signkey *alg;    unsigned char *public_blob;    int public_blob_len;    int i;    const char *error = NULL;    public_blob = NULL;    fp = f_open(*filename, "rb");    if (!fp) {	error = "can't open file";	goto error;    }    /* Read the first header line which contains the key type. */    if (!read_header(fp, header)	|| (0 != strcmp(header, "PuTTY-User-Key-File-2") &&	    0 != strcmp(header, "PuTTY-User-Key-File-1"))) {	error = "not a PuTTY SSH-2 private key";	goto error;    }    error = "file format error";    if ((b = read_body(fp)) == NULL)	goto error;    /* Select key algorithm structure. Currently only ssh-rsa. */    alg = find_pubkey_alg(b);    if (!alg) {	sfree(b);	goto error;    }    sfree(b);    /* Read the Encryption header line. */    if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))	goto error;    if ((b = read_body(fp)) == NULL)	goto error;    sfree(b);			       /* we don't care */    /* Read the Comment header line. */    if (!read_header(fp, header) || 0 != strcmp(header, "Comment"))	goto error;    if ((b = read_body(fp)) == NULL)	goto error;    sfree(b);			       /* we don't care */    /* Read the Public-Lines header line and the public blob. */    if (!read_header(fp, header) || 0 != strcmp(header, "Public-Lines"))	goto error;    if ((b = read_body(fp)) == NULL)	goto error;    i = atoi(b);    sfree(b);    if ((public_blob = read_blob(fp, i, &public_blob_len)) == NULL)	goto error;    fclose(fp);    if (pub_blob_len)	*pub_blob_len = public_blob_len;    if (algorithm)	*algorithm = alg->name;    return (char *)public_blob;    /*     * Error processing.     */  error:    if (fp)	fclose(fp);    if (public_blob)	sfree(public_blob);    if (errorstr)	*errorstr = error;    return NULL;}int ssh2_userkey_encrypted(const Filename *filename, char **commentptr){    FILE *fp;    char header[40], *b, *comment;    int ret;    if (commentptr)	*commentptr = NULL;    fp = f_open(*filename, "rb");    if (!fp)	return 0;    if (!read_header(fp, header)	|| (0 != strcmp(header, "PuTTY-User-Key-File-2") &&	    0 != strcmp(header, "PuTTY-User-Key-File-1"))) {	fclose(fp);	return 0;    }    if ((b = read_body(fp)) == NULL) {	fclose(fp);	return 0;    }    sfree(b);			       /* we don't care about key type here */    /* Read the Encryption header line. */    if (!read_header(fp, header) || 0 != strcmp(header, "Encryption")) {	fclose(fp);	return 0;    }    if ((b = read_body(fp)) == NULL) {	fclose(fp);	return 0;    }    /* Read the Comment header line. */    if (!read_header(fp, header) || 0 != strcmp(header, "Comment")) {	fclose(fp);	sfree(b);	return 1;    }    if ((comment = read_body(fp)) == NULL) {	fclose(fp);	sfree(b);	return 1;    }    if (commentptr)	*commentptr = comment;    fclose(fp);    if (!strcmp(b, "aes256-cbc"))	ret = 1;    else	ret = 0;    sfree(b);    return ret;}int base64_lines(int datalen){    /* When encoding, we use 64 chars/line, which equals 48 real chars. */    return (datalen + 47) / 48;}void base64_encode(FILE * fp, unsigned char *data, int datalen, int cpl){    int linelen = 0;    char out[4];    int n, i;    while (datalen > 0) {	n = (datalen < 3 ? datalen : 3);	base64_encode_atom(data, n, out);	data += n;	datalen -= n;	for (i = 0; i < 4; i++) {	    if (linelen >= cpl) {		linelen = 0;		fputc('\n', fp);	    }	    fputc(out[i], fp);	    linelen++;	}    }    fputc('\n', fp);}int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,		      char *passphrase){    FILE *fp;    unsigned char *pub_blob, *priv_blob, *priv_blob_encrypted;    int pub_blob_len, priv_blob_len, priv_encrypted_len;    int passlen;    int cipherblk;    int i;    char *cipherstr;    unsigned char priv_mac[20];    /*     * Fetch the key component blobs.     */    pub_blob = key->alg->public_blob(key->data, &pub_blob_len);    priv_blob = key->alg->private_blob(key->data, &priv_blob_len);    if (!pub_blob || !priv_blob) {	sfree(pub_blob);	sfree(priv_blob);	return 0;    }    /*     * Determine encryption details, and encrypt the private blob.     */    if (passphrase) {	cipherstr = "aes256-cbc";	cipherblk = 16;    } else {	cipherstr = "none";	cipherblk = 1;    }    priv_encrypted_len = priv_blob_len + cipherblk - 1;    priv_encrypted_len -= priv_encrypted_len % cipherblk;    priv_blob_encrypted = snewn(priv_encrypted_len, unsigned char);    memset(priv_blob_encrypted, 0, priv_encrypted_len);    memcpy(priv_blob_encrypted, priv_blob, priv_blob_len);    /* Create padding based on the SHA hash of the unpadded blob. This prevents     * too easy a known-plaintext attack on the last block. */    SHA_Simple(priv_blob, priv_blob_len, priv_mac);    assert(priv_encrypted_len - priv_blob_len < 20);    memcpy(priv_blob_encrypted + priv_blob_len, priv_mac,	   priv_encrypted_len - priv_blob_len);    /* Now create the MAC. */    {	unsigned char *macdata;	int maclen;	unsigned char *p;	int namelen = strlen(key->alg->name);	int enclen = strlen(cipherstr);	int commlen = strlen(key->comment);	SHA_State s;	unsigned char mackey[20];	char header[] = "putty-private-key-file-mac-key";	maclen = (4 + namelen +		  4 + enclen +		  4 + commlen +		  4 + pub_blob_len +		  4 + priv_encrypted_len);	macdata = snewn(maclen, unsigned char);	p = macdata;#define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)	DO_STR(key->alg->name, namelen);	DO_STR(cipherstr, enclen);	DO_STR(key->comment, commlen);	DO_STR(pub_blob, pub_blob_len);	DO_STR(priv_blob_encrypted, priv_encrypted_len);	SHA_Init(&s);	SHA_Bytes(&s, header, sizeof(header)-1);	if (passphrase)	    SHA_Bytes(&s, passphrase, strlen(passphrase));	SHA_Final(&s, mackey);	hmac_sha1_simple(mackey, 20, macdata, maclen, priv_mac);	memset(macdata, 0, maclen);	sfree(macdata);	memset(mackey, 0, sizeof(mackey));	memset(&s, 0, sizeof(s));    }    if (passphrase) {	unsigned char key[40];	SHA_State s;	passlen = strlen(passphrase);	SHA_Init(&s);	SHA_Bytes(&s, "\0\0\0\0", 4);	SHA_Bytes(&s, passphrase, passlen);	SHA_Final(&s, key + 0);	SHA_Init(&s);	SHA_Bytes(&s, "\0\0\0\1", 4);	SHA_Bytes(&s, passphrase, passlen);	SHA_Final(&s, key + 20);	aes256_encrypt_pubkey(key, priv_blob_encrypted,			      priv_encrypted_len);	memset(key, 0, sizeof(key));	memset(&s, 0, sizeof(s));    }    fp = f_open(*filename, "w");    if (!fp)	return 0;    fprintf(fp, "PuTTY-User-Key-File-2: %s\n", key->alg->name);    fprintf(fp, "Encryption: %s\n", cipherstr);    fprintf(fp, "Comment: %s\n", key->comment);    fprintf(fp, "Public-Lines: %d\n", base64_lines(pub_blob_len));    base64_encode(fp, pub_blob, pub_blob_len, 64);    fprintf(fp, "Private-Lines: %d\n", base64_lines(priv_encrypted_len));    base64_encode(fp, priv_blob_encrypted, priv_encrypted_len, 64);    fprintf(fp, "Private-MAC: ");    for (i = 0; i < 20; i++)	fprintf(fp, "%02x", priv_mac[i]);    fprintf(fp, "\n");    fclose(fp);    sfree(pub_blob);    memset(priv_blob, 0, priv_blob_len);    sfree(priv_blob);    sfree(priv_blob_encrypted);    return 1;}/* ---------------------------------------------------------------------- * A function to determine the type of a private key file. Returns * 0 on failure, 1 or 2 on success. */int key_type(const Filename *filename){    FILE *fp;    char buf[32];    const char putty2_sig[] = "PuTTY-User-Key-File-";    const char sshcom_sig[] = "---- BEGIN SSH2 ENCRYPTED PRIVAT";    const char openssh_sig[] = "-----BEGIN ";    int i;    fp = f_open(*filename, "r");    if (!fp)	return SSH_KEYTYPE_UNOPENABLE;    i = fread(buf, 1, sizeof(buf), fp);    fclose(fp);    if (i < 0)	return SSH_KEYTYPE_UNOPENABLE;    if (i < 32)	return SSH_KEYTYPE_UNKNOWN;    if (!memcmp(buf, rsa_signature, sizeof(rsa_signature)-1))	return SSH_KEYTYPE_SSH1;    if (!memcmp(buf, putty2_sig, sizeof(putty2_sig)-1))	return SSH_KEYTYPE_SSH2;    if (!memcmp(buf, openssh_sig, sizeof(openssh_sig)-1))	return SSH_KEYTYPE_OPENSSH;    if (!memcmp(buf, sshcom_sig, sizeof(sshcom_sig)-1))	return SSH_KEYTYPE_SSHCOM;    return SSH_KEYTYPE_UNKNOWN;	       /* unrecognised or EOF */}/* * Convert the type word to a string, for `wrong type' error * messages. */char *key_type_to_str(int type){    switch (type) {      case SSH_KEYTYPE_UNOPENABLE: return "unable to open file"; break;      case SSH_KEYTYPE_UNKNOWN: return "not a private key"; break;      case SSH_KEYTYPE_SSH1: return "SSH1 private key"; break;      case SSH_KEYTYPE_SSH2: return "PuTTY SSH2 private key"; break;      case SSH_KEYTYPE_OPENSSH: return "OpenSSH SSH2 private key"; break;      case SSH_KEYTYPE_SSHCOM: return "ssh.com SSH2 private key"; break;      default: return "INTERNAL ERROR"; break;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -