Last active
May 24, 2019 14:40
-
-
Save cybrox/5af7ee3053738e7e4c68a021d8118d86 to your computer and use it in GitHub Desktop.
Elixir Telegram
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use Bitwise | |
defmodule Telegram do | |
use Bitwise | |
@byte 8 | |
@bloc_size 4 * @byte | |
def get_bloc(telegram, bloc_nr) do | |
<<bloc::size(32)>> = binary_part(telegram, 2 + (bloc_nr - 1) * 4, 4) | |
bloc | |
end | |
def get_byte(telegram, byte_nr) do | |
<<byte::size(8)>> = binary_part(telegram, byte_nr, 1) | |
byte | |
end | |
def decode(telegram, byte, max_byte, register, out) when byte == max_byte, do: out | |
def decode(telegram, byte, max_byte, register, out \\ <<>>) do | |
{new_register, pout} = decode_single(0, 8, register, 0) | |
new_byte = get_byte(telegram, byte) ^^^ pout | |
decode(telegram, byte + 1, max_byte, new_register, out <> <<new_byte>>) | |
end | |
def decode_single(count, max_count, register, pout) when count == max_count, do: {register, pout} | |
def decode_single(count, max_count, register, pout) do | |
out = 0 | |
|> maybe_xor(register &&& 0x00000002) | |
|> maybe_xor(register &&& 0x00000004) | |
|> maybe_xor(register &&& 0x00000800) | |
|> maybe_xor(register &&& 0x80000000) | |
register = (register <<< 1) + out | |
pout = (pout <<< 1) + out | |
decode_single(count + 1, max_count, register, pout) | |
end | |
defp maybe_xor(input, condition) do | |
if condition > 0, do: input ^^^ 1, else: input | |
end | |
end | |
raw_telegram = "19442423850747321215A2214900139DFA2186B456C843AF6ACC" | |
telegram = Base.decode16!(raw_telegram) | |
IO.puts "Encoded Telegram: #{raw_telegram}" | |
IO.puts "Encoded Telegram: #{inspect(telegram)}" | |
IO.puts "Encoded Telegram length: #{byte_size(telegram)}\n" | |
bloc1 = Telegram.get_bloc(telegram, 1) | |
bloc2 = Telegram.get_bloc(telegram, 2) | |
bloc3 = Telegram.get_bloc(telegram, 3) | |
<<key_h::size(32)>> = Base.decode16!("51728910") | |
<<key_l::size(32)>> = Base.decode16!("E66D83F8") | |
register = bloc1 ^^^ bloc2 ^^^ bloc3 ^^^ key_h ^^^ key_l | |
telegram_base = binary_part(telegram, 0, 15) | |
decoded_part = Telegram.decode(telegram, 15, byte_size(telegram), register) | |
result = telegram_base <> decoded_part | |
IO.puts "Decoded Telegram: #{Base.encode16(result)}" | |
IO.puts "Decoded Telegram: #{inspect(result)}" | |
IO.puts "Decoded Telegram length: #{byte_size(result)}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Added this for convenience of testing for multiple values | |
# Use Telegram.decode(telegram, key) for decoding. | |
defmodule Telegram do | |
use Bitwise | |
def decode(raw_telegram, raw_key) do | |
telegram = raw_telegram |> String.upcase() |> Base.decode16!() | |
bloc1 = get_bloc(telegram, 1) | |
bloc2 = get_bloc(telegram, 2) | |
bloc3 = get_bloc(telegram, 3) | |
<<key_h::size(32)>> = get_key_segment(raw_key, 0) | |
<<key_l::size(32)>> = get_key_segment(raw_key, 1) | |
register = bloc1 ^^^ bloc2 ^^^ bloc3 ^^^ key_h ^^^ key_l | |
telegram_base = binary_part(telegram, 0, 15) | |
decoded_part = decode(telegram, 15, byte_size(telegram), register) | |
Base.encode16(telegram_base <> decoded_part) | |
end | |
defp get_key_segment(key, segment_id) do | |
key |> String.upcase() |> String.slice(segment_id * 8, 8) |> Base.decode16!() | |
end | |
defp get_bloc(telegram, bloc_nr) do | |
<<bloc::size(32)>> = binary_part(telegram, 2 + (bloc_nr - 1) * 4, 4) | |
bloc | |
end | |
defp get_byte(telegram, byte_nr) do | |
<<byte::size(8)>> = binary_part(telegram, byte_nr, 1) | |
byte | |
end | |
defp decode(telegram, byte, max_byte, register, out \\ <<>>) | |
defp decode(_telegram, byte, max_byte, _register, out) when byte == max_byte, do: out | |
defp decode(telegram, byte, max_byte, register, out) do | |
{new_register, pout} = decode_single(0, 8, register, 0) | |
new_byte = get_byte(telegram, byte) ^^^ pout | |
decode(telegram, byte + 1, max_byte, new_register, out <> <<new_byte>>) | |
end | |
defp decode_single(count, max_count, register, pout) when count == max_count, do: {register, pout} | |
defp decode_single(count, max_count, register, pout) do | |
out = 0 | |
|> maybe_xor(register &&& 0x00000002) | |
|> maybe_xor(register &&& 0x00000004) | |
|> maybe_xor(register &&& 0x00000800) | |
|> maybe_xor(register &&& 0x80000000) | |
register = (register <<< 1) + out | |
pout = (pout <<< 1) + out | |
decode_single(count + 1, max_count, register, pout) | |
end | |
defp maybe_xor(input, condition) do | |
if condition > 0, do: input ^^^ 1, else: input | |
end | |
end | |
IO.puts Telegram.decode("19442423850747321215A2214900139DFA2186B456C843AF6ACC", "51728910E66D83F851728910E66D83F8") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment