Example #1
0
        // Initialize the hashing context "ctx" with optional key "key".
        //      1 <= outlen <= 32 gives the digest size in bytes.
        //      Secret key (also <= 32 bytes) is optional (keylen = 0).
        unsafe public static void init(ref Blake2Context ctx, uint outlen,
                                       void *key, uint keylen) // (keylen=0: no key)
        {
            if (outlen == 0 || outlen > 32 || keylen > 32)
            {
                throw new ArgumentException();
            }

            for (uint i = 0; i < 8; i++)             // state, "param block"
            {
                ctx.h[i] = iv[i];
            }
            ctx.h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen;

            ctx.t[0]   = 0;                          // input count low word
            ctx.t[1]   = 0;                          // input count high word
            ctx.c      = 0;                          // pointer within buffer
            ctx.outlen = outlen;

            for (uint i = keylen; i < 64; i++)       // zero input block
            {
                ctx.b[i] = 0;
            }
            if (keylen > 0)
            {
                update(ref ctx, key, keylen);
                ctx.c = 64;                          // at the end
            }
        }
Example #2
0
 // Add "inlen" bytes from "in" into the hash.
 unsafe public static void update(ref Blake2Context ctx,
                                  void *data, uint inlen) // data bytes
 {
     for (uint i = 0; i < inlen; i++)
     {
         if (ctx.c == 64)                     // buffer full ?
         {
             ctx.t[0] += ctx.c;               // add counters
             if (ctx.t[0] < ctx.c)            // carry overflow ?
             {
                 ctx.t[1]++;                  // high word
             }
             compress(ref ctx, false);        // compress (not last)
             ctx.c = 0;                       // counter to zero
         }
         ctx.b[ctx.c++] = ((byte *)data)[i];
     }
 }
Example #3
0
        // Compression function. "last" flag indicates last block.
        unsafe static void compress(ref Blake2Context ctx, bool last)
        {
            uint *v = stackalloc uint[16];
            uint *m = stackalloc uint[16];

            for (uint i = 0; i < 8; i++)             // init work variables
            {
                v[i]     = ctx.h[i];
                v[i + 8] = iv[i];
            }

            v[12] ^= ctx.t[0];                       // low 32 bits of offset
            v[13] ^= ctx.t[1];                       // high 32 bits
            if (last)                                // last block flag set ?
            {
                v[14] = ~v[14];

                fixed(byte *pb = &ctx.b[0])
                for (uint i = 0; i < 16; i++)        // get little-endian words
                    m[i] = getUInt32(&pb[sizeof(uint) * i]);

                for (uint i = 0; i < 10; i++)        // ten rounds
                {
                    mix(ref v[0], ref v[4], ref v[8], ref v[12], m[sigma[i][0]], m[sigma[i][1]]);
                    mix(ref v[1], ref v[5], ref v[9], ref v[13], m[sigma[i][2]], m[sigma[i][3]]);
                    mix(ref v[2], ref v[6], ref v[10], ref v[14], m[sigma[i][4]], m[sigma[i][5]]);
                    mix(ref v[3], ref v[7], ref v[11], ref v[15], m[sigma[i][6]], m[sigma[i][7]]);
                    mix(ref v[0], ref v[5], ref v[10], ref v[15], m[sigma[i][8]], m[sigma[i][9]]);
                    mix(ref v[1], ref v[6], ref v[11], ref v[12], m[sigma[i][10]], m[sigma[i][11]]);
                    mix(ref v[2], ref v[7], ref v[8], ref v[13], m[sigma[i][12]], m[sigma[i][13]]);
                    mix(ref v[3], ref v[4], ref v[9], ref v[14], m[sigma[i][14]], m[sigma[i][15]]);
                }

                for (uint i = 0; i < 8; i++)
                {
                    ctx.h[i] ^= v[i] ^ v[i + 8];
                }
        }

        // Initialize the hashing context "ctx" with optional key "key".
        //      1 <= outlen <= 32 gives the digest size in bytes.
        //      Secret key (also <= 32 bytes) is optional (keylen = 0).
        unsafe public static void init(ref Blake2Context ctx, uint outlen,
Example #4
0
        // Generate the message digest (size given in init).
        //      Result placed in "out".
        unsafe public static void final(ref Blake2Context ctx, void *hash)
        {
            ctx.t[0] += ctx.c;                       // mark last block offset
            if (ctx.t[0] < ctx.c)                    // carry overflow
                ctx.t[1]++;                          // high word
}