

Challenge 1: Base64 Encoding
source link: https://www.scottbrady91.com/cryptopals/base64-encoding
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Cryptopals Crypto Challenges
These are solutions to the Cryptopals Crypto Challenges, solved using C# and .NET Core. These articles talk through the theory and code snippets that I found most valuable towards solving the challenges.
A friendly reminder as always: do not use this code in production.
See my introductory post for more solutions, links to complete source code, and my favorite resources.
We’ve all used Convert.ToBase64String()
but what is it actually happening under the covers?
Sure, it’s taking a value and representing it using only characters from a range of 64 characters, but how exactly does it do that?
Up until now, I probably couldn’t have told you.
My favorite example for understanding how Base64 encoding works is actually from Wikipedia:
Source Text (ASCII) M a n
Octets 77 (0x4d) 97 (0x61) 110 (0x6e)
Bits 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
Base64
encoded
Sextets
19
22
5
46
Character T W F u
Octets 84 (0x54) 87 (0x57) 70 (0x46) 117 (0x75)
Base64 adapted from Wikipedia
To Base64 encode, we take our original string, convert it into bytes (octets), take 6 bits at a time (sextets), and then look up that sextet’s corresponding value in our Base64 lookup table.
Hex to Bytes
In the challenge, we’re given a hex string to Base64 encode.
Hexadecimal is the Base16 (0–9, a–f) representation of a byte.
For example, the byte 77 would be 4d.
In C languages, you’ll often see this prefixed with 0x
, making it 0x4d.
We typically don’t work directly with hex strings, and I’ve yet to find simple handling for hex string in C#, so the first thing I did was to take the hex string and turn it into bytes:
public static byte[] StringToBytes(string hex) {
var hexAsBytes = new byte[hex.Length / 2];
for (var i = 0; i < hex.Length; i += 2) {
hexAsBytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return hexAsBytes;
}
Here we have our hex string, take two characters at a time, and then convert them to a byte using Convert.ToByte()
with a fromBase
of 16 (which is the base for hexadecimals (0–f)).
Bytes to Binary
Now that we have the bytes, we need to get their octets, and then break those octets into sextets.
The simplest way I could find was to parse the byte array into a string representation of the binary. I’m sure there’s a more efficient way to do this, but I found this the clearest way for me to see what was going on.
public static string ToBinaryString(byte[] bytes) {
var binaryOctets = bytes.Select(x =>
Convert.ToString(x, 2) // get as 1's & 0's
.PadLeft(8, '0')) // ensure always 8 chars longs, otherwise padding 0's on left
.ToList();
return binaryOctets.Aggregate(string.Empty,
(current, currentBit) => current + currentBit); // concatenate into single string
}
Octets to Sextets
Now that we have the octets, let’s get them sextets by taking 6 bits at a time and then convert them back into integers (to simplify the next step):
public static List<int> OctetsToSextets(string bits) {
var taken = 0;
var sextets = new List<int>();
while (taken < bits.Length) {
var sextet = bits
.Skip(taken)
.Take(6)
.Aggregate(string.Empty, (c, c1) => c + c1);
sextets.Add(Convert.ToInt32(sextet, 2));
taken += 6;
}
return sextets;
}
Base64 Lookup
Now that we have our sextets, we can look up their corresponding base 64 value. So, the value 42 turns into q, and 4 is E.
private static string SextetsToBase64String(IList<int> sextets) {
string base64String = null;
foreach (var sextet in sextets) {
base64String += Base64Lookup[sextet];
}
return base64String;
}
private static readonly char[] Base64Lookup = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
And if you chain the above together, you should end up with the hex string 4d616e
being encoded as: TWFu
.
Padding
So, what happens when the original text length is not neatly divisible by 3? Well, we need to deal with padding.
Going back to that really useful Wikipedia example, we can see that if the final block is not 3 in length, then we need to pad both the final sextet and the encoded value itself.
Source Text (ASCII) M a
Octets 77 (0x4d) 97 (0x61)
Bits 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 0
Base64
encoded
Sextets
19
22
4
Padding
Character T W E =
Octets 84 (0x54) 87 (0x57) 69 (0x45) 61 (0x3D)
Base64 adapted from Wikipedia
So, the final sextet gets padded with 0s on the right, and any missing sextets become the padding character '='
.
We can update our OctetsToSextets
with a check such as:
if (sextet.Length != 6) {
sextet = sextet.PadRight(6, '0'); // if not 6 in length, pad right with 0's
}
And then, after creating our Base64 value in SextetsToBase64String
, check to see if it’s missing any characters, padding with '='
as appropriate.
if (base64String?.Length % 4 != 0) {
if (base64String?.Length % 4 == 2) base64String += "==";
else base64String += "=";
}
So, testing our code, if we enter the hex string 4d61
, then we should end up with TWE=
.
There’s a much nicer implementation by David Zych which goes into more detail. I recommend checking it out.
We’ve only dealt with encoding here, however, you'll need to handle decoding later in the challenges.
You can either use Convert.FromBase64String()
or implement the reverse of the above yourself.
Source Code
These articles discuss the theory and code snippets that helped me the most. For full challenge solutions, check out the accompanying GitHub repository.
Recommend
-
112
对称加密和Base64编码
-
19
While browsing some API documentation, I saw references to Base64 for passing credentials to the API. I had seen Base64 referenced a few times, but had no idea how to convert text into Base64. So, I did some digging. This post will o...
-
7
The Oracle documentation for java.util.Base64 refers to three different kinds of Base64, but only by reference to RFCs. Here it is in one place.
-
13
Base64 Encoding and Decoding in JavaScript in Adobe AIR Thursday, June 12, 2008 I have been working on a JavaScript AIR app for the past week or so while on the on AIR Tour in Europe, and ran into the need to Base64 enc...
-
11
January 14, 2021 Base64 Encoding With C# ...
-
12
S M Firoz Ashraf November 26, 2021 2 minute read
-
6
Base64 Encoding and Decoding Using Pythonby Abder-Rahman AliMar 22, 2016(Updated Apr 11, 2022)Read Time:9...
-
7
Encoding Base64/32/16 encoding/decoding for React Native written in C/C++ and JSI May 17, 2022 1 min read
-
6
Base64 encoding: What sysadmins need to know By understanding Base64 encoding, you can apply it to Kubernetes secrets, OpenSSL, e...
-
8
How to upload files from your HTML form using Base64 encodingDecember 22, 2021 · 5 min readMelih EkinciFrontend...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK