C#
Possibly crazy, roundabout, and convoluted way to get to the (exact) result - with only variable renames and without any literal "mom" in any of the code.
Reading the "if you take a code block from a post, you take the whole thing" rule very literally probably didn't help - but made it more fun.
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
public class Program
{
void Main()
{
// Step 1
var n = 3;
var helloAndGoodbye = "12345678900"
.Select((c, i) => new { letter = c, group = i / n })
.GroupBy(l => l.group, l => l.letter)
.Select(g => string.Join("", g))
.ToList();
// Step 2
string place = "world";
string greet = String.Format("Hello {0}!", place);
// Step 3
byte[] b1 = System.Text.Encoding.UTF8.GetBytes (greet);
byte[] b2 = System.Text.Encoding.ASCII.GetBytes (greet);
// Step 4
string encryptionKey = "test";
var md5 = MD5.Create();
var keyBytes = Encoding.UTF8.GetBytes(encryptionKey);
byte[] encryptionKeyBytes = md5.ComputeHash(keyBytes);
// Step 5
string strName = md5.GetType().Name;
if(strName == "Person")
{
//My Code
}
// Step 6
string HashAlgorithm = new string(strName.Take(n).ToArray());
// Step 7
int previousYear = DateTime.Now.AddYears(-1).Year;
// Step 8
string myString = previousYear.ToString();
// Step 9
string totallyRandomString = new string(myString.Take(n).ToArray());
// Step 10
int myInt = System.Convert.ToInt32(totallyRandomString);
// Step 11
int x = myInt << 1 + 1;
// Step 12
PasswordDeriveBytes DerivedPassword =
new PasswordDeriveBytes(place, b1, HashAlgorithm, x);
byte[] KeyBytes = DerivedPassword.GetBytes(32);
// Step 13
string base64 = Convert.ToBase64String(KeyBytes);
byte[] bytes = Convert.FromBase64String(base64);
// Step 14
var split = base64.Split('/');
var last = split[split.Length -1];
var prev = split[split.Length -2];
// Step 15
string truncatedToNLength = new string(last.Take(n).ToArray());
// Step 16
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
greet = rgx.Replace(greet, "");
// Step 17
var newString = greet.Replace(place.ToString(), truncatedToNLength);
// Step 18
var searchStr = newString.ToLower();
searchStr = searchStr.Trim();
// Step 19
Console.WriteLine(searchStr);
}
}
.NET Fiddle
http://dotnetfiddle.net/PbjhPn
http://dotnetfiddle.net/bg20wb (with redundant lines in code blocks removed)
Short explanation
Basically, we get "Hello world!" from a simple string format. Now we need "mom" to replace it. For that, we use the Base64 encoded result of running 804 iterations of PBKDF1 using MD5 with "world" as password and "Hello world!" as salt. That yields a string "ciSf5cCls1l/MoM...". We extract that "MoM" and use it as a replacement for "world". Then we clean up the string.
How do we get to 804? The previous year clipped to three characters (= "201"), and then multiplied by 4.
Long explanation and attributions
1: We start with a bit of rule-following overkill.
The integer 3 is a very very important constant in this program.
Here we assign that integer to n
. We must include the entire block from the source. It may be redundant, but it will compile just fine, as long as we rename the split
variable that we'll be needing later. Source
Replaced variable names:
split > helloAndGoodbye
2: Set up starting string ("Hello world!"). Source
This is a very personal message to our mom. So we obviously need some cryptography to deal with those NSA types. For that, we'll need some parameters, which we prepare now.
3: Convert greet
("Hello world!") to byte array for salting. Source
myString > greet
4: Although we're using cryptography, we don't actually need to instantiate the MD5 class. We do, however, need the string "MD5" assigned for one of our parameters to be used further down - and that's not easy to find in usable code. So we'll take another... "shortcut"... Once again, entire code block included as per rules, although we only need the second line. Source
5: Now we need the name of the type of the md5
variable (MD5CryptoServiceProvider
). The if
is yet another redundancy. Source
entity > md5
6: Get the first 3 (ooh, there's our constant!) characters of the type name. Source
s > strName
truncatedToNLength > HashAlgorithm
7: Code-trolling: Using DateTime.Now
would mean this would only work until 2019. To make it a bit more future proof, we use the previous year. Then it will work until 2020 ;-)Source
8: Convert our previousYear
to string. Source
myInt > previousYear
9: Hey, code reuse! ;-) Get the first 3 (our constant!) characters of our year. Source
s > myString
truncatedToNLength > totallyRandomString
10: Aaaaaaaand... convert the result back to integer. Source
myString > totallyRandomString
11: Eric Lippert makes every answer better. Multiply by 4 in a roundabout way. Source
y > myInt
12: Send place
(password) and greet
(salt) through PBKDF1 using MD5 with x
(which is now 201*4 = 804
) iterations. Source
Password > place
SaltValueBytes > b1
PasswordIterations > x
13: Jon Skeet also makes every answer better. Convert our derived password to base 64. We throw out the bytes
array. Source
bytes (first occurrence) > KeyBytes
14: What a crazy random happenstance! We now have a base64
with "MoM" in it. Conveniently, right before "MoM" is a single '/'. So split the string with that character as delimiter: Source
filePath > base64
15: Hey, our favorite piece of code reuse tape! Get the first 3 (constant!) letters of last
. Source
s > last
16: Remove "!". Source
str > greet
17: MoM is our world - so make the string reflect that (replace "world" with "MoM"). Source
someTestString > greet
someID > place
sessionID > truncatedToNLength
18: Finally, convert to lower case. Trim for good measure (or possibly because it's part of the duct tape block). Source
wordToSearchReplacemntsFor > newString
19: Output to console. Source
_surface > searchStr
A bit of "bonus material"/commentary
At first I tried every combination of built-in cryptographic hashes (each combined with HMAC) and inputs ("world", "Hello world!", "Hello world", "hello world" etc.) to see if something would miraculously give a usable output to derive "mom" from - before taking the easy route of just looking for a number of iterations of PDKDB1 (or 2) that would be useful.
Wasn't quite happy with the use of the year as input for the 201*4 = 804 iterations. At first I tried to find some useful code for HttpStatusCode.Created
(201) to use as input - with a "troll excuse" along the lines of "we've created our 'Hello world!' string, so a good practice would be to use a 'Created' status code" here. Unfortunately, I never found a usage of the HttpStatusCode
enumeration that didn't introduce a dependency on most of the ASP.NET WebAPI framework.
The start of the code (the "Hello world!" string format) was never looked at again after I first added it. If I had, yeah, I might have realized that the assignment of place
was actually in a different block in the source - so I could have simply assigned my derived "mom" to place
rather than using "world" and later replacing it. Ah well.
m
or ano
as a literal. Or a snippet that converts code points to characters and snippets that let you calculate the right code point. The restriction is exactly what encourages creativity here. This is what I mentioned on your own challenge, and why I suggested to limit the scope (and subsequently why it was closed). \$\endgroup\$