Exemple #1
0
        bool verify(HashFunctions hs, byte[] m, byte[] sm, byte[] pk)
        {
            int  i;
            int  smlen   = sm.Length;
            long leafidx = 0;

            byte[] wots_pk = new byte[Wots.WOTS_L * SPHINCS256Config.HASH_BYTES];
            byte[] pkhash  = new byte[SPHINCS256Config.HASH_BYTES];
            byte[] root    = new byte[SPHINCS256Config.HASH_BYTES];
            byte[] sig     = new byte[CRYPTO_BYTES];
            int    sigp;

            byte[] tpk = new byte[SPHINCS256Config.CRYPTO_PUBLICKEYBYTES];

            if (smlen != CRYPTO_BYTES)
            {
                throw new ArgumentException("signature wrong size");
            }

            byte[] m_h = new byte[SPHINCS256Config.MSGHASH_BYTES];

            for (i = 0; i < SPHINCS256Config.CRYPTO_PUBLICKEYBYTES; i++)
            {
                tpk[i] = pk[i];
            }

            // construct message hash
            {
                byte[] R = new byte[SPHINCS256Config.MESSAGE_HASH_SEED_BYTES];

                for (i = 0; i < SPHINCS256Config.MESSAGE_HASH_SEED_BYTES; i++)
                {
                    R[i] = sm[i];
                }

                Array.Copy(sm, 0, sig, 0, CRYPTO_BYTES);

                IDigest mHash = hs.getMessageHash();

                // input R
                mHash.BlockUpdate(R, 0, SPHINCS256Config.MESSAGE_HASH_SEED_BYTES);

                // input pub key
                mHash.BlockUpdate(tpk, 0, SPHINCS256Config.CRYPTO_PUBLICKEYBYTES);

                // input message
                mHash.BlockUpdate(m, 0, m.Length);

                mHash.DoFinal(m_h, 0);
            }

            sigp = 0;

            sigp  += SPHINCS256Config.MESSAGE_HASH_SEED_BYTES;
            smlen -= SPHINCS256Config.MESSAGE_HASH_SEED_BYTES;


            for (i = 0; i < (SPHINCS256Config.TOTALTREE_HEIGHT + 7) / 8; i++)
            {
                leafidx ^= ((long)(sig[sigp + i] & 0xff) << (8 * i));
            }


            Horst.horst_verify(hs, root, sig, sigp + (SPHINCS256Config.TOTALTREE_HEIGHT + 7) / 8,
                               tpk, m_h);

            sigp  += (SPHINCS256Config.TOTALTREE_HEIGHT + 7) / 8;
            smlen -= (SPHINCS256Config.TOTALTREE_HEIGHT + 7) / 8;

            sigp  += Horst.HORST_SIGBYTES;
            smlen -= Horst.HORST_SIGBYTES;

            Wots w = new Wots();

            for (i = 0; i < SPHINCS256Config.N_LEVELS; i++)
            {
                w.wots_verify(hs, wots_pk, sig, sigp, root, tpk);

                sigp  += Wots.WOTS_SIGBYTES;
                smlen -= Wots.WOTS_SIGBYTES;

                Tree.l_tree(hs, pkhash, 0, wots_pk, 0, tpk, 0);
                validate_authpath(hs, root, pkhash, (uint)(leafidx & 0x1f), sig, sigp, tpk, SPHINCS256Config.SUBTREE_HEIGHT);
                leafidx >>= 5;

                sigp  += SPHINCS256Config.SUBTREE_HEIGHT * SPHINCS256Config.HASH_BYTES;
                smlen -= SPHINCS256Config.SUBTREE_HEIGHT * SPHINCS256Config.HASH_BYTES;
            }

            bool verified = true;

            for (i = 0; i < SPHINCS256Config.HASH_BYTES; i++)
            {
                if (root[i] != tpk[i + Horst.N_MASKS * SPHINCS256Config.HASH_BYTES])
                {
                    verified = false;
                }
            }

            return(verified);
        }
Exemple #2
0
        byte[] crypto_sign(HashFunctions hs, byte[] m, byte[] sk)
        {
            byte[] sm = new byte[CRYPTO_BYTES];
            int    i;
            ulong  leafidx;

            byte[]  R   = new byte[SPHINCS256Config.MESSAGE_HASH_SEED_BYTES];
            byte[]  m_h = new byte[SPHINCS256Config.MSGHASH_BYTES];
            ulong[] rnd = new ulong[8];

            byte[] root  = new byte[SPHINCS256Config.HASH_BYTES];
            byte[] seed  = new byte[SPHINCS256Config.SEED_BYTES];
            byte[] masks = new byte[Horst.N_MASKS * SPHINCS256Config.HASH_BYTES];
            int    pk;

            byte[] tsk = new byte[SPHINCS256Config.CRYPTO_SECRETKEYBYTES];

            for (i = 0; i < SPHINCS256Config.CRYPTO_SECRETKEYBYTES; i++)
            {
                tsk[i] = sk[i];
            }

            // create leafidx deterministically
            {
                // shift scratch upwards so we can reuse msg later
                int scratch = CRYPTO_BYTES - SPHINCS256Config.SK_RAND_SEED_BYTES;

                // Copy secret random seed to scratch
                Array.Copy(tsk, SPHINCS256Config.CRYPTO_SECRETKEYBYTES - SPHINCS256Config.SK_RAND_SEED_BYTES, sm, scratch, SPHINCS256Config.SK_RAND_SEED_BYTES);

                IDigest d    = hs.getMessageHash();
                byte[]  bRnd = new byte[d.GetDigestSize()];

                d.BlockUpdate(sm, scratch, SPHINCS256Config.SK_RAND_SEED_BYTES);

                d.BlockUpdate(m, 0, m.Length);

                d.DoFinal(bRnd, 0);
                // wipe sk
                zerobytes(sm, scratch, SPHINCS256Config.SK_RAND_SEED_BYTES);

                for (int j = 0; j != rnd.Length; j++)
                {
                    rnd[j] = Pack.LE_To_UInt64(bRnd, j * 8);
                }
                leafidx = rnd[0] & 0xfffffffffffffffUL;

                Array.Copy(bRnd, 16, R, 0, SPHINCS256Config.MESSAGE_HASH_SEED_BYTES);

                // prepare msg_hash
                scratch = CRYPTO_BYTES - SPHINCS256Config.MESSAGE_HASH_SEED_BYTES - SPHINCS256Config.CRYPTO_PUBLICKEYBYTES;

                // cpy R
                Array.Copy(R, 0, sm, scratch, SPHINCS256Config.MESSAGE_HASH_SEED_BYTES);

                // construct and cpy pk
                Tree.leafaddr b = new Tree.leafaddr();
                b.level   = SPHINCS256Config.N_LEVELS - 1;
                b.subtree = 0;
                b.subleaf = 0;

                pk = scratch + SPHINCS256Config.MESSAGE_HASH_SEED_BYTES;

                Array.Copy(tsk, SPHINCS256Config.SEED_BYTES, sm, pk, Horst.N_MASKS * SPHINCS256Config.HASH_BYTES);

                Tree.treehash(hs, sm, pk + (Horst.N_MASKS * SPHINCS256Config.HASH_BYTES), SPHINCS256Config.SUBTREE_HEIGHT, tsk, b, sm, pk);

                d = hs.getMessageHash();

                d.BlockUpdate(sm, scratch, SPHINCS256Config.MESSAGE_HASH_SEED_BYTES + SPHINCS256Config.CRYPTO_PUBLICKEYBYTES);
                d.BlockUpdate(m, 0, m.Length);
                d.DoFinal(m_h, 0);
            }

            Tree.leafaddr a = new Tree.leafaddr();

            a.level   = SPHINCS256Config.N_LEVELS; // Use unique value $d$ for HORST address.
            a.subleaf = (leafidx & (1UL << SPHINCS256Config.SUBTREE_HEIGHT) - 1);
            a.subtree = (leafidx >> SPHINCS256Config.SUBTREE_HEIGHT);

            int smlen = 0;

            for (i = 0; i < SPHINCS256Config.MESSAGE_HASH_SEED_BYTES; i++)
            {
                sm[i] = R[i];
            }

            int smOff = SPHINCS256Config.MESSAGE_HASH_SEED_BYTES;

            smlen += SPHINCS256Config.MESSAGE_HASH_SEED_BYTES;

            Array.Copy(tsk, SPHINCS256Config.SEED_BYTES, masks, 0, Horst.N_MASKS * SPHINCS256Config.HASH_BYTES);
            for (i = 0; i < (SPHINCS256Config.TOTALTREE_HEIGHT + 7) / 8; i++)
            {
                sm[smOff + i] = (byte)((leafidx >> 8 * i) & 0xff);
            }

            smOff += (SPHINCS256Config.TOTALTREE_HEIGHT + 7) / 8;
            smlen += (SPHINCS256Config.TOTALTREE_HEIGHT + 7) / 8;

            Seed.get_seed(hs, seed, 0, tsk, a);

            int horst_sigbytes = Horst.horst_sign(hs, sm, smOff, root, seed, masks, m_h);

            smOff += horst_sigbytes;
            smlen += horst_sigbytes;

            Wots w = new Wots();

            for (i = 0; i < SPHINCS256Config.N_LEVELS; i++)
            {
                a.level = i;

                Seed.get_seed(hs, seed, 0, tsk, a); //XXX: Don't use the same address as for horst_sign here!

                w.wots_sign(hs, sm, smOff, root, seed, masks);

                smOff += Wots.WOTS_SIGBYTES;
                smlen += Wots.WOTS_SIGBYTES;

                compute_authpath_wots(hs, root, sm, smOff, a, tsk, masks, SPHINCS256Config.SUBTREE_HEIGHT);
                smOff += SPHINCS256Config.SUBTREE_HEIGHT * SPHINCS256Config.HASH_BYTES;
                smlen += SPHINCS256Config.SUBTREE_HEIGHT * SPHINCS256Config.HASH_BYTES;

                a.subleaf   = (a.subtree & ((1UL << SPHINCS256Config.SUBTREE_HEIGHT) - 1));
                a.subtree >>= SPHINCS256Config.SUBTREE_HEIGHT;
            }

            zerobytes(tsk, 0, SPHINCS256Config.CRYPTO_SECRETKEYBYTES);

            return(sm);
        }