示例#1
0
        private IEnumerable <byte> P_hash(byte[] secret, byte[] seed)
        {
            var hmac = new HMAC(_digest, secret);

            var a = seed;

            while (true)
            {
                hmac.Reset();
                hmac.Update(a);
                a = hmac.DigestBuffer();

                hmac.Reset();
                hmac.Update(a);
                hmac.Update(seed);

                var b = hmac.DigestBuffer();
                foreach (var x in b)
                {
                    yield return(x);
                }
            }
        }
示例#2
0
        public void VerifyHMAC(MessageDigest digest, string[] results)
        {
            byte[] hash = HMAC.Digest(digest, key, small_data);
            string str  = BitConverter.ToString(hash);

            if (str != results[0])
            {
                Console.WriteLine("{0} - Failed to calculate hash on {1}", digest.Name, small_data);
                Console.WriteLine("got {0} instead of {1}", str, results[0]);
            }
            else
            {
                Console.WriteLine("{0} - Test 1 passed.", digest.Name);
            }
            // Compute the large hash
            using (HMAC hmac = new HMAC())
            {
                byte[] buf = Encoding.ASCII.GetBytes(new string('a', 1000));
                hmac.Init(key, digest);
                for (int i = 0; i < 1000; i++)
                {
                    hmac.Update(buf);
                }
                hash = hmac.DigestFinal();
                // Check for error
                str = BitConverter.ToString(hash);
                if (str != results[1])
                {
                    Console.WriteLine("{0} - Failed to calculate hash on a*1000", digest.Name);
                    Console.WriteLine("got {0} instead of {1}", str, results[1]);
                }
                else
                {
                    Console.WriteLine("{0} - Test 2 passed.", digest.Name);
                }
            }
        }
示例#3
0
        /*
         * This function computes Phash with the specified HMAC
         * engine, XORing the output with the current contents of
         * the outBuf[] buffer.
         */
        static void Phash(HMAC hm, byte[] s, int soff, int slen,
                          byte[] bufa, byte[] bufb,
                          byte[] label, byte[] seed,
                          byte[] outBuf, int outOff, int outLen)
        {
            /*
             * Set the key for HMAC.
             */
            hm.SetKey(s, soff, slen);

            /*
             * Compute A(1) = HMAC(secret, seed).
             */
            hm.Update(label);
            hm.Update(seed);
            hm.DoFinal(bufa, 0);
            while (outLen > 0)
            {
                /*
                 * Next chunk: HMAC(secret, A(i) + label + seed)
                 */
                hm.Update(bufa);
                hm.Update(label);
                hm.Update(seed);
                hm.DoFinal(bufb, 0);
                int clen = Math.Min(hm.MACSize, outLen);
                for (int i = 0; i < clen; i++)
                {
                    outBuf[outOff++] ^= bufb[i];
                }
                outLen -= clen;

                /*
                 * If we are not finished, then compute:
                 * A(i+1) = HMAC(secret, A(i))
                 */
                if (outLen > 0)
                {
                    hm.Update(bufa);
                    hm.DoFinal(bufa, 0);
                }
            }
        }
    void DecryptStream(Stream encryptedStream, Stream output)
    {
        using (BinaryReader reader = new BinaryReader(encryptedStream))
            using (BinaryWriter writer = new BinaryWriter(output))
            {
                //Read file header
                byte[] headerNonce;
                byte[] ciphertextPayload;
                byte[] mac;
                byte[] contentKey;
                byte[] cleartextPayload;

                headerNonce       = reader.ReadBytes(16);
                ciphertextPayload = reader.ReadBytes(40);
                mac = reader.ReadBytes(32);

                HMAC headerHmac = new HMAC(macKey);
                headerHmac.Update(headerNonce);
                headerHmac.DoFinal(ciphertextPayload);
                if (!headerHmac.Hash.SequenceEqual(mac))
                {
                    throw new IOException("Encrypted file fails integrity check.");
                }

                cleartextPayload = AesCtr(ciphertextPayload, masterKey, headerNonce);
                contentKey       = Slice(cleartextPayload, 8, 32);

                HMAC chunkHmac = new HMAC(macKey);

                //Process all chunks
                for (int blocknum = 0; ; ++blocknum)
                {
                    //read file content payload
                    byte[] chunk;
                    chunk = reader.ReadBytes(32768 + 48);
                    if (chunk.Length == 0)
                    {
                        break;
                    }

                    var chunkNonce   = Slice(chunk, 0, 16);
                    var chunkpayload = Slice(chunk, chunkNonce.Length, chunk.Length - 48);
                    var chunkmac     = Slice(chunk, chunkNonce.Length + chunkpayload.Length, 32);


                    byte[] beBlockNum = BitConverter.GetBytes((long)blocknum);
                    if (BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(beBlockNum);
                    }

                    chunkHmac.Initialize();
                    chunkHmac.Update(headerNonce);
                    chunkHmac.Update(beBlockNum);
                    chunkHmac.Update(chunkNonce);
                    chunkHmac.DoFinal(chunkpayload);
                    if (!chunkHmac.Hash.SequenceEqual(chunkmac))
                    {
                        throw new IOException("Encrypted file fails integrity check.");
                    }

                    var decryptedContent = AesCtr(chunkpayload, contentKey, chunkNonce);
                    writer.Write(decryptedContent);
                }
            }
    }
示例#5
0
        void EncryptInner(int recordType, int version,
                          byte[] data, ref int off, ref int len)
        {
            int blen = bc.BlockSize;
            int mlen = hm.MACSize;
            int doff = off;
            int dlen = len;

            if (explicitIV)
            {
                /*
                 * To make pseudorandom IV, we reuse HMAC, computed
                 * over the encoded sequence number. Since this
                 * input is distinct from all other HMAC inputs with
                 * the same key, this should be randomish enough
                 * (assuming HMAC is a good imitation of a random
                 * oracle).
                 */
                IO.Enc64be(seq, tmp, 0);
                hm.Update(tmp, 0, 8);
                hm.DoFinal(tmp, 0);
                Array.Copy(tmp, 0, data, off - blen, blen);
                off -= blen;
                len += blen;
            }

            /*
             * Compute HMAC.
             */
            IO.Enc64be(seq, tmp, 0);
            IO.WriteHeader(recordType, version, dlen, tmp, 8);
            hm.Update(tmp, 0, 13);
            hm.Update(data, doff, dlen);
            hm.DoFinal(data, off + len);
            len += mlen;
            seq++;

            /*
             * Add padding.
             */
            int plen = blen - (len & (blen - 1));

            for (int i = 0; i < plen; i++)
            {
                data[off + len + i] = (byte)(plen - 1);
            }
            len += plen;

            /*
             * Perform CBC encryption. We use our saved IV. If there is
             * an explicit IV, then it gets encrypted, which is fine
             * (CBC encryption of randomness is equally good randomness).
             */
            bc.CBCEncrypt(iv, data, off, len);
            Array.Copy(data, off + len - blen, iv, 0, blen);

            /*
             * Add the header.
             */
            off -= 5;
            IO.WriteHeader(recordType, version, len, data, off);
            len += 5;
        }
示例#6
0
        internal override bool Decrypt(int recordType, int version,
                                       byte[] data, ref int off, ref int len)
        {
            int blen = bc.BlockSize;
            int hlen = hm.MACSize;

            /*
             * Grab a copy of the last encrypted block; this is
             * the "saved IV" for the next record.
             */
            Array.Copy(data, off + len - blen, ivTmp, 0, blen);

            /*
             * Decrypt the data. The length has already been
             * checked. If there is an explicit IV, it gets
             * "decrypted" as well, which is not a problem.
             */
            bc.CBCDecrypt(iv, data, off, len);
            Array.Copy(ivTmp, 0, iv, 0, blen);
            if (explicitIV)
            {
                off += blen;
                len -= blen;
            }

            /*
             * Compute minimum and maximum length of plaintext + MAC.
             * These can be inferred from the observable record length,
             * and thus are not secret.
             */
            int minLen = (hlen + 256 < len) ? len - 256 : hlen;
            int maxLen = len - 1;

            /*
             * Get the actual padding length and check padding. The
             * padding length must match the minLen/maxLen range.
             */
            int padLen     = data[off + len - 1];
            int good       = ~(((maxLen - minLen) - padLen) >> 31);
            int lenWithMAC = minLen ^ (good & (minLen ^ (maxLen - padLen)));
            int dbb        = 0;

            for (int i = minLen; i < maxLen; i++)
            {
                dbb |= ~((i - lenWithMAC) >> 31)
                       & (data[off + i] ^ padLen);
            }
            good &= ~((dbb | -dbb) >> 31);

            /*
             * Extract the MAC value; this is done in one pass, but
             * results in a "rotate" MAC value. The rotation count
             * is kept in 'rotCount': this is the offset of the
             * first MAC value byte in tmp1[].
             */
            int lenNoMAC = lenWithMAC - hlen;

            minLen -= hlen;
            int rotCount = 0;

            for (int i = 0; i < hlen; i++)
            {
                tmp1[i] = 0;
            }
            int v = 0;

            for (int i = minLen; i < maxLen; i++)
            {
                int m = ~((i - lenNoMAC) >> 31)
                        & ((i - lenWithMAC) >> 31);
                tmp1[v]  |= (byte)(m & data[off + i]);
                m         = i - lenNoMAC;
                rotCount |= ~((m | -m) >> 31) & v;
                if (++v == hlen)
                {
                    v = 0;
                }
            }
            maxLen -= hlen;

            /*
             * Rotate back the MAC value. We do it bit by bit, with
             * 6 iterations; this is good for all MAC value up to
             * and including 64 bytes.
             */
            for (int i = 5; i >= 0; i--)
            {
                int rc = 1 << i;
                if (rc >= hlen)
                {
                    continue;
                }
                int ctl = -((rotCount >> i) & 1);
                for (int j = 0, k = rc; j < hlen; j++)
                {
                    int b1 = tmp1[j];
                    int b2 = tmp1[k];
                    tmp2[j] = (byte)(b1 ^ (ctl & (b1 ^ b2)));
                    if (++k == hlen)
                    {
                        k = 0;
                    }
                }
                Array.Copy(tmp2, 0, tmp1, 0, hlen);
                rotCount &= ~rc;
            }

            /*
             * Recompute the HMAC value. At that point, minLen and
             * maxLen have been adjusted to match the plaintext
             * without the MAC.
             */
            IO.Enc64be(seq++, tmp2, 0);
            IO.WriteHeader(recordType, version, lenNoMAC, tmp2, 8);
            hm.Update(tmp2, 0, 13);
            hm.ComputeCT(data, off, lenNoMAC, minLen, maxLen, tmp2, 0);

            /*
             * Compare MAC values.
             */
            dbb = 0;
            for (int i = 0; i < hlen; i++)
            {
                dbb |= tmp1[i] ^ tmp2[i];
            }
            good &= ~((dbb | -dbb) >> 31);

            /*
             * We must also check that the plaintext length fits in
             * the maximum allowed by the standard (previous check
             * was on the encrypted length).
             */
            good &= (lenNoMAC - 16385) >> 31;
            len   = lenNoMAC;
            return(good != 0);
        }