private static void __sha256_finish_ctx(sha256_ctx ctx, ArrayPointer <byte> buffer) { byte[] temp = new byte[ctx.stream.Length]; ctx.stream.Seek(0, SeekOrigin.Begin); ctx.stream.Read(temp, 0, temp.Length); temp = SHA256.Create().ComputeHash(temp); for (int i = 0; i < temp.Length; i++, buffer++) { buffer.Value = temp[i]; } }
private static void __sha256_init_ctx(sha256_ctx ctx) { ctx.stream = new MemoryStream(); }
private static void __sha256_process_bytes(ArrayPointer <byte> buffer, int count, sha256_ctx ctx) { ctx.stream.Write(buffer.SourceArray, buffer.Address, count); }
private static ArrayPointer <byte> __sha256_crypt_r(ArrayPointer <byte> key, ArrayPointer <byte> salt, ArrayPointer <byte> buffer, int buflen) { ArrayPointer <byte> alt_result = new ArrayPointer <byte>(new byte[32]); ArrayPointer <byte> temp_result = new ArrayPointer <byte>(new byte[32]); sha256_ctx ctx = new sha256_ctx(); sha256_ctx alt_ctx = new sha256_ctx(); int salt_len; int key_len; int cnt; ArrayPointer <byte> cp; ArrayPointer <byte> copied_key; ArrayPointer <byte> copied_salt; ArrayPointer <byte> p_bytes; ArrayPointer <byte> s_bytes; /* Default number of rounds. */ int rounds = RoundsDefault; bool rounds_custom = false; /* Find beginning of salt string. The prefix should normally always * be present. Just in case it is not. */ if (strncmp(sha256_salt_prefix, salt, strlen(sha256_salt_prefix)) == 0) { /* Skip salt prefix. */ salt += strlen(sha256_salt_prefix); } if (strncmp(salt, sha256_rounds_prefix, strlen(sha256_rounds_prefix)) == 0) { ArrayPointer <byte> num = salt + strlen(sha256_rounds_prefix); ArrayPointer <byte> endp; ulong srounds = strtoul(num, out endp, 10); if (endp.Value == (byte)'$') { salt = endp + 1; rounds = (int)Math.Max(RoundsMin, Math.Min(srounds, RoundsMax)); rounds_custom = true; } } salt_len = Math.Min(strcspn(salt, dollar_sign), SaltLenMax); 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. */ __sha256_init_ctx(ctx); /* Add the key string. */ __sha256_process_bytes(key, key_len, ctx); /* The last part is the salt string. This must be at most 16 * characters and it ends at the first `$' character. */ __sha256_process_bytes(salt, salt_len, ctx); /* Compute alternate SHA256 sum with input KEY, SALT, and KEY. The * final result will be added to the first context. */ __sha256_init_ctx(alt_ctx); /* Add key. */ __sha256_process_bytes(key, key_len, alt_ctx); /* Add salt. */ __sha256_process_bytes(salt, salt_len, alt_ctx); /* Add key again. */ __sha256_process_bytes(key, key_len, alt_ctx); /* Now get result of this (32 bytes) and add it to the other * context. */ __sha256_finish_ctx(alt_ctx, alt_result); /* Add for any character in the key one byte of the alternate sum. */ for (cnt = key_len; cnt > 32; cnt -= 32) { __sha256_process_bytes(alt_result, 32, ctx); } __sha256_process_bytes(alt_result, cnt, ctx); /* Take the binary representation of the length of the key and for every * 1 add the alternate sum, for every 0 the key. */ for (cnt = key_len; cnt > 0; cnt >>= 1) { if ((cnt & 1) != 0) { __sha256_process_bytes(alt_result, 32, ctx); } else { __sha256_process_bytes(key, key_len, ctx); } } /* Create intermediate result. */ __sha256_finish_ctx(ctx, alt_result); /* Start computation of P byte sequence. */ __sha256_init_ctx(alt_ctx); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < key_len; ++cnt) { __sha256_process_bytes(key, key_len, alt_ctx); } /* Finish the digest. */ __sha256_finish_ctx(alt_ctx, temp_result); /* Create byte sequence P. */ cp = p_bytes = new ArrayPointer <byte>(new byte[key_len]); for (cnt = key_len; cnt >= 32; cnt -= 32) { cp = mempcpy(cp, temp_result, 32); } memcpy(cp, temp_result, cnt); /* Start computation of S byte sequence. */ __sha256_init_ctx(alt_ctx); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) { __sha256_process_bytes(salt, salt_len, alt_ctx); } /* Finish the digest. */ __sha256_finish_ctx(alt_ctx, temp_result); /* Create byte sequence S. */ cp = s_bytes = new ArrayPointer <byte>(new byte[salt_len]); for (cnt = salt_len; cnt >= 32; cnt -= 32) { cp = mempcpy(cp, temp_result, 32); } memcpy(cp, temp_result, cnt); /* Repeatedly run the collected hash value through SHA256 to burn * CPU cycles. */ for (cnt = 0; cnt < rounds; ++cnt) { /* New context. */ __sha256_init_ctx(ctx); /* Add key or last result. */ if ((cnt & 1) != 0) { __sha256_process_bytes(p_bytes, key_len, ctx); } else { __sha256_process_bytes(alt_result, 32, ctx); } /* Add salt for numbers not divisible by 3. */ if (cnt % 3 != 0) { __sha256_process_bytes(s_bytes, salt_len, ctx); } /* Add key for numbers not divisible by 7. */ if (cnt % 7 != 0) { __sha256_process_bytes(p_bytes, key_len, ctx); } /* Add key or last result. */ if ((cnt & 1) != 0) { __sha256_process_bytes(alt_result, 32, ctx); } else { __sha256_process_bytes(p_bytes, key_len, ctx); } /* Create intermediate result. */ __sha256_finish_ctx(ctx, alt_result); } /* Now we can construct the result string. It consists of three * parts. */ cp = __stpncpy(buffer, sha256_salt_prefix, Math.Max(0, buflen)); buflen -= strlen(sha256_salt_prefix); if (rounds_custom) { cp = __stpncpy(cp, sha256_rounds_prefix, Math.Max(0, buflen)); buflen -= strlen(sha256_rounds_prefix); char[] temp1 = (rounds.ToString() + "$\0").ToCharArray(); byte[] temp2 = new byte[temp1.Length]; for (int i = 0; i < temp1.Length; i++) { temp2[i] = (byte)temp1[i]; } ArrayPointer <byte> temp3 = new ArrayPointer <byte>(temp2); cp = __stpncpy(cp, temp3, Math.Max(0, buflen)); buflen -= strlen(temp3); } 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[10], alt_result[20], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4, cp, buflen, out buflen); cp = b64_from_24bit(0, alt_result[31], alt_result[30], 3, 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 SHA256 implementation as well. */ __sha256_init_ctx(ctx); __sha256_finish_ctx(ctx, alt_result); return(buffer); }
private static void __sha256_process_bytes(ArrayPointer<byte> buffer, int count, sha256_ctx ctx) { ctx.stream.Write(buffer.SourceArray, buffer.Address, count); }
private static void __sha256_finish_ctx(sha256_ctx ctx, ArrayPointer<byte> buffer) { byte[] temp = new byte[ctx.stream.Length]; ctx.stream.Seek(0, SeekOrigin.Begin); ctx.stream.Read(temp, 0, temp.Length); temp = SHA256.Create().ComputeHash(temp); for (int i = 0; i < temp.Length; i++, buffer++) { buffer.Value = temp[i]; } }
private static ArrayPointer<byte> __sha256_crypt_r(ArrayPointer<byte> key, ArrayPointer<byte> salt, ArrayPointer<byte> buffer, int buflen) { ArrayPointer<byte> alt_result = new ArrayPointer<byte>(new byte[32]); ArrayPointer<byte> temp_result = new ArrayPointer<byte>(new byte[32]); sha256_ctx ctx = new sha256_ctx(); sha256_ctx alt_ctx = new sha256_ctx(); int salt_len; int key_len; int cnt; ArrayPointer<byte> cp; ArrayPointer<byte> copied_key; ArrayPointer<byte> copied_salt; ArrayPointer<byte> p_bytes; ArrayPointer<byte> s_bytes; /* Default number of rounds. */ int rounds = RoundsDefault; bool rounds_custom = false; /* Find beginning of salt string. The prefix should normally always be present. Just in case it is not. */ if (strncmp(sha256_salt_prefix, salt, strlen(sha256_salt_prefix)) == 0) { /* Skip salt prefix. */ salt += strlen(sha256_salt_prefix); } if (strncmp(salt, sha256_rounds_prefix, strlen(sha256_rounds_prefix)) == 0) { ArrayPointer<byte> num = salt + strlen(sha256_rounds_prefix); ArrayPointer<byte> endp; ulong srounds = strtoul(num, out endp, 10); if (endp.Value == (byte)'$') { salt = endp + 1; rounds = (int)Math.Max(RoundsMin, Math.Min(srounds, RoundsMax)); rounds_custom = true; } } salt_len = Math.Min(strcspn(salt, dollar_sign), SaltLenMax); 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. */ __sha256_init_ctx(ctx); /* Add the key string. */ __sha256_process_bytes(key, key_len, ctx); /* The last part is the salt string. This must be at most 16 characters and it ends at the first `$' character. */ __sha256_process_bytes(salt, salt_len, ctx); /* Compute alternate SHA256 sum with input KEY, SALT, and KEY. The final result will be added to the first context. */ __sha256_init_ctx(alt_ctx); /* Add key. */ __sha256_process_bytes(key, key_len, alt_ctx); /* Add salt. */ __sha256_process_bytes(salt, salt_len, alt_ctx); /* Add key again. */ __sha256_process_bytes(key, key_len, alt_ctx); /* Now get result of this (32 bytes) and add it to the other context. */ __sha256_finish_ctx(alt_ctx, alt_result); /* Add for any character in the key one byte of the alternate sum. */ for (cnt = key_len; cnt > 32; cnt -= 32) __sha256_process_bytes(alt_result, 32, ctx); __sha256_process_bytes(alt_result, cnt, ctx); /* Take the binary representation of the length of the key and for every 1 add the alternate sum, for every 0 the key. */ for (cnt = key_len; cnt > 0; cnt >>= 1) if ((cnt & 1) != 0) __sha256_process_bytes(alt_result, 32, ctx); else __sha256_process_bytes(key, key_len, ctx); /* Create intermediate result. */ __sha256_finish_ctx(ctx, alt_result); /* Start computation of P byte sequence. */ __sha256_init_ctx(alt_ctx); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < key_len; ++cnt) __sha256_process_bytes(key, key_len, alt_ctx); /* Finish the digest. */ __sha256_finish_ctx(alt_ctx, temp_result); /* Create byte sequence P. */ cp = p_bytes = new ArrayPointer<byte>(new byte[key_len]); for (cnt = key_len; cnt >= 32; cnt -= 32) cp = mempcpy(cp, temp_result, 32); memcpy(cp, temp_result, cnt); /* Start computation of S byte sequence. */ __sha256_init_ctx(alt_ctx); /* For every character in the password add the entire password. */ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) __sha256_process_bytes(salt, salt_len, alt_ctx); /* Finish the digest. */ __sha256_finish_ctx(alt_ctx, temp_result); /* Create byte sequence S. */ cp = s_bytes = new ArrayPointer<byte>(new byte[salt_len]); for (cnt = salt_len; cnt >= 32; cnt -= 32) cp = mempcpy(cp, temp_result, 32); memcpy(cp, temp_result, cnt); /* Repeatedly run the collected hash value through SHA256 to burn CPU cycles. */ for (cnt = 0; cnt < rounds; ++cnt) { /* New context. */ __sha256_init_ctx(ctx); /* Add key or last result. */ if ((cnt & 1) != 0) __sha256_process_bytes(p_bytes, key_len, ctx); else __sha256_process_bytes(alt_result, 32, ctx); /* Add salt for numbers not divisible by 3. */ if (cnt % 3 != 0) __sha256_process_bytes(s_bytes, salt_len, ctx); /* Add key for numbers not divisible by 7. */ if (cnt % 7 != 0) __sha256_process_bytes(p_bytes, key_len, ctx); /* Add key or last result. */ if ((cnt & 1) != 0) __sha256_process_bytes(alt_result, 32, ctx); else __sha256_process_bytes(p_bytes, key_len, ctx); /* Create intermediate result. */ __sha256_finish_ctx(ctx, alt_result); } /* Now we can construct the result string. It consists of three parts. */ cp = __stpncpy(buffer, sha256_salt_prefix, Math.Max(0, buflen)); buflen -= strlen(sha256_salt_prefix); if (rounds_custom) { cp = __stpncpy(cp, sha256_rounds_prefix, Math.Max(0, buflen)); buflen -= strlen(sha256_rounds_prefix); char[] temp1 = (rounds.ToString() + "$\0").ToCharArray(); byte[] temp2 = new byte[temp1.Length]; for(int i = 0; i < temp1.Length; i++) temp2[i] = (byte)temp1[i]; ArrayPointer<byte> temp3 = new ArrayPointer<byte>(temp2); cp = __stpncpy(cp, temp3, Math.Max(0, buflen)); buflen -= strlen(temp3); } 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[10], alt_result[20], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4, cp, buflen, out buflen); cp = b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4, cp, buflen, out buflen); cp = b64_from_24bit(0, alt_result[31], alt_result[30], 3, 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 SHA256 implementation as well. */ __sha256_init_ctx(ctx); __sha256_finish_ctx(ctx, alt_result); return buffer; }