In case anyone cares, here's an implementation of the Solovay-Strassen
primality test.

#include <openssl/bn.h>
#include "bn_prime.h"

/* return Jacobi symbol, or -2 on error */
int BN_jacobi_symbol(BIGNUM *A, BIGNUM *N, BN_CTX *ctx)
        {
        BIGNUM *a, *n, *r, *m4, *m8, *tmp;
        unsigned long e;
        int ok = 0, s = 1;

        a = &(ctx->bn[ctx->tos++]);
        n = &(ctx->bn[ctx->tos++]);
        r = &(ctx->bn[ctx->tos++]);
        m4 = &(ctx->bn[ctx->tos++]);
        m8 = &(ctx->bn[ctx->tos++]);

        if (!BN_set_word(m4, 4)) goto err;
        if (!BN_set_word(m8, 8)) goto err;
        if (!BN_copy(a, A)) goto err;
        if (!BN_copy(n, N)) goto err;

        for (;;)
                {
                if (BN_is_zero(a))
                        {
                        s = 0;
                        break;
                        }
                if (BN_is_one(a))
                        break;
        
                e = 0;
                while (!BN_is_odd(a))
                        {
                        e++;
                        if (!BN_rshift1(a, a)) goto err;
                        }

                if (e % 2)
                        {
                        if (!BN_mod(r, n, m8, ctx)) goto err;
                        if (!BN_is_one(r) && !BN_is_word(r, 7))
                                s = -s;
                        }

                if (!BN_mod(r, n, m4, ctx)) goto err;
                if (BN_is_word(r, 3))
                        {
                        if (!BN_mod(r, a, m4, ctx)) goto err;
                        if (BN_is_word(r, 3))
                                s = -s;
                        }

                if (!BN_is_one(a))
                        if (!BN_mod(n, n, a, ctx)) goto err;

                tmp=n; n=a; a=tmp;
                }
        ok = 1;

 err:
        ctx->tos -= 5;
        return (ok ? s : -2);
        }

static int witness(BIGNUM *a, BIGNUM *n, BN_CTX *ctx, BN_CTX *ctx2)
        {
        int s,ret= -1;
        BIGNUM *r,*n1;

        r = &(ctx->bn[ctx->tos++]);
        n1 = &(ctx->bn[ctx->tos++]);

        if (!BN_copy(n1,n)) goto err;
        if (!BN_rshift1(n1,n1)) goto err; /* n1 = (n-1)/2 */

        if (!BN_mod_exp(r, a, n1, n, ctx2)) goto err;

        if (!BN_add_word(r,1)) goto err;
        if (!BN_is_word(r,2) && BN_cmp(r,n) != 0)
                ret = 1;
        if (ret != 1)
                {
                if ((s = BN_jacobi_symbol(a, n, ctx)) == -2) goto err;
                if ((s == 1 && BN_is_word(r,2)) ||
                    (s == -1 && BN_cmp(r,n) == 0))
                        ret = 0;
                else
                        ret = 1;
                }
 err:
        ctx->tos -= 2;
        return(ret);
        }

int BN_is_prime_solovay_strassen(BIGNUM *a, int checks,
                void (*callback)(int,int,void *),
                BN_CTX *ctx_passed, BN_CTX *ctx2_passed, void *cb_arg,
                int do_trial_division)
        {
        int i,j,ret= -1;
        BIGNUM *check;
        BN_CTX *ctx=NULL,*ctx2=NULL;

        if (checks == BN_prime_checks)
                {
                checks = 50;
                }

        if (!BN_is_odd(a))
                return(0);
        if (do_trial_division)
                {
                for (i = 1; i < NUMPRIMES; i++)
                        if (BN_mod_word(a, primes[i]) == 0) 
                                return 0;
                if (callback != NULL) callback(1,-1,cb_arg);
                }

        if (ctx_passed != NULL)
                ctx=ctx_passed;
        else
                if ((ctx=BN_CTX_new()) == NULL) goto err;
        if (ctx2_passed != NULL)
                ctx2=ctx2_passed;
        else
                if ((ctx2=BN_CTX_new()) == NULL) goto err;

        check= &(ctx->bn[ctx->tos++]);

        for (i=0; i<checks; i++)
                {
                if (!BN_pseudo_rand(check,BN_num_bits(a),0,0)) goto err;
                if (BN_cmp(check, a) >= 0)
                        BN_sub(check, check, a);
                if (BN_is_zero(check)) BN_one(check);
                j=witness(check,a,ctx,ctx2);
                if (j == -1) goto err;
                if (j)
                        {
                        ret=0;
                        goto err;
                        }
                if (callback != NULL) callback(1,i,cb_arg);
                }
        ret=1;
err:
        ctx->tos--;
        if ((ctx_passed == NULL) && (ctx != NULL))
                BN_CTX_free(ctx);
        if ((ctx2_passed == NULL) && (ctx2 != NULL))
                BN_CTX_free(ctx2);
        return(ret);
        }
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to