示例#1
0
/* IEEE1363 ECDSA Signature Verification. Signature C and D on F is verified using public key W */
    public static int ECPVP_DSA(sbyte[] W, sbyte[] F, sbyte[] C, sbyte[] D)
    {
        BIG r, gx, gy, f, c, d, h2;
        int res = 0;
        ECP G, WP, P;

        HASH H = new HASH();

        H.process_array(F);
        sbyte[] B = H.hash();

        gx = new BIG(ROM.CURVE_Gx);
        gy = new BIG(ROM.CURVE_Gy);

        G = new ECP(gx, gy);
        r = new BIG(ROM.CURVE_Order);

        c = BIG.fromBytes(C);
        d = BIG.fromBytes(D);
        f = BIG.fromBytes(B);

        if (c.iszilch() || BIG.comp(c, r) >= 0 || d.iszilch() || BIG.comp(d, r) >= 0)
        {
            res = INVALID;
        }

        if (res == 0)
        {
            d.invmodp(r);
            f.copy(BIG.modmul(f, d, r));
            h2 = BIG.modmul(c, d, r);

            WP = ECP.fromBytes(W);
            if (WP.is_infinity())
            {
                res = ERROR;
            }
            else
            {
                P = new ECP();
                P.copy(WP);
                P = P.mul2(h2, G, f);
                if (P.is_infinity())
                {
                    res = INVALID;
                }
                else
                {
                    d = P.X;
                    d.mod(r);
                    if (BIG.comp(d, c) != 0)
                    {
                        res = INVALID;
                    }
                }
            }
        }

        return(res);
    }
示例#2
0
/* Initialize RNG with some real entropy from some external source */
    public virtual void seed(int rawlen, sbyte[] raw)
    {     // initialise from at least 128 byte string of raw random entropy
        int i;

        sbyte[] digest;
        sbyte[] b  = new sbyte[4];
        HASH    sh = new HASH();

        pool_ptr = 0;
        for (i = 0; i < NK; i++)
        {
            ira[i] = 0;
        }
        if (rawlen > 0)
        {
            for (i = 0; i < rawlen; i++)
            {
                sh.process(raw[i]);
            }
            digest = sh.hash();

/* initialise PRNG from distilled randomness */

            for (i = 0; i < 8; i++)
            {
                b[0] = digest[4 * i];
                b[1] = digest[4 * i + 1];
                b[2] = digest[4 * i + 2];
                b[3] = digest[4 * i + 3];
                sirand(pack(b));
            }
        }
        fill_pool();
    }
示例#3
0
/* IEEE ECDSA Signature, C and D are signature on F using private key S */
    public static int ECPSP_DSA(RAND RNG, sbyte[] S, sbyte[] F, sbyte[] C, sbyte[] D)
    {
        sbyte[] T = new sbyte[EFS];
        BIG     gx, gy, r, s, f, c, d, u, vx;
        ECP     G, V;

        HASH H = new HASH();

        H.process_array(F);
        sbyte[] B = H.hash();

        gx = new BIG(ROM.CURVE_Gx);
        gy = new BIG(ROM.CURVE_Gy);

        G = new ECP(gx, gy);
        r = new BIG(ROM.CURVE_Order);

        s = BIG.fromBytes(S);
        f = BIG.fromBytes(B);

        c = new BIG(0);
        d = new BIG(0);
        V = new ECP();

        do
        {
            u = BIG.randomnum(r, RNG);

            V.copy(G);
            V  = V.mul(u);
            vx = V.X;
            c.copy(vx);
            c.mod(r);
            if (c.iszilch())
            {
                continue;
            }
            u.invmodp(r);
            d.copy(BIG.modmul(s, c, r));
            d.add(f);
            d.copy(BIG.modmul(u, d, r));
        } while (d.iszilch());

        c.toBytes(T);
        for (int i = 0; i < EFS; i++)
        {
            C[i] = T[i];
        }
        d.toBytes(T);
        for (int i = 0; i < EFS; i++)
        {
            D[i] = T[i];
        }
        return(0);
    }
示例#4
0
    private void fill_pool()
    {
        HASH sh = new HASH();

        for (int i = 0; i < 128; i++)
        {
            sh.process(sbrand());
        }
        pool     = sh.hash();
        pool_ptr = 0;
    }
示例#5
0
    public const int TRAP   = 200;   // 200 for 4 digit PIN, 2000 for 6-digit PIN  - approx 2*sqrt(MAXPIN)

/* Hash number (optional) and string to point on curve */

    public static sbyte[] hashit(int n, sbyte[] ID)
    {
        HASH H = new HASH();

        if (n != 0)
        {
            H.process_num(n);
        }
        H.process_array(ID);
        sbyte[] h = H.hash();
        return(h);
    }
示例#6
0
/* Key Derivation Functions */
/* Input octet Z */
/* Output key of length olen */
    public static sbyte[] KDF1(sbyte[] Z, int olen)
    {
/* NOTE: the parameter olen is the length of the output K in bytes */
        HASH H    = new HASH();
        int  hlen = HASH.len;

        sbyte[] K = new sbyte[olen];

        sbyte[] B;
        int     counter, cthreshold, k = 0;

        for (int i = 0; i < K.Length; i++)
        {
            K[i] = 0;
        }

        cthreshold = olen / hlen;
        if (olen % hlen != 0)
        {
            cthreshold++;
        }

        for (counter = 0; counter < cthreshold; counter++)
        {
            H.process_array(Z);
            if (counter > 0)
            {
                H.process_num(counter);
            }
            B = H.hash();
            if (k + hlen > olen)
            {
                for (int i = 0; i < olen % hlen; i++)
                {
                    K[k++] = B[i];
                }
            }
            else
            {
                for (int i = 0; i < hlen; i++)
                {
                    K[k++] = B[i];
                }
            }
        }
        return(K);
    }
示例#7
0
/* Mask Generation Function */

    public static void MGF1(sbyte[] Z, int olen, sbyte[] K)
    {
        HASH H    = new HASH();
        int  hlen = HASH.len;

        sbyte[] B = new sbyte[hlen];

        int counter, cthreshold, k = 0;

        for (int i = 0; i < K.Length; i++)
        {
            K[i] = 0;
        }

        cthreshold = olen / hlen;
        if (olen % hlen != 0)
        {
            cthreshold++;
        }
        for (counter = 0; counter < cthreshold; counter++)
        {
            H.process_array(Z);
            H.process_num(counter);
            B = H.hash();

            if (k + hlen > olen)
            {
                for (int i = 0; i < olen % hlen; i++)
                {
                    K[k++] = B[i];
                }
            }
            else
            {
                for (int i = 0; i < hlen; i++)
                {
                    K[k++] = B[i];
                }
            }
        }
    }
示例#8
0
/* Calculate HMAC of m using key k. HMAC is tag of length olen */
    public static int HMAC(sbyte[] M, sbyte[] K, sbyte[] tag)
    {
        /* Input is from an octet m        *
         * olen is requested output length in bytes. k is the key  *
         * The output is the calculated tag */
        int b;

        sbyte[] B;
        sbyte[] K0   = new sbyte[64];
        int     olen = tag.Length;

        b = K0.Length;
        if (olen < 4 || olen > HASH.len)
        {
            return(0);
        }

        for (int i = 0; i < b; i++)
        {
            K0[i] = 0;
        }

        HASH H = new HASH();

        if (K.Length > b)
        {
            H.process_array(K);
            B = H.hash();
            for (int i = 0; i < 32; i++)
            {
                K0[i] = B[i];
            }
        }
        else
        {
            for (int i = 0; i < K.Length; i++)
            {
                K0[i] = K[i];
            }
        }

        for (int i = 0; i < b; i++)
        {
            K0[i] ^= 0x36;
        }
        H.process_array(K0);
        H.process_array(M);
        B = H.hash();

        for (int i = 0; i < b; i++)
        {
            K0[i] ^= 0x6a;
        }
        H.process_array(K0);
        H.process_array(B);
        B = H.hash();

        for (int i = 0; i < olen; i++)
        {
            tag[i] = B[i];
        }

        return(1);
    }
示例#9
0
    /* OAEP Message Decoding for Decryption */
    public static sbyte[] OAEP_DECODE(sbyte[] p, sbyte[] f)
    {
        int  x, t;
        bool comp;
        int  i, k, olen = RFS - 1;
        int  hlen, seedlen;

        HASH H = new HASH();

        hlen = HASH.len;
        sbyte[] SEED = new sbyte[hlen];
        seedlen = hlen;
        sbyte[] CHASH = new sbyte[hlen];

        if (olen < seedlen + hlen + 1)
        {
            return(new sbyte[0]);
        }
        sbyte[] DBMASK = new sbyte[olen - seedlen];
        for (i = 0; i < olen - seedlen; i++)
        {
            DBMASK[i] = 0;
        }

        if (f.Length < RFS)
        {
            int d = RFS - f.Length;
            for (i = RFS - 1; i >= d; i--)
            {
                f[i] = f[i - d];
            }
            for (i = d - 1; i >= 0; i--)
            {
                f[i] = 0;
            }
        }

        if (p != null)
        {
            H.process_array(p);
        }
        sbyte[] h = H.hash();
        for (i = 0; i < hlen; i++)
        {
            CHASH[i] = h[i];
        }

        x = f[0];

        for (i = seedlen; i < olen; i++)
        {
            DBMASK[i - seedlen] = f[i + 1];
        }

        MGF1(DBMASK, seedlen, SEED);
        for (i = 0; i < seedlen; i++)
        {
            SEED[i] ^= f[i + 1];
        }
        MGF1(SEED, olen - seedlen, f);
        for (i = 0; i < olen - seedlen; i++)
        {
            DBMASK[i] ^= f[i];
        }

        comp = true;
        for (i = 0; i < hlen; i++)
        {
            if (CHASH[i] != DBMASK[i])
            {
                comp = false;
            }
        }

        for (i = 0; i < olen - seedlen - hlen; i++)
        {
            DBMASK[i] = DBMASK[i + hlen];
        }

        for (i = 0; i < hlen; i++)
        {
            SEED[i] = CHASH[i] = 0;
        }

        for (k = 0;; k++)
        {
            if (k >= olen - seedlen - hlen)
            {
                return(new sbyte[0]);
            }
            if (DBMASK[k] != 0)
            {
                break;
            }
        }

        t = DBMASK[k];
        if (!comp || x != 0 || t != 0x01)
        {
            for (i = 0; i < olen - seedlen; i++)
            {
                DBMASK[i] = 0;
            }
            return(new sbyte[0]);
        }

        sbyte[] r = new sbyte[olen - seedlen - hlen - k - 1];

        for (i = 0; i < olen - seedlen - hlen - k - 1; i++)
        {
            r[i] = DBMASK[i + k + 1];
        }

        for (i = 0; i < olen - seedlen; i++)
        {
            DBMASK[i] = 0;
        }

        return(r);
    }
示例#10
0
    /* OAEP Message Encoding for Encryption */
    public static sbyte[] OAEP_ENCODE(sbyte[] m, RAND rng, sbyte[] p)
    {
        int i, slen, olen = RFS - 1;
        int mlen = m.Length;
        int hlen, seedlen;

        sbyte[] f = new sbyte[RFS];

        HASH H = new HASH();

        hlen = HASH.len;
        sbyte[] SEED = new sbyte[hlen];
        seedlen = hlen;
        if (mlen > olen - hlen - seedlen - 1)
        {
            return(new sbyte[0]);
        }

        sbyte[] DBMASK = new sbyte[olen - seedlen];

        if (p != null)
        {
            H.process_array(p);
        }
        sbyte[] h = H.hash();
        for (i = 0; i < hlen; i++)
        {
            f[i] = h[i];
        }

        slen = olen - mlen - hlen - seedlen - 1;

        for (i = 0; i < slen; i++)
        {
            f[hlen + i] = 0;
        }
        f[hlen + slen] = 1;
        for (i = 0; i < mlen; i++)
        {
            f[hlen + slen + 1 + i] = m[i];
        }

        for (i = 0; i < seedlen; i++)
        {
            SEED[i] = (sbyte)rng.Byte;
        }
        MGF1(SEED, olen - seedlen, DBMASK);

        for (i = 0; i < olen - seedlen; i++)
        {
            DBMASK[i] ^= f[i];
        }
        MGF1(DBMASK, seedlen, f);

        for (i = 0; i < seedlen; i++)
        {
            f[i] ^= SEED[i];
        }

        for (i = 0; i < olen - seedlen; i++)
        {
            f[i + seedlen] = DBMASK[i];
        }

        /* pad to length RFS */
        int d = 1;

        for (i = RFS - 1; i >= d; i--)
        {
            f[i] = f[i - d];
        }
        for (i = d - 1; i >= 0; i--)
        {
            f[i] = 0;
        }

        return(f);
    }
示例#11
0
/* calculate common key on server side */
/* Z=r.A - no time permits involved */

    public static int SERVER_KEY(sbyte[] Z, sbyte[] SST, sbyte[] W, sbyte[] xID, sbyte[] xCID, sbyte[] SK)
    {
        HASH H = new HASH();

        sbyte[] t = new sbyte[EFS];

        ECP2 sQ = ECP2.fromBytes(SST);

        if (sQ.is_infinity())
        {
            return(INVALID_POINT);
        }
        ECP R = ECP.fromBytes(Z);

        if (R.is_infinity())
        {
            return(INVALID_POINT);
        }

        ECP U;

        if (xCID != null)
        {
            U = ECP.fromBytes(xCID);
        }
        else
        {
            U = ECP.fromBytes(xID);
        }
        if (U.is_infinity())
        {
            return(INVALID_POINT);
        }

        BIG w = BIG.fromBytes(W);

        U = PAIR.G1mul(U, w);
        FP12 g = PAIR.ate(sQ, R);

        g = PAIR.fexp(g);

        FP4 c = g.trace();

        c.geta().A.toBytes(t);
        H.process_array(t);
        c.geta().B.toBytes(t);
        H.process_array(t);
        c.getb().A.toBytes(t);
        H.process_array(t);
        c.getb().B.toBytes(t);
        H.process_array(t);

        U.X.toBytes(t);
        H.process_array(t);
        U.Y.toBytes(t);
        H.process_array(t);

        t = H.hash();
        for (int i = 0; i < PAS; i++)
        {
            SK[i] = t[i];
        }

        return(0);
    }
示例#12
0
/* calculate common key on client side */
/* wCID = w.(A+AT) */
    public static int CLIENT_KEY(sbyte[] G1, sbyte[] G2, int pin, sbyte[] R, sbyte[] X, sbyte[] wCID, sbyte[] CK)
    {
        HASH H = new HASH();

        sbyte[] t = new sbyte[EFS];

        FP12 g1 = FP12.fromBytes(G1);
        FP12 g2 = FP12.fromBytes(G2);
        BIG  z  = BIG.fromBytes(R);
        BIG  x  = BIG.fromBytes(X);

        ECP W = ECP.fromBytes(wCID);

        if (W.is_infinity())
        {
            return(INVALID_POINT);
        }

        W = PAIR.G1mul(W, x);

        FP2 f = new FP2(new BIG(ROM.CURVE_Fra), new BIG(ROM.CURVE_Frb));
        BIG r = new BIG(ROM.CURVE_Order);
        BIG q = new BIG(ROM.Modulus);

        BIG m = new BIG(q);

        m.mod(r);

        BIG a = new BIG(z);

        a.mod(m);

        BIG b = new BIG(z);

        b.div(m);

        g2.pinpow(pin, PBLEN);
        g1.mul(g2);

        FP4 c = g1.trace();

        g2.copy(g1);
        g2.frob(f);
        FP4 cp = g2.trace();

        g1.conj();
        g2.mul(g1);
        FP4 cpm1 = g2.trace();

        g2.mul(g1);
        FP4 cpm2 = g2.trace();

        c = c.xtr_pow2(cp, cpm1, cpm2, a, b);

        c.geta().A.toBytes(t);
        H.process_array(t);
        c.geta().B.toBytes(t);
        H.process_array(t);
        c.getb().A.toBytes(t);
        H.process_array(t);
        c.getb().B.toBytes(t);
        H.process_array(t);

        W.X.toBytes(t);
        H.process_array(t);
        W.Y.toBytes(t);
        H.process_array(t);

        t = H.hash();
        for (int i = 0; i < PAS; i++)
        {
            CK[i] = t[i];
        }

        return(0);
    }