Skip to content

Instantly share code, notes, and snippets.

@cybrox
Last active May 24, 2019 14:40
Show Gist options
  • Save cybrox/5af7ee3053738e7e4c68a021d8118d86 to your computer and use it in GitHub Desktop.
Save cybrox/5af7ee3053738e7e4c68a021d8118d86 to your computer and use it in GitHub Desktop.
Elixir Telegram
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)}"
# 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