Esempio n. 1
0
        /// <summary>
        ///     Computes the <seealso cref="ChecksumTable" /> for this cache. The checksum table
        ///     forms part of the so-called "update keys".
        /// </summary>
        /// <returns> The <seealso cref="ChecksumTable" />. </returns>
        /// <exception cref="IOException"> if an I/O error occurs. </exception>
        public ChecksumTable CreateChecksumTable()
        {
            /* create the checksum table */
            var size  = store.GetTypeCount();
            var table = new ChecksumTable(size);

            /* loop through all the reference tables and get their CRC and versions */
            for (var i = 0; i < size; i++)
            {
                var buf = store.Read(255, i);

                var crc       = 0;
                var version   = 0;
                var whirlpool = new byte[64];

                /*
                 * if there is actually a reference table, calculate the CRC,
                 * version and whirlpool hash
                 */
                if (buf.limit() > 0) // some indices are not used, is this appropriate?
                {
                    var @ref = ReferenceTable.Decode(Container.Decode(buf)
                                                     .GetData());
                    crc     = ByteBufferExtensions.GetCrcChecksum(buf);
                    version = @ref.GetVersion();
                    buf.position(0);
                    whirlpool = ByteBufferExtensions.GetWhirlpoolDigest(buf);
                }

                table.SetEntry(i, new ChecksumTable.Entry(crc, version, whirlpool));
            }

            /* return the table */
            return(table);
        }
        /// <summary>
        ///     Decodes the <seealso cref="ChecksumTable" /> in the specified
        ///     <seealso cref="ByteBuffer" /> and decrypts the final whirlpool hash.
        /// </summary>
        /// <param name="buffer"> The <seealso cref="ByteBuffer" /> containing the table. </param>
        /// <param name="whirlpool"> If whirlpool digests should be read. </param>
        /// <param name="modulus"> The modulus. </param>
        /// <param name="publicKey"> The public key. </param>
        /// <returns> The decoded <seealso cref="ChecksumTable" />. </returns>
        /// <exception cref="IOException"> if an I/O error occurs. </exception>
        public static ChecksumTable Decode(ByteBuffer buffer, bool whirlpool, BigInteger modulus, BigInteger publicKey)
        {
            /* find out how many entries there are and allocate a new table */
            var size  = whirlpool ? (buffer.limit() / 8) : (buffer.get() & 0xFF);
            var table = new ChecksumTable(size);

            /* calculate the whirlpool digest we expect to have at the end */
            byte[] masterDigest = null;
            if (whirlpool)
            {
                var temp = new byte[size * 72 + 1];
                buffer.position(0);
                buffer.get(temp);
                masterDigest = Whirlpool.Crypt(temp, 0, temp.Length);
            }

            /* read the entries */
            buffer.position(1);
            for (var i = 0; i < size; i++)
            {
                var crc     = buffer.getInt();
                var version = buffer.getInt();
                var digest  = new byte[64];
                if (whirlpool)
                {
                    buffer.get(digest);
                }
                table.entries[i] = new Entry(crc, version, digest);
            }

            /* read the trailing digest and check if it matches up */
            if (whirlpool)
            {
                var bytes = new byte[buffer.remaining()];
                buffer.get(bytes);
                var temp = ByteBuffer.wrap(bytes);

                if (modulus != null && publicKey != null)
                {
                    temp = Rsa.Crypt(buffer, modulus, publicKey);
                }

                if (temp.limit() != 66)
                {
                    throw new IOException("Decrypted data is not 66 bytes long");
                }

                for (var i = 0; i < 64; i++)
                {
                    if (temp.get(i + 1) != masterDigest[i])
                    {
                        throw new IOException("Whirlpool digest mismatch");
                    }
                }
            }

            /* if it looks good return the table */
            return(table);
        }