Beispiel #1
0
void rsaencrypt(unsigned char *data, int length, struct RSAKey *key) {
    Bignum b1, b2;
    int w, i;
    unsigned char *p;

    debug(key->exponent);

    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;

    w = (key->bytes+1)/2;

    b1 = newbn(w);
    b2 = newbn(w);

    p = data;
    for (i=1; i<=w; i++)
	b1[i] = 0;
    for (i=0; i<key->bytes; i++) {
	unsigned char byte = *p++;
	if ((key->bytes-i) & 1)
	    b1[w-i/2] |= byte;
	else
	    b1[w-i/2] |= byte<<8;
    }

    debug(b1);

    modpow(b1, key->exponent, key->modulus, b2);

    debug(b2);

    p = data;
    for (i=0; i<key->bytes; i++) {
	unsigned char b;
	if (i & 1)
	    b = b2[w-i/2] & 0xFF;
	else
	    b = b2[w-i/2] >> 8;
	*p++ = b;
    }

    freebn(b1);
    freebn(b2);
}
Beispiel #2
0
static void modmult(Bignum r1, Bignum r2, Bignum modulus, Bignum result) {
    Bignum temp = newbn(modulus[0]+1);
    Bignum tmp2 = newbn(modulus[0]+1);
    int i;
    int bit, bits, digit, smallbit;

    enter((">modmult\n"));
    debug(r1);
    debug(r2);
    debug(modulus);

    for (i=1; i<=result[0]; i++)
	result[i] = 0;		       /* result := 0 */
    for (i=1; i<=temp[0]; i++)
	temp[i] = (i > r2[0] ? 0 : r2[i]);   /* temp := r2 */

    bits = 1+msb(r1);

    for (bit = 0; bit < bits; bit++) {
	digit = 1 + bit / 16;
	smallbit = bit % 16;

	debug(temp);
	if (digit <= r1[0] && (r1[digit] & (1<<smallbit))) {
	    dmsg(("bit %d\n", bit));
	    add(temp, result, tmp2);
	    if (ge(tmp2, modulus))
		sub(tmp2, modulus, result);
	    else
		add(tmp2, Zero, result);
	    debug(result);
	}

	add(temp, temp, tmp2);
	if (ge(tmp2, modulus))
	    sub(tmp2, modulus, temp);
	else
	    add(tmp2, Zero, temp);
    }

    freebn(temp);
    freebn(tmp2);

    debug(result);
    leave(("<modmult\n"));
}
Beispiel #3
0
int makekey(unsigned char *data, struct RSAKey *result,
	    unsigned char **keystr) {
    unsigned char *p = data;
    Bignum bn[2];
    int i, j;
    int w, b;

    result->bits = 0;
    for (i=0; i<4; i++)
	result->bits = (result->bits << 8) + *p++;

    for (j=0; j<2; j++) {

	w = 0;
	for (i=0; i<2; i++)
	    w = (w << 8) + *p++;

	result->bytes = b = (w+7)/8;   /* bits -> bytes */
	w = (w+15)/16;		       /* bits -> words */

	bn[j] = newbn(w);

	if (keystr) *keystr = p;       /* point at key string, second time */

	for (i=1; i<=w; i++)
	    bn[j][i] = 0;
	for (i=0; i<b; i++) {
	    unsigned char byte = *p++;
	    if ((b-i) & 1)
		bn[j][w-i/2] |= byte;
	    else
		bn[j][w-i/2] |= byte<<8;
	}

	debug(bn[j]);

    }

    result->exponent = bn[0];
    result->modulus = bn[1];

    return p - data;
}
Beispiel #4
0
static Bignum getmp(char **data, int *datalen) {
    char *p;
    int i, j, length;
    Bignum b;

    getstring(data, datalen, &p, &length);
    if (!p)
        return NULL;
    if (p[0] & 0x80)
        return NULL;                   /* negative mp */
    b = newbn((length+1)/2);
    for (i = 0; i < length; i++) {
        j = length - 1 - i;
        if (j & 1)
            b[j/2+1] |= ((unsigned char)p[i]) << 8;
        else
            b[j/2+1] |= ((unsigned char)p[i]);
    }
    while (b[0] > 1 && b[b[0]] == 0) b[0]--;
    return b;
}
Beispiel #5
0
static Bignum get160(char **data, int *datalen) {
    char *p;
    int i, j, length;
    Bignum b;

    p = *data;
    *data += 20;
    *datalen -= 20;

    length = 20;
    while (length > 0 && !p[0])
        p++, length--;
    b = newbn((length+1)/2);
    for (i = 0; i < length; i++) {
        j = length - 1 - i;
        if (j & 1)
            b[j/2+1] |= ((unsigned char)p[i]) << 8;
        else
            b[j/2+1] |= ((unsigned char)p[i]);
    }
    return b;
}
Beispiel #6
0
Bignum bn_power_2(int n)
{
    Bignum ret = newbn(n / BIGNUM_INT_BITS + 1);
    bignum_set_bit(ret, n, 1);
    return ret;
}
Beispiel #7
0
/*
 * Generate a prime. We arrange to select a prime with the property
 * (prime % modulus) != residue (to speed up use in RSA).
 */
Bignum primegen(int bits, int modulus, int residue,
                int phase, progfn_t pfn, void *pfnparam) {
    int i, k, v, byte, bitsleft, check, checks;
    unsigned long delta, moduli[NPRIMES+1], residues[NPRIMES+1];
    Bignum p, pm1, q, wqp, wqp2;
    int progress = 0;

    byte = 0; bitsleft = 0;

    STARTOVER:

    pfn(pfnparam, phase, ++progress);

    /*
     * Generate a k-bit random number with top and bottom bits set.
     */
    p = newbn((bits+15)/16);
    for (i = 0; i < bits; i++) {
        if (i == 0 || i == bits-1)
            v = 1;
        else {
            if (bitsleft <= 0)
                bitsleft = 8; byte = random_byte();
            v = byte & 1;
            byte >>= 1;
            bitsleft--;
        }
        bignum_set_bit(p, i, v);
    }

    /*
     * Ensure this random number is coprime to the first few
     * primes, by repeatedly adding 2 to it until it is.
     */
    for (i = 0; i < NPRIMES; i++) {
        moduli[i] = primes[i];
        residues[i] = bignum_mod_short(p, primes[i]);
    }
    moduli[NPRIMES] = modulus;
    residues[NPRIMES] = (bignum_mod_short(p, (unsigned short)modulus)
                         + modulus - residue);
    delta = 0;
    while (1) {
        for (i = 0; i < (sizeof(moduli) / sizeof(*moduli)); i++)
            if (!((residues[i] + delta) % moduli[i]))
                break;
        if (i < (sizeof(moduli) / sizeof(*moduli))) {/* we broke */
            delta += 2;
            if (delta < 2) {
                freebn(p);
                goto STARTOVER;
            }
            continue;
        }
        break;
    }
    q = p;
    p = bignum_add_long(q, delta);
    freebn(q);

    /*
     * Now apply the Miller-Rabin primality test a few times. First
     * work out how many checks are needed.
     */
    checks = 27;
    if (bits >= 150) checks = 18;
    if (bits >= 200) checks = 15;
    if (bits >= 250) checks = 12;
    if (bits >= 300) checks = 9;
    if (bits >= 350) checks = 8;
    if (bits >= 400) checks = 7;
    if (bits >= 450) checks = 6;
    if (bits >= 550) checks = 5;
    if (bits >= 650) checks = 4;
    if (bits >= 850) checks = 3;
    if (bits >= 1300) checks = 2;

    /*
     * Next, write p-1 as q*2^k.
     */
    for (k = 0; bignum_bit(p, k) == !k; k++);   /* find first 1 bit in p-1 */
    q = bignum_rshift(p, k);
    /* And store p-1 itself, which we'll need. */
    pm1 = copybn(p);
    decbn(pm1);

    /*
     * Now, for each check ...
     */
    for (check = 0; check < checks; check++) {
        Bignum w;

        /*
         * Invent a random number between 1 and p-1 inclusive.
         */
        while (1) {
            w = newbn((bits+15)/16);
            for (i = 0; i < bits; i++) {
                if (bitsleft <= 0)
                    bitsleft = 8; byte = random_byte();
                v = byte & 1;
                byte >>= 1;
                bitsleft--;
                bignum_set_bit(w, i, v);
            }
            if (bignum_cmp(w, p) >= 0 || bignum_cmp(w, Zero) == 0) {
                freebn(w);
                continue;
            }
            break;
        }

        pfn(pfnparam, phase, ++progress);

        /*
         * Compute w^q mod p.
         */
        wqp = modpow(w, q, p);
        freebn(w);

        /*
         * See if this is 1, or if it is -1, or if it becomes -1
         * when squared at most k-1 times.
         */
        if (bignum_cmp(wqp, One) == 0 || bignum_cmp(wqp, pm1) == 0) {
            freebn(wqp);
            continue;
        }
        for (i = 0; i < k-1; i++) {
            wqp2 = modmul(wqp, wqp, p);
            freebn(wqp);
            wqp = wqp2;
            if (bignum_cmp(wqp, pm1) == 0)
                break;
        }
        if (i < k-1) {
            freebn(wqp);
            continue;
        }

        /*
         * It didn't. Therefore, w is a witness for the
         * compositeness of p.
         */
        freebn(p);
        freebn(pm1);
        freebn(q);
        goto STARTOVER;
    }

    /*
     * We have a prime!
     */
    freebn(q);
    freebn(pm1);
    return p;
}