Ejemplo n.º 1
0
        public AsymmetricCipherKeyPair GenerateKeyPair()
        {
            Tree.leafaddr a = new Tree.leafaddr();

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

            random.NextBytes(sk);

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

            Array.Copy(sk, SPHINCS256Config.SEED_BYTES, pk, 0, Horst.N_MASKS * SPHINCS256Config.HASH_BYTES);

            // Initialization of top-subtree address
            a.level   = SPHINCS256Config.N_LEVELS - 1;
            a.subtree = 0;
            a.subleaf = 0;

            HashFunctions hs = new HashFunctions(treeDigest);

            // Format pk: [|N_MASKS*params.HASH_BYTES| Bitmasks || root]
            // Construct top subtree
            Tree.treehash(hs, pk, (Horst.N_MASKS * SPHINCS256Config.HASH_BYTES), SPHINCS256Config.SUBTREE_HEIGHT, sk, a, pk, 0);

            return(new AsymmetricCipherKeyPair(new SphincsPublicKeyParameters(pk), new SphincsPrivateKeyParameters(sk)));
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        internal static void get_seed(HashFunctions hs, byte[] seed, int seedOff, byte[] sk, Tree.leafaddr a)
        {
            byte[] buffer = new byte[SPHINCS256Config.SEED_BYTES + 8];
            ulong  t;
            int    i;

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

            //4 bits to encode level
            t = (uint)a.level;
            //55 bits to encode subtree
            t |= a.subtree << 4;
            //5 bits to encode leaf
            t |= a.subleaf << 59;

            Pack.UInt64_To_LE(t, buffer, SPHINCS256Config.SEED_BYTES);

            hs.varlen_hash(seed, seedOff, buffer, buffer.Length);
        }
Ejemplo n.º 4
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);
        }