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

📄 sshrsa.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * RSA implementation for PuTTY. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include "ssh.h"#include "misc.h"#define GET_32BIT(cp) \    (((unsigned long)(unsigned char)(cp)[0] << 24) | \    ((unsigned long)(unsigned char)(cp)[1] << 16) | \    ((unsigned long)(unsigned char)(cp)[2] << 8) | \    ((unsigned long)(unsigned char)(cp)[3]))#define PUT_32BIT(cp, value) { \    (cp)[0] = (unsigned char)((value) >> 24); \    (cp)[1] = (unsigned char)((value) >> 16); \    (cp)[2] = (unsigned char)((value) >> 8); \    (cp)[3] = (unsigned char)(value); }int makekey(unsigned char *data, int len, struct RSAKey *result,	    unsigned char **keystr, int order){    unsigned char *p = data;    int i, n;    if (len < 4)	return -1;    if (result) {	result->bits = 0;	for (i = 0; i < 4; i++)	    result->bits = (result->bits << 8) + *p++;    } else	p += 4;    len -= 4;    /*     * order=0 means exponent then modulus (the keys sent by the     * server). order=1 means modulus then exponent (the keys     * stored in a keyfile).     */    if (order == 0) {	n = ssh1_read_bignum(p, len, result ? &result->exponent : NULL);	if (n < 0) return -1;	p += n;	len -= n;    }    n = ssh1_read_bignum(p, len, result ? &result->modulus : NULL);    if (n < 0 || (result && bignum_bitcount(result->modulus) == 0)) return -1;    if (result)	result->bytes = n - 2;    if (keystr)	*keystr = p + 2;    p += n;    len -= n;    if (order == 1) {	n = ssh1_read_bignum(p, len, result ? &result->exponent : NULL);	if (n < 0) return -1;	p += n;	len -= n;    }    return p - data;}int makeprivate(unsigned char *data, int len, struct RSAKey *result){    return ssh1_read_bignum(data, len, &result->private_exponent);}int rsaencrypt(unsigned char *data, int length, struct RSAKey *key){    Bignum b1, b2;    int i;    unsigned char *p;    if (key->bytes < length + 4)	return 0;		       /* RSA key too short! */    memmove(data + key->bytes - length, data, length);    data[0] = 0;    data[1] = 2;    for (i = 2; i < key->bytes - length - 1; i++) {	do {	    data[i] = random_byte();	} while (data[i] == 0);    }    data[key->bytes - length - 1] = 0;    b1 = bignum_from_bytes(data, key->bytes);    b2 = modpow(b1, key->exponent, key->modulus);    p = data;    for (i = key->bytes; i--;) {	*p++ = bignum_byte(b2, i);    }    freebn(b1);    freebn(b2);    return 1;}static void sha512_mpint(SHA512_State * s, Bignum b){    unsigned char lenbuf[4];    int len;    len = (bignum_bitcount(b) + 8) / 8;    PUT_32BIT(lenbuf, len);    SHA512_Bytes(s, lenbuf, 4);    while (len-- > 0) {	lenbuf[0] = bignum_byte(b, len);	SHA512_Bytes(s, lenbuf, 1);    }    memset(lenbuf, 0, sizeof(lenbuf));}/* * This function is a wrapper on modpow(). It has the same effect * as modpow(), but employs RSA blinding to protect against timing * attacks. */static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key){    Bignum random, random_encrypted, random_inverse;    Bignum input_blinded, ret_blinded;    Bignum ret;    SHA512_State ss;    unsigned char digest512[64];    int digestused = lenof(digest512);    int hashseq = 0;    /*     * Start by inventing a random number chosen uniformly from the     * range 2..modulus-1. (We do this by preparing a random number     * of the right length and retrying if it's greater than the     * modulus, to prevent any potential Bleichenbacher-like     * attacks making use of the uneven distribution within the     * range that would arise from just reducing our number mod n.     * There are timing implications to the potential retries, of     * course, but all they tell you is the modulus, which you     * already knew.)     *      * To preserve determinism and avoid Pageant needing to share     * the random number pool, we actually generate this `random'     * number by hashing stuff with the private key.     */    while (1) {	int bits, byte, bitsleft, v;	random = copybn(key->modulus);	/*	 * Find the topmost set bit. (This function will return its	 * index plus one.) Then we'll set all bits from that one	 * downwards randomly.	 */	bits = bignum_bitcount(random);	byte = 0;	bitsleft = 0;	while (bits--) {	    if (bitsleft <= 0) {		bitsleft = 8;		/*		 * Conceptually the following few lines are equivalent to		 *    byte = random_byte();		 */		if (digestused >= lenof(digest512)) {		    unsigned char seqbuf[4];		    PUT_32BIT(seqbuf, hashseq);		    SHA512_Init(&ss);		    SHA512_Bytes(&ss, "RSA deterministic blinding", 26);		    SHA512_Bytes(&ss, seqbuf, sizeof(seqbuf));		    sha512_mpint(&ss, key->private_exponent);		    SHA512_Final(&ss, digest512);		    hashseq++;		    /*		     * Now hash that digest plus the signature		     * input.		     */		    SHA512_Init(&ss);		    SHA512_Bytes(&ss, digest512, sizeof(digest512));		    sha512_mpint(&ss, input);		    SHA512_Final(&ss, digest512);		    digestused = 0;		}		byte = digest512[digestused++];	    }	    v = byte & 1;	    byte >>= 1;	    bitsleft--;	    bignum_set_bit(random, bits, v);	}	/*	 * Now check that this number is strictly greater than	 * zero, and strictly less than modulus.	 */	if (bignum_cmp(random, Zero) <= 0 ||	    bignum_cmp(random, key->modulus) >= 0) {	    freebn(random);	    continue;	} else {	    break;	}    }    /*     * RSA blinding relies on the fact that (xy)^d mod n is equal     * to (x^d mod n) * (y^d mod n) mod n. We invent a random pair     * y and y^d; then we multiply x by y, raise to the power d mod     * n as usual, and divide by y^d to recover x^d. Thus an     * attacker can't correlate the timing of the modpow with the     * input, because they don't know anything about the number     * that was input to the actual modpow.     *      * The clever bit is that we don't have to do a huge modpow to     * get y and y^d; we will use the number we just invented as     * _y^d_, and use the _public_ exponent to compute (y^d)^e = y     * from it, which is much faster to do.     */    random_encrypted = modpow(random, key->exponent, key->modulus);    random_inverse = modinv(random, key->modulus);    input_blinded = modmul(input, random_encrypted, key->modulus);    ret_blinded = modpow(input_blinded, key->private_exponent, key->modulus);    ret = modmul(ret_blinded, random_inverse, key->modulus);    freebn(ret_blinded);    freebn(input_blinded);    freebn(random_inverse);    freebn(random_encrypted);    freebn(random);    return ret;}Bignum rsadecrypt(Bignum input, struct RSAKey *key){    return rsa_privkey_op(input, key);}int rsastr_len(struct RSAKey *key){    Bignum md, ex;    int mdlen, exlen;    md = key->modulus;    ex = key->exponent;    mdlen = (bignum_bitcount(md) + 15) / 16;    exlen = (bignum_bitcount(ex) + 15) / 16;    return 4 * (mdlen + exlen) + 20;}void rsastr_fmt(char *str, struct RSAKey *key){    Bignum md, ex;    int len = 0, i, nibbles;    static const char hex[] = "0123456789abcdef";    md = key->modulus;    ex = key->exponent;    len += sprintf(str + len, "0x");    nibbles = (3 + bignum_bitcount(ex)) / 4;    if (nibbles < 1)	nibbles = 1;    for (i = nibbles; i--;)	str[len++] = hex[(bignum_byte(ex, i / 2) >> (4 * (i % 2))) & 0xF];    len += sprintf(str + len, ",0x");    nibbles = (3 + bignum_bitcount(md)) / 4;    if (nibbles < 1)	nibbles = 1;    for (i = nibbles; i--;)	str[len++] = hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF];    str[len] = '\0';}/* * Generate a fingerprint string for the key. Compatible with the * OpenSSH fingerprint code. */void rsa_fingerprint(char *str, int len, struct RSAKey *key){    struct MD5Context md5c;    unsigned char digest[16];    char buffer[16 * 3 + 40];    int numlen, slen, i;    MD5Init(&md5c);    numlen = ssh1_bignum_length(key->modulus) - 2;    for (i = numlen; i--;) {	unsigned char c = bignum_byte(key->modulus, i);	MD5Update(&md5c, &c, 1);    }    numlen = ssh1_bignum_length(key->exponent) - 2;    for (i = numlen; i--;) {	unsigned char c = bignum_byte(key->exponent, i);	MD5Update(&md5c, &c, 1);    }    MD5Final(digest, &md5c);    sprintf(buffer, "%d ", bignum_bitcount(key->modulus));    for (i = 0; i < 16; i++)	sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",		digest[i]);    strncpy(str, buffer, len);    str[len - 1] = '\0';    slen = strlen(str);    if (key->comment && slen < len - 1) {	str[slen] = ' ';	strncpy(str + slen + 1, key->comment, len - slen - 1);	str[len - 1] = '\0';    }}/* * Verify that the public data in an RSA key matches the private * data. We also check the private data itself: we ensure that p > * q and that iqmp really is the inverse of q mod p. */int rsa_verify(struct RSAKey *key){    Bignum n, ed, pm1, qm1;    int cmp;    /* n must equal pq. */    n = bigmul(key->p, key->q);    cmp = bignum_cmp(n, key->modulus);    freebn(n);    if (cmp != 0)	return 0;    /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */    pm1 = copybn(key->p);    decbn(pm1);    ed = modmul(key->exponent, key->private_exponent, pm1);    cmp = bignum_cmp(ed, One);    sfree(ed);    if (cmp != 0)	return 0;    qm1 = copybn(key->q);    decbn(qm1);    ed = modmul(key->exponent, key->private_exponent, qm1);    cmp = bignum_cmp(ed, One);    sfree(ed);    if (cmp != 0)	return 0;    /*     * Ensure p > q.     */    if (bignum_cmp(key->p, key->q) <= 0)	return 0;    /*     * Ensure iqmp * q is congruent to 1, modulo p.     */    n = modmul(key->iqmp, key->q, key->p);    cmp = bignum_cmp(n, One);    sfree(n);    if (cmp != 0)	return 0;    return 1;}/* Public key blob as used by Pageant: exponent before modulus. */unsigned char *rsa_public_blob(struct RSAKey *key, int *len){    int length, pos;    unsigned char *ret;    length = (ssh1_bignum_length(key->modulus) +	      ssh1_bignum_length(key->exponent) + 4);    ret = snewn(length, unsigned char);    PUT_32BIT(ret, bignum_bitcount(key->modulus));    pos = 4;    pos += ssh1_write_bignum(ret + pos, key->exponent);    pos += ssh1_write_bignum(ret + pos, key->modulus);    *len = length;    return ret;}/* Given a public blob, determine its length. */int rsa_public_blob_len(void *data, int maxlen){    unsigned char *p = (unsigned char *)data;    int n;    if (maxlen < 4)	return -1;    p += 4;			       /* length word */    maxlen -= 4;    n = ssh1_read_bignum(p, maxlen, NULL);    /* exponent */    if (n < 0)	return -1;    p += n;    n = ssh1_read_bignum(p, maxlen, NULL);    /* modulus */    if (n < 0)	return -1;    p += n;    return p - (unsigned char *)data;}

⌨️ 快捷键说明

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