Beispiel #1
0
        static void validate_authpath(HashFunctions hs, byte[] root, byte[] leaf, uint leafidx, byte[] authpath, int auOff, byte[] masks, int height)
        {
            int i, j;

            byte[] buffer = new byte[2 * SPHINCS256Config.HASH_BYTES];

            if ((leafidx & 1) != 0)
            {
                for (j = 0; j < SPHINCS256Config.HASH_BYTES; j++)
                {
                    buffer[SPHINCS256Config.HASH_BYTES + j] = leaf[j];
                }
                for (j = 0; j < SPHINCS256Config.HASH_BYTES; j++)
                {
                    buffer[j] = authpath[auOff + j];
                }
            }
            else
            {
                for (j = 0; j < SPHINCS256Config.HASH_BYTES; j++)
                {
                    buffer[j] = leaf[j];
                }
                for (j = 0; j < SPHINCS256Config.HASH_BYTES; j++)
                {
                    buffer[SPHINCS256Config.HASH_BYTES + j] = authpath[auOff + j];
                }
            }
            int authOff = auOff + SPHINCS256Config.HASH_BYTES;

            for (i = 0; i < height - 1; i++)
            {
                leafidx >>= 1;
                if ((leafidx & 1) != 0)
                {
                    hs.hash_2n_n_mask(buffer, SPHINCS256Config.HASH_BYTES, buffer, 0, masks, 2 * (Wots.WOTS_LOG_L + i) * SPHINCS256Config.HASH_BYTES);
                    for (j = 0; j < SPHINCS256Config.HASH_BYTES; j++)
                    {
                        buffer[j] = authpath[authOff + j];
                    }
                }
                else
                {
                    hs.hash_2n_n_mask(buffer, 0, buffer, 0, masks, 2 * (Wots.WOTS_LOG_L + i) * SPHINCS256Config.HASH_BYTES);
                    for (j = 0; j < SPHINCS256Config.HASH_BYTES; j++)
                    {
                        buffer[j + SPHINCS256Config.HASH_BYTES] = authpath[authOff + j];
                    }
                }
                authOff += SPHINCS256Config.HASH_BYTES;
            }
            hs.hash_2n_n_mask(root, 0, buffer, 0, masks, 2 * (Wots.WOTS_LOG_L + height - 1) * SPHINCS256Config.HASH_BYTES);
        }
Beispiel #2
0
        internal static void treehash(HashFunctions hs, byte[] node, int nodeOff, int height, byte[] sk, leafaddr leaf, byte[] masks, int masksOff)
        {
            leafaddr a = new leafaddr(leaf);
            ulong    lastnode;
            int      i;

            byte[] stack       = new byte[(height + 1) * SPHINCS256Config.HASH_BYTES];
            int[]  stacklevels = new int[height + 1];
            int    stackoffset = 0;

            lastnode = a.subleaf + (1UL << height);

            for (; a.subleaf < lastnode; a.subleaf++)
            {
                gen_leaf_wots(hs, stack, stackoffset * SPHINCS256Config.HASH_BYTES, masks, masksOff, sk, a);
                stacklevels[stackoffset] = 0;
                stackoffset++;
                while (stackoffset > 1 && stacklevels[stackoffset - 1] == stacklevels[stackoffset - 2])
                {
                    //MASKS
                    int maskoffset = 2 * (stacklevels[stackoffset - 1] + Wots.WOTS_LOG_L) * SPHINCS256Config.HASH_BYTES;

                    hs.hash_2n_n_mask(stack, (stackoffset - 2) * SPHINCS256Config.HASH_BYTES, stack, (stackoffset - 2) * SPHINCS256Config.HASH_BYTES,
                                      masks, masksOff + maskoffset);
                    stacklevels[stackoffset - 2]++;
                    stackoffset--;
                }
            }
            for (i = 0; i < SPHINCS256Config.HASH_BYTES; i++)
            {
                node[nodeOff + i] = stack[i];
            }
        }
Beispiel #3
0
        static void compute_authpath_wots(HashFunctions hs, byte[] root, byte[] authpath, int authOff, Tree.leafaddr a, byte[] sk, byte[] masks, int height)
        {
            int  i, j;
            uint idx;

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

            byte[] tree = new byte[2 * (1 << SPHINCS256Config.SUBTREE_HEIGHT) * SPHINCS256Config.HASH_BYTES];
            byte[] seed = new byte[(1 << SPHINCS256Config.SUBTREE_HEIGHT) * SPHINCS256Config.SEED_BYTES];
            byte[] pk   = new byte[(1 << SPHINCS256Config.SUBTREE_HEIGHT) * Wots.WOTS_L * SPHINCS256Config.HASH_BYTES];

            // level 0
            for (ta.subleaf = 0; ta.subleaf < (1UL << SPHINCS256Config.SUBTREE_HEIGHT); ta.subleaf++)
            {
                Seed.get_seed(hs, seed, (int)(ta.subleaf * (ulong)SPHINCS256Config.SEED_BYTES), sk, ta);
            }

            Wots w = new Wots();

            for (ta.subleaf = 0; ta.subleaf < (1UL << SPHINCS256Config.SUBTREE_HEIGHT); ta.subleaf++)
            {
                w.wots_pkgen(hs, pk, (int)(ta.subleaf * (ulong)Wots.WOTS_L * (ulong)SPHINCS256Config.HASH_BYTES), seed, (int)(ta.subleaf * (ulong)SPHINCS256Config.SEED_BYTES), masks, 0);
            }

            for (ta.subleaf = 0; ta.subleaf < (1UL << SPHINCS256Config.SUBTREE_HEIGHT); ta.subleaf++)
            {
                Tree.l_tree(hs, tree, (int)((1UL << SPHINCS256Config.SUBTREE_HEIGHT) * (ulong)SPHINCS256Config.HASH_BYTES + ta.subleaf * (ulong)SPHINCS256Config.HASH_BYTES),
                            pk, (int)(ta.subleaf * (ulong)Wots.WOTS_L * (ulong)SPHINCS256Config.HASH_BYTES), masks, 0);
            }

            int level = 0;

            // tree
            for (i = (1 << SPHINCS256Config.SUBTREE_HEIGHT); i > 0; i >>= 1)
            {
                for (j = 0; j < i; j += 2)
                {
                    hs.hash_2n_n_mask(tree, (i >> 1) * SPHINCS256Config.HASH_BYTES + (j >> 1) * SPHINCS256Config.HASH_BYTES,
                                      tree, i * SPHINCS256Config.HASH_BYTES + j * SPHINCS256Config.HASH_BYTES,
                                      masks, 2 * (Wots.WOTS_LOG_L + level) * SPHINCS256Config.HASH_BYTES);
                }

                level++;
            }


            idx = (uint)a.subleaf;

            // copy authpath
            for (i = 0; i < height; i++)
            {
                Array.Copy(tree, ((1 << SPHINCS256Config.SUBTREE_HEIGHT) >> i) * SPHINCS256Config.HASH_BYTES + ((idx >> i) ^ 1) * SPHINCS256Config.HASH_BYTES, authpath, authOff + i * SPHINCS256Config.HASH_BYTES, SPHINCS256Config.HASH_BYTES);
            }

            // copy root
            Array.Copy(tree, SPHINCS256Config.HASH_BYTES, root, 0, SPHINCS256Config.HASH_BYTES);
        }
Beispiel #4
0
        internal static void l_tree(HashFunctions hs, byte[] leaf, int leafOff, byte[] wots_pk, int pkOff, byte[] masks, int masksOff)
        {
            uint l = (uint)Wots.WOTS_L;
            int  i, j = 0;

            for (i = 0; i < Wots.WOTS_LOG_L; i++)
            {
                for (j = 0; j < (l >> 1); j++)
                {
                    hs.hash_2n_n_mask(wots_pk, pkOff + j * SPHINCS256Config.HASH_BYTES, wots_pk, pkOff + j * 2 * SPHINCS256Config.HASH_BYTES, masks, masksOff + i * 2 * SPHINCS256Config.HASH_BYTES);
                }

                if ((l & 1) != 0)
                {
                    Array.Copy(wots_pk, pkOff + (l - 1) * SPHINCS256Config.HASH_BYTES, wots_pk, pkOff + (l >> 1) * SPHINCS256Config.HASH_BYTES, SPHINCS256Config.HASH_BYTES);
                    l = (l >> 1) + 1;
                }
                else
                {
                    l = (l >> 1);
                }
            }
            Array.Copy(wots_pk, pkOff, leaf, leafOff, SPHINCS256Config.HASH_BYTES);
        }
Beispiel #5
0
        internal static int horst_verify(HashFunctions hs, byte[] pk, byte[] sig, int sigOff, byte[] masks, byte[] m_hash)
        {
            byte[] buffer = new byte[32 * HASH_BYTES];

            uint idx;
            int  i, j, k;

            int sigOffset = sigOff + 64 * HASH_BYTES;

            for (i = 0; i < HORST_K; i++)
            {
                idx = (uint)((m_hash[2 * i] & 0xff) + ((m_hash[2 * i + 1] & 0xff) << 8));

                if ((idx & 1) == 0)
                {
                    hs.hash_n_n(buffer, 0, sig, sigOffset);
                    for (k = 0; k < HASH_BYTES; k++)
                    {
                        buffer[HASH_BYTES + k] = sig[sigOffset + HORST_SKBYTES + k];
                    }
                }
                else
                {
                    hs.hash_n_n(buffer, HASH_BYTES, sig, sigOffset);
                    for (k = 0; k < HASH_BYTES; k++)
                    {
                        buffer[k] = sig[sigOffset + HORST_SKBYTES + k];
                    }
                }
                sigOffset += HORST_SKBYTES + HASH_BYTES;

                for (j = 1; j < HORST_LOGT - 6; j++)
                {
                    idx = idx >> 1; // parent node

                    if ((idx & 1) == 0)
                    {
                        hs.hash_2n_n_mask(buffer, 0, buffer, 0, masks, 2 * (j - 1) * HASH_BYTES);
                        for (k = 0; k < HASH_BYTES; k++)
                        {
                            buffer[HASH_BYTES + k] = sig[sigOffset + k];
                        }
                    }
                    else
                    {
                        hs.hash_2n_n_mask(buffer, HASH_BYTES, buffer, 0, masks, 2 * (j - 1) * HASH_BYTES);
                        for (k = 0; k < HASH_BYTES; k++)
                        {
                            buffer[k] = sig[sigOffset + k];
                        }
                    }
                    sigOffset += HASH_BYTES;
                }

                idx = idx >> 1; // parent node
                hs.hash_2n_n_mask(buffer, 0, buffer, 0, masks, 2 * (HORST_LOGT - 7) * HASH_BYTES);

                for (k = 0; k < HASH_BYTES; k++)
                {
                    if (sig[sigOff + idx * HASH_BYTES + k] != buffer[k])
                    {
                        for (k = 0; k < HASH_BYTES; k++)
                        {
                            pk[k] = 0;
                        }
                        return(-1);
                    }
                }
            }

            // Compute root from level10
            for (j = 0; j < 32; j++)
            {
                hs.hash_2n_n_mask(buffer, j * HASH_BYTES, sig, sigOff + 2 * j * HASH_BYTES, masks, 2 * (HORST_LOGT - 6) * HASH_BYTES);
            }
            // Hash from level 11 to 12
            for (j = 0; j < 16; j++)
            {
                hs.hash_2n_n_mask(buffer, j * HASH_BYTES, buffer, 2 * j * HASH_BYTES, masks, 2 * (HORST_LOGT - 5) * HASH_BYTES);
            }
            // Hash from level 12 to 13
            for (j = 0; j < 8; j++)
            {
                hs.hash_2n_n_mask(buffer, j * HASH_BYTES, buffer, 2 * j * HASH_BYTES, masks, 2 * (HORST_LOGT - 4) * HASH_BYTES);
            }
            // Hash from level 13 to 14
            for (j = 0; j < 4; j++)
            {
                hs.hash_2n_n_mask(buffer, j * HASH_BYTES, buffer, 2 * j * HASH_BYTES, masks, 2 * (HORST_LOGT - 3) * HASH_BYTES);
            }
            // Hash from level 14 to 15
            for (j = 0; j < 2; j++)
            {
                hs.hash_2n_n_mask(buffer, j * HASH_BYTES, buffer, 2 * j * HASH_BYTES, masks, 2 * (HORST_LOGT - 2) * HASH_BYTES);
            }
            // Hash from level 15 to 16

            hs.hash_2n_n_mask(pk, 0, buffer, 0, masks, 2 * (HORST_LOGT - 1) * HASH_BYTES);

            return(0);
        }
Beispiel #6
0
        internal static int horst_sign(HashFunctions hs,
                                       byte[] sig, int sigOff, byte[] pk,
                                       byte[] seed,
                                       byte[] masks,
                                       byte[] m_hash)
        {
            byte[] sk = new byte[HORST_T * HORST_SKBYTES];
            uint   idx;
            int    i, j, k;
            int    sigpos = sigOff;

            byte[] tree = new byte[(2 * HORST_T - 1) * HASH_BYTES]; /* replace by something more memory-efficient? */

            expand_seed(sk, seed);

            // Build the whole tree and save it

            // Generate pk leaves
            for (i = 0; i < HORST_T; i++)
            {
                hs.hash_n_n(tree, (HORST_T - 1 + i) * HASH_BYTES, sk, i * HORST_SKBYTES);
            }

            long offset_in, offset_out;

            for (i = 0; i < HORST_LOGT; i++)
            {
                offset_in  = (1 << (HORST_LOGT - i)) - 1;
                offset_out = (1 << (HORST_LOGT - i - 1)) - 1;
                for (j = 0; j < (1 << (HORST_LOGT - i - 1)); j++)
                {
                    hs.hash_2n_n_mask(tree, (int)((offset_out + j) * HASH_BYTES), tree, (int)((offset_in + 2 * j) * HASH_BYTES), masks, 2 * i * HASH_BYTES);
                }
            }

            // First write 64 hashes from level 10 to the signature
            for (j = 63 * HASH_BYTES; j < 127 * HASH_BYTES; j++)
            {
                sig[sigpos++] = tree[j];
            }

            // Signature consists of HORST_K parts; each part of secret key and HORST_LOGT-4 auth-path hashes
            for (i = 0; i < HORST_K; i++)
            {
                idx = (uint)((m_hash[2 * i] & 0xff) + ((m_hash[2 * i + 1] & 0xff) << 8));

                for (k = 0; k < HORST_SKBYTES; k++)
                {
                    sig[sigpos++] = sk[idx * HORST_SKBYTES + k];
                }

                idx += (uint)(HORST_T - 1);
                for (j = 0; j < HORST_LOGT - 6; j++)
                {
                    idx = ((idx & 1) != 0) ? idx + 1 : idx - 1; // neighbor node
                    for (k = 0; k < HASH_BYTES; k++)
                    {
                        sig[sigpos++] = tree[idx * HASH_BYTES + k];
                    }
                    idx = (idx - 1) / 2; // parent node
                }
            }

            for (i = 0; i < HASH_BYTES; i++)
            {
                pk[i] = tree[i];
            }

            return(HORST_SIGBYTES);
        }