示例#1
0
        private static ArrayPointer <byte> b64_from_24bit(uint B2, uint B1, uint B0, int N, ArrayPointer <byte> cp, int buflen, out int buflen_out)
        {
            uint w = ((B2) << 16) | ((B1) << 8) | (B0);
            int  n = (N);

            while (n-- > 0 && buflen > 0)
            {
                cp.Value = (byte)b64t[w & 0x3f];
                cp++;
                buflen--;
                w >>= 6;
            }
            buflen_out = buflen;
            return(cp);
        }
示例#2
0
 private static void __sha256_process_bytes(ArrayPointer <byte> buffer, int count, sha256_ctx ctx)
 {
     ctx.stream.Write(buffer.SourceArray, buffer.Address, count);
 }
示例#3
0
        private static ArrayPointer <byte> __md5_crypt_r(ArrayPointer <byte> key, ArrayPointer <byte> salt, ArrayPointer <byte> buffer, int buflen)
        {
            ArrayPointer <byte> alt_result = new ArrayPointer <byte>(new byte[16]);
            md5_ctx             ctx        = new md5_ctx();
            md5_ctx             alt_ctx    = new md5_ctx();
            int salt_len;
            int key_len;
            int cnt;
            ArrayPointer <byte> cp;
            ArrayPointer <byte> copied_key;
            ArrayPointer <byte> copied_salt;

            /* Find beginning of salt string.  The prefix should normally always
             * be present.  Just in case it is not.  */
            if (strncmp(md5_salt_prefix, salt, strlen(md5_salt_prefix)) == 0)
            {
                salt += strlen(md5_salt_prefix);
            }

            salt_len = Math.Min(strcspn(salt, dollar_sign), 8);
            key_len  = strlen(key);

            byte[] temp = new byte[key.SourceArray.Length];
            key.SourceArray.CopyTo(temp, 0);
            copied_key         = new ArrayPointer <byte>(temp);
            copied_key.Address = key.Address;
            key = copied_key;

            temp = new byte[salt.SourceArray.Length];
            salt.SourceArray.CopyTo(temp, 0);
            copied_salt         = new ArrayPointer <byte>(temp);
            copied_salt.Address = salt.Address;
            salt = copied_salt;

            /* Prepare for the real work.  */
            __md5_init_ctx(ctx);

            /* Add the key string.  */
            __md5_process_bytes(key, key_len, ctx);

            /* Because the SALT argument need not always have the salt prefix we
             * add it separately.  */
            __md5_process_bytes(md5_salt_prefix, strlen(md5_salt_prefix), ctx);

            /* The last part is the salt string.  This must be at most 8
             * characters and it ends at the first `$' character (for
             * compatibility with existing implementations).  */
            __md5_process_bytes(salt, salt_len, ctx);


            /* Compute alternate MD5 sum with input KEY, SALT, and KEY.  The
             * final result will be added to the first context.  */
            __md5_init_ctx(alt_ctx);

            /* Add key.  */
            __md5_process_bytes(key, key_len, alt_ctx);

            /* Add salt.  */
            __md5_process_bytes(salt, salt_len, alt_ctx);

            /* Add key again.  */
            __md5_process_bytes(key, key_len, alt_ctx);

            /* Now get result of this (16 bytes) and add it to the other
             * context.  */
            __md5_finish_ctx(alt_ctx, alt_result);

            /* Add for any character in the key one byte of the alternate sum.  */
            for (cnt = key_len; cnt > 16; cnt -= 16)
            {
                __md5_process_bytes(alt_result, 16, ctx);
            }
            __md5_process_bytes(alt_result, cnt, ctx);

            /* For the following code we need a NUL byte.  */
            alt_result.Value = 0;

            /* The original implementation now does something weird: for every 1
             * bit in the key the first 0 is added to the buffer, for every 0
             * bit the first character of the key.  This does not seem to be
             * what was intended but we have to follow this to be compatible.  */
            for (cnt = key_len; cnt > 0; cnt >>= 1)
            {
                __md5_process_bytes((cnt & 1) != 0 ? alt_result : key, 1, ctx);
            }

            /* Create intermediate result.  */
            __md5_finish_ctx(ctx, alt_result);

            /* Now comes another weirdness.  In fear of password crackers here
             * comes a quite long loop which just processes the output of the
             * previous round again.  We cannot ignore this here.  */
            for (cnt = 0; cnt < 1000; ++cnt)
            {
                /* New context.  */
                __md5_init_ctx(ctx);

                /* Add key or last result.  */
                if ((cnt & 1) != 0)
                {
                    __md5_process_bytes(key, key_len, ctx);
                }
                else
                {
                    __md5_process_bytes(alt_result, 16, ctx);
                }

                /* Add salt for numbers not divisible by 3.  */
                if (cnt % 3 != 0)
                {
                    __md5_process_bytes(salt, salt_len, ctx);
                }

                /* Add key for numbers not divisible by 7.  */
                if (cnt % 7 != 0)
                {
                    __md5_process_bytes(key, key_len, ctx);
                }

                /* Add key or last result.  */
                if ((cnt & 1) != 0)
                {
                    __md5_process_bytes(alt_result, 16, ctx);
                }
                else
                {
                    __md5_process_bytes(key, key_len, ctx);
                }

                /* Create intermediate result.  */
                __md5_finish_ctx(ctx, alt_result);
            }

            /* Now we can construct the result string.  It consists of three
             * parts.  */
            cp      = __stpncpy(buffer, md5_salt_prefix, Math.Max(0, buflen));
            buflen -= strlen(md5_salt_prefix);

            cp      = __stpncpy(cp, salt, Math.Min(Math.Max(0, buflen), salt_len));
            buflen -= Math.Min(Math.Max(0, buflen), salt_len);

            if (buflen > 0)
            {
                cp.Value = (byte)'$';
                cp++;
                buflen--;
            }

            cp = b64_from_24bit(alt_result[0], alt_result[6], alt_result[12], 4, cp, buflen, out buflen);
            cp = b64_from_24bit(alt_result[1], alt_result[7], alt_result[13], 4, cp, buflen, out buflen);
            cp = b64_from_24bit(alt_result[2], alt_result[8], alt_result[14], 4, cp, buflen, out buflen);
            cp = b64_from_24bit(alt_result[3], alt_result[9], alt_result[15], 4, cp, buflen, out buflen);
            cp = b64_from_24bit(alt_result[4], alt_result[10], alt_result[5], 4, cp, buflen, out buflen);
            cp = b64_from_24bit(0, 0, alt_result[11], 2, cp, buflen, out buflen);

            if (buflen <= 0)
            {
                throw new IndexOutOfRangeException();
            }
            else
            {
                cp.Value = 0;           /* Terminate the string.  */
            }

            /* Clear the buffer for the intermediate result so that people
             * attaching to processes or reading core dumps cannot get any
             * information.  We do it in this way to clear correct_words[]
             * inside the MD5 implementation as well.  */
            __md5_init_ctx(ctx);
            __md5_finish_ctx(ctx, alt_result);

            return(buffer);
        }