The Messenger's Oracle
Description:
Your Background
As a master spy, you have been embedded in a rival kingdom in order to monitor communications between their top General and the monarch and risen to the role of messenger between the two of them.
Unfortunately, the messages you've been delivering are all encrypted. You have gathered some intel (listed below) in your time here, as the General can be quite talkative whilst decoding their messages, but you have been unable to find a list of the keys in use. Worried that your cover might be starting to wear thin you need to find another way to read the messages from the intel you have.
Gathered Intel
Mood of the General
The General's mood does not seem to be affected by the quantity of messages they receive. However, you have noticed that when the General receives a message they seem to have one of following three reactions:
- If the message has been signed by the monarch then they always seem to be happy;
- If the message has come from someone else and so has not been signed by the monarch then they seem to be angry and just discard it;
- If the message doesn't seem to have been written correctly then they seem to be confused;
Decryption Process
- The messages you deliver first need to be base64 decoded
- The result is then split with the first 16 bytes noted as the initialisation vector (IV) for the decryption
- The message is then decrypted using the IV from step 2 and a key from a secret book the General always keeps on themselves. The encryption method is AES-128 CBC
- Finally there's always some padding to be removed, the General looks at the value of the last byte and removes that many copies of the byte from the end of the message (it's at this point the General occasionally seems confused)
In code, this equates to:
@key "Secret 16 bytes!"
def decrypt_message(message) do
# Base 64 decode (1) and split into IV and message data (2)
<< iv::binary-16, data::binary >> = Base.decode64!(message)
# Perform AES-128 CBC decryption (3)
:crypto.block_decrypt(:aes_cbc128, @key, iv, data)
|> OracleHelpers.unpad() # Remove padding using helper function (4) and return
end
Note: this is the process when you know the key, sadly you haven't got your hands on the book of keys so won't be able to use it this way in this kata
Known Examples
You have found a handful of early examples of encoded/decoded messages along with their key which has allowed you to verify the encryption process (these make up the example tests). From this you know that the monarch's signature is " - HRH"
at the end of a message.
Solving This Kata
In order to solve this kata you must provide a function spy_on_message/2
the arguments to this function will be:
message
- a base64 encoded string representing the message to decode;deliver_fn/1
- a function that allows you to deliver a message to the General and observe their response. The response will be one of:[:angry, :confused, :happy]
The output of the function should be the decrypted message with no added padding.
There is a utility function available to you OracleHelpers.unpad/1
which follows the process detailed above to remove message padding (so you don't have to write it yourself).
It will return the unpadded message if all is fine, or :nil
/ None
if something was wrong with the padding.
If you wish to work on this via a local IDE, the example test section should have everything you need to get started with testing your code.
Note: For python, predefined kata functions output/receive bytes rather than strings.
Test Constraints
- The decrypted messages may be any length from 0 bytes to 160 bytes long;
- The decrypted messages will sometimes result in a readable string but most of the time they will not.
Similar Kata:
Stats:
Created | Jul 19, 2020 |
Published | Jul 19, 2020 |
Warriors Trained | 66 |
Total Skips | 7 |
Total Code Submissions | 41 |
Total Times Completed | 7 |
Elixir Completions | 1 |
Python Completions | 7 |
Total Stars | 7 |
% of votes with a positive feedback rating | 88% of 4 |
Total "Very Satisfied" Votes | 3 |
Total "Somewhat Satisfied" Votes | 1 |
Total "Not Satisfied" Votes | 0 |
Total Rank Assessments | 4 |
Average Assessed Rank | 3 kyu |
Highest Assessed Rank | 2 kyu |
Lowest Assessed Rank | 4 kyu |