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

📄 import.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 4 页
字号:
                    len = base64_decode_atom(base64_bit, out);                    if (len <= 0) {                        errmsg = "Invalid base64 encoding";                        goto error;                    }                    if (ret->keyblob_len + len > ret->keyblob_size) {                        ret->keyblob_size = ret->keyblob_len + len + 256;                        ret->keyblob = sresize(ret->keyblob, ret->keyblob_size,					       unsigned char);                    }                    memcpy(ret->keyblob + ret->keyblob_len, out, len);                    ret->keyblob_len += len;                    memset(out, 0, sizeof(out));                }		p++;	    }	}    }    if (ret->keyblob_len == 0 || !ret->keyblob) {	errmsg = "Key body not present";	goto error;    }    if (ret->encrypted && ret->keyblob_len % 8 != 0) {	errmsg = "Encrypted key blob is not a multiple of cipher block size";	goto error;    }    memset(buffer, 0, sizeof(buffer));    memset(base64_bit, 0, sizeof(base64_bit));    return ret;    error:    memset(buffer, 0, sizeof(buffer));    memset(base64_bit, 0, sizeof(base64_bit));    if (ret) {	if (ret->keyblob) {            memset(ret->keyblob, 0, ret->keyblob_size);            sfree(ret->keyblob);        }        memset(&ret, 0, sizeof(ret));	sfree(ret);    }    return NULL;}int openssh_encrypted(const Filename *filename){    struct openssh_key *key = load_openssh_key(filename);    int ret;    if (!key)	return 0;    ret = key->encrypted;    memset(key->keyblob, 0, key->keyblob_size);    sfree(key->keyblob);    memset(&key, 0, sizeof(key));    sfree(key);    return ret;}struct ssh2_userkey *openssh_read(const Filename *filename, char *passphrase){    struct openssh_key *key = load_openssh_key(filename);    struct ssh2_userkey *retkey;    unsigned char *p;    int ret, id, len, flags;    int i, num_integers;    struct ssh2_userkey *retval = NULL;    char *errmsg;    unsigned char *blob;    int blobsize = 0, blobptr, privptr;    char *modptr = NULL;    int modlen = 0;    blob = NULL;    if (!key)	return NULL;    if (key->encrypted) {	/*	 * Derive encryption key from passphrase and iv/salt:	 * 	 *  - let block A equal MD5(passphrase || iv)	 *  - let block B equal MD5(A || passphrase || iv)	 *  - block C would be MD5(B || passphrase || iv) and so on	 *  - encryption key is the first N bytes of A || B	 */	struct MD5Context md5c;	unsigned char keybuf[32];	MD5Init(&md5c);	MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));	MD5Update(&md5c, (unsigned char *)key->iv, 8);	MD5Final(keybuf, &md5c);	MD5Init(&md5c);	MD5Update(&md5c, keybuf, 16);	MD5Update(&md5c, (unsigned char *)passphrase, strlen(passphrase));	MD5Update(&md5c, (unsigned char *)key->iv, 8);	MD5Final(keybuf+16, &md5c);	/*	 * Now decrypt the key blob.	 */	des3_decrypt_pubkey_ossh(keybuf, (unsigned char *)key->iv,				 key->keyblob, key->keyblob_len);        memset(&md5c, 0, sizeof(md5c));        memset(keybuf, 0, sizeof(keybuf));    }    /*     * Now we have a decrypted key blob, which contains an ASN.1     * encoded private key. We must now untangle the ASN.1.     *     * We expect the whole key blob to be formatted as a SEQUENCE     * (0x30 followed by a length code indicating that the rest of     * the blob is part of the sequence). Within that SEQUENCE we     * expect to see a bunch of INTEGERs. What those integers mean     * depends on the key type:     *     *  - For RSA, we expect the integers to be 0, n, e, d, p, q,     *    dmp1, dmq1, iqmp in that order. (The last three are d mod     *    (p-1), d mod (q-1), inverse of q mod p respectively.)     *     *  - For DSA, we expect them to be 0, p, q, g, y, x in that     *    order.     */        p = key->keyblob;    /* Expect the SEQUENCE header. Take its absence as a failure to decrypt. */    ret = ber_read_id_len(p, key->keyblob_len, &id, &len, &flags);    p += ret;    if (ret < 0 || id != 16) {	errmsg = "ASN.1 decoding failure";	retval = SSH2_WRONG_PASSPHRASE;	goto error;    }    /* Expect a load of INTEGERs. */    if (key->type == OSSH_RSA)	num_integers = 9;    else if (key->type == OSSH_DSA)	num_integers = 6;    else	num_integers = 0;	       /* placate compiler warnings */    /*     * Space to create key blob in.     */    blobsize = 256+key->keyblob_len;    blob = snewn(blobsize, unsigned char);    PUT_32BIT(blob, 7);    if (key->type == OSSH_DSA)	memcpy(blob+4, "ssh-dss", 7);    else if (key->type == OSSH_RSA)	memcpy(blob+4, "ssh-rsa", 7);    blobptr = 4+7;    privptr = -1;    for (i = 0; i < num_integers; i++) {	ret = ber_read_id_len(p, key->keyblob+key->keyblob_len-p,			      &id, &len, &flags);	p += ret;	if (ret < 0 || id != 2 ||	    key->keyblob+key->keyblob_len-p < len) {	    errmsg = "ASN.1 decoding failure";	    retval = SSH2_WRONG_PASSPHRASE;	    goto error;	}	if (i == 0) {	    /*	     * The first integer should be zero always (I think	     * this is some sort of version indication).	     */	    if (len != 1 || p[0] != 0) {		errmsg = "Version number mismatch";		goto error;	    }	} else if (key->type == OSSH_RSA) {	    /*	     * Integers 1 and 2 go into the public blob but in the	     * opposite order; integers 3, 4, 5 and 8 go into the	     * private blob. The other two (6 and 7) are ignored.	     */	    if (i == 1) {		/* Save the details for after we deal with number 2. */		modptr = (char *)p;		modlen = len;	    } else if (i != 6 && i != 7) {		PUT_32BIT(blob+blobptr, len);		memcpy(blob+blobptr+4, p, len);		blobptr += 4+len;		if (i == 2) {		    PUT_32BIT(blob+blobptr, modlen);		    memcpy(blob+blobptr+4, modptr, modlen);		    blobptr += 4+modlen;		    privptr = blobptr;		}	    }	} else if (key->type == OSSH_DSA) {	    /*	     * Integers 1-4 go into the public blob; integer 5 goes	     * into the private blob.	     */	    PUT_32BIT(blob+blobptr, len);	    memcpy(blob+blobptr+4, p, len);	    blobptr += 4+len;	    if (i == 4)		privptr = blobptr;	}	/* Skip past the number. */	p += len;    }    /*     * Now put together the actual key. Simplest way to do this is     * to assemble our own key blobs and feed them to the createkey     * functions; this is a bit faffy but it does mean we get all     * the sanity checks for free.     */    assert(privptr > 0);	       /* should have bombed by now if not */    retkey = snew(struct ssh2_userkey);    retkey->alg = (key->type == OSSH_RSA ? &ssh_rsa : &ssh_dss);    retkey->data = retkey->alg->createkey(blob, privptr,					  blob+privptr, blobptr-privptr);    if (!retkey->data) {	sfree(retkey);	errmsg = "unable to create key data structure";	goto error;    }    retkey->comment = dupstr("imported-openssh-key");    errmsg = NULL;                     /* no error */    retval = retkey;    error:    if (blob) {        memset(blob, 0, blobsize);        sfree(blob);    }    memset(key->keyblob, 0, key->keyblob_size);    sfree(key->keyblob);    memset(&key, 0, sizeof(key));    sfree(key);    return retval;}int openssh_write(const Filename *filename, struct ssh2_userkey *key,		  char *passphrase){    unsigned char *pubblob, *privblob, *spareblob;    int publen, privlen, sparelen = 0;    unsigned char *outblob;    int outlen;    struct mpint_pos numbers[9];    int nnumbers, pos, len, seqlen, i;    char *header, *footer;    char zero[1];    unsigned char iv[8];    int ret = 0;    FILE *fp;    /*     * Fetch the key blobs.     */    pubblob = key->alg->public_blob(key->data, &publen);    privblob = key->alg->private_blob(key->data, &privlen);    spareblob = outblob = NULL;    /*     * Find the sequence of integers to be encoded into the OpenSSH     * key blob, and also decide on the header line.     */    if (key->alg == &ssh_rsa) {        int pos;        struct mpint_pos n, e, d, p, q, iqmp, dmp1, dmq1;        Bignum bd, bp, bq, bdmp1, bdmq1;        pos = 4 + GET_32BIT(pubblob);        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &e);        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &n);        pos = 0;        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &d);        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &p);        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &q);        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &iqmp);        assert(e.start && iqmp.start); /* can't go wrong */        /* We also need d mod (p-1) and d mod (q-1). */        bd = bignum_from_bytes(d.start, d.bytes);        bp = bignum_from_bytes(p.start, p.bytes);        bq = bignum_from_bytes(q.start, q.bytes);        decbn(bp);        decbn(bq);        bdmp1 = bigmod(bd, bp);        bdmq1 = bigmod(bd, bq);        freebn(bd);        freebn(bp);        freebn(bq);        dmp1.bytes = (bignum_bitcount(bdmp1)+8)/8;        dmq1.bytes = (bignum_bitcount(bdmq1)+8)/8;        sparelen = dmp1.bytes + dmq1.bytes;        spareblob = snewn(sparelen, unsigned char);        dmp1.start = spareblob;        dmq1.start = spareblob + dmp1.bytes;        for (i = 0; i < dmp1.bytes; i++)            spareblob[i] = bignum_byte(bdmp1, dmp1.bytes-1 - i);        for (i = 0; i < dmq1.bytes; i++)            spareblob[i+dmp1.bytes] = bignum_byte(bdmq1, dmq1.bytes-1 - i);        freebn(bdmp1);        freebn(bdmq1);        numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';        numbers[1] = n;        numbers[2] = e;        numbers[3] = d;        numbers[4] = p;        numbers[5] = q;        numbers[6] = dmp1;        numbers[7] = dmq1;        numbers[8] = iqmp;        nnumbers = 9;        header = "-----BEGIN RSA PRIVATE KEY-----\n";        footer = "-----END RSA PRIVATE KEY-----\n";    } else if (key->alg == &ssh_dss) {        int pos;        struct mpint_pos p, q, g, y, x;        pos = 4 + GET_32BIT(pubblob);        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &p);        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &q);        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &g);        pos += ssh2_read_mpint(pubblob+pos, publen-pos, &y);        pos = 0;        pos += ssh2_read_mpint(privblob+pos, privlen-pos, &x);        assert(y.start && x.start); /* can't go wrong */        numbers[0].start = zero; numbers[0].bytes = 1; zero[0] = '\0';         numbers[1] = p;        numbers[2] = q;        numbers[3] = g;        numbers[4] = y;        numbers[5] = x;        nnumbers = 6;        header = "-----BEGIN DSA PRIVATE KEY-----\n";        footer = "-----END DSA PRIVATE KEY-----\n";    } else {        assert(0);                     /* zoinks! */    }    /*     * Now count up the total size of the ASN.1 encoded integers,     * so as to determine the length of the containing SEQUENCE.     */    len = 0;    for (i = 0; i < nnumbers; i++) {	len += ber_write_id_len(NULL, 2, numbers[i].bytes, 0);	len += numbers[i].bytes;    }    seqlen = len;    /* Now add on the SEQUENCE header. */    len += ber_write_id_len(NULL, 16, seqlen, ASN1_CONSTRUCTED);    /* Round up to the cipher block size, ensuring we have at least one     * byte of padding (see below). */    outlen = len;    if (passphrase)	outlen = (outlen+8) &~ 7;    /*     * Now we know how big outblob needs to be. Allocate it.     */    outblob = snewn(outlen, unsigned char);    /*     * And write the data into it.     */    pos = 0;    pos += ber_write_id_len(outblob+pos, 16, seqlen, ASN1_CONSTRUCTED);    for (i = 0; i < nnumbers; i++) {	pos += ber_write_id_len(outblob+pos, 2, numbers[i].bytes, 0);	memcpy(outblob+pos, numbers[i].start, numbers[i].bytes);	pos += numbers[i].bytes;    }    /*     * Padding on OpenSSH keys is deterministic. The number of     * padding bytes is always more than zero, and always at most     * the cipher block length. The value of each padding byte is     * equal to the number of padding bytes. So a plaintext that's     * an exact multiple of the block size will be padded with 08     * 08 08 08 08 08 08 08 (assuming a 64-bit block cipher); a

⌨️ 快捷键说明

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