Commit 4c216cba authored by lain's avatar lain
Browse files

Decode and verify salmons.

parent 8a07ddef
defmodule Pleroma.Web.Salmon do
use Bitwise
def decode_and_validate(magickey, salmon) do
{doc, _rest} = :xmerl_scan.string(to_charlist(salmon))
{:xmlObj, :string, data} = :xmerl_xpath.string('string(//me:data[1])', doc)
{:xmlObj, :string, sig} = :xmerl_xpath.string('string(//me:sig[1])', doc)
{:xmlObj, :string, alg} = :xmerl_xpath.string('string(//me:alg[1])', doc)
{:xmlObj, :string, encoding} = :xmerl_xpath.string('string(//me:encoding[1])', doc)
{:xmlObj, :string, type} = :xmerl_xpath.string('string(//me:data[1]/@type)', doc)
{:ok, data} = Base.url_decode64(to_string(data), ignore: :whitespace)
{:ok, sig} = Base.url_decode64(to_string(sig), ignore: :whitespace)
alg = to_string(alg)
encoding = to_string(encoding)
type = to_string(type)
signed_text = [data, type, encoding, alg]
|> Enum.map(&Base.url_encode64/1)
|> Enum.join(".")
key = decode_key(magickey)
verify = :public_key.verify(signed_text, :sha256, sig, key)
if verify do
{:ok, data}
else
:error
end
end
defp decode_key("RSA." <> magickey) do
make_integer = fn(bin) ->
list = :erlang.binary_to_list(bin)
Enum.reduce(list, 0, fn (el, acc) -> (acc <<< 8) ||| el end)
end
[modulus, exponent] = magickey
|> String.split(".")
|> Enum.map(&Base.url_decode64!/1)
|> Enum.map(make_integer)
{:RSAPublicKey, modulus, exponent}
end
end
<?xml version="1.0" encoding="UTF-8"?>
<me:env xmlns:me="http://salmon-protocol.org/ns/magic-env"><me:data type="application/atom+xml">PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiID8-PGVudHJ5IHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDA1L0F0b20iIHhtbG5zOnRocj0iaHR0cDovL3B1cmwub3JnL3N5bmRpY2F0aW9uL3RocmVhZC8xLjAiIHhtbG5zOmFjdGl2aXR5PSJodHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zcGVjLzEuMC8iIHhtbG5zOmdlb3Jzcz0iaHR0cDovL3d3dy5nZW9yc3Mub3JnL2dlb3JzcyIgeG1sbnM6b3N0YXR1cz0iaHR0cDovL29zdGF0dXMub3JnL3NjaGVtYS8xLjAiIHhtbG5zOnBvY289Imh0dHA6Ly9wb3J0YWJsZWNvbnRhY3RzLm5ldC9zcGVjLzEuMCIgeG1sbnM6bWVkaWE9Imh0dHA6Ly9wdXJsLm9yZy9zeW5kaWNhdGlvbi9hdG9tbWVkaWEiIHhtbG5zOnN0YXR1c25ldD0iaHR0cDovL3N0YXR1cy5uZXQvc2NoZW1hL2FwaS8xLyI-CiA8aWQ-dGFnOmdzLmV4YW1wbGUub3JnOjQwNDAsMjAxNy0wNC0yMzpkaXNmYXZvcjoxOjg6MTk3MC0wMS0wMVQwMDowMDowMCswMDowMDwvaWQ-CiA8dGl0bGU-VW5saWtlPC90aXRsZT4KIDxjb250ZW50IHR5cGU9Imh0bWwiPmxhbWJkYSBubyBsb25nZXIgbGlrZXMgaHR0cDovL3BsZXJvbWEuZXhhbXBsZS5vcmc6NDAwMC9vYmplY3RzL2UyODk2ZmMxLTY1OGItNDJhNy1hMzYyLWUyNThkMzkwNmRlOS48L2NvbnRlbnQ-CiA8YWN0aXZpdHk6dmVyYj5odHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zY2hlbWEvMS4wL3VuZmF2b3JpdGU8L2FjdGl2aXR5OnZlcmI-CiA8cHVibGlzaGVkPjIwMTctMDQtMjNUMTE6NDc6NTUrMDA6MDA8L3B1Ymxpc2hlZD4KIDx1cGRhdGVkPjIwMTctMDQtMjNUMTE6NDc6NTUrMDA6MDA8L3VwZGF0ZWQ-CiA8YXV0aG9yPgogIDxhY3Rpdml0eTpvYmplY3QtdHlwZT5odHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zY2hlbWEvMS4wL3BlcnNvbjwvYWN0aXZpdHk6b2JqZWN0LXR5cGU-CiAgPHVyaT5odHRwOi8vZ3MuZXhhbXBsZS5vcmc6NDA0MC9pbmRleC5waHAvdXNlci8xPC91cmk-CiAgPG5hbWU-bGFtYmRhPC9uYW1lPgogIDxsaW5rIHJlbD0iYWx0ZXJuYXRlIiB0eXBlPSJ0ZXh0L2h0bWwiIGhyZWY9Imh0dHA6Ly9ncy5leGFtcGxlLm9yZzo0MDQwL2luZGV4LnBocC9sYW1iZGEiLz4KICA8bGluayByZWw9ImF2YXRhciIgdHlwZT0iaW1hZ2UvcG5nIiBtZWRpYTp3aWR0aD0iOTYiIG1lZGlhOmhlaWdodD0iOTYiIGhyZWY9Imh0dHA6Ly9ncy5leGFtcGxlLm9yZzo0MDQwL3RoZW1lL25lby1nbnUvZGVmYXVsdC1hdmF0YXItcHJvZmlsZS5wbmciLz4KICA8bGluayByZWw9ImF2YXRhciIgdHlwZT0iaW1hZ2UvcG5nIiBtZWRpYTp3aWR0aD0iNDgiIG1lZGlhOmhlaWdodD0iNDgiIGhyZWY9Imh0dHA6Ly9ncy5leGFtcGxlLm9yZzo0MDQwL3RoZW1lL25lby1nbnUvZGVmYXVsdC1hdmF0YXItc3RyZWFtLnBuZyIvPgogIDxsaW5rIHJlbD0iYXZhdGFyIiB0eXBlPSJpbWFnZS9wbmciIG1lZGlhOndpZHRoPSIyNCIgbWVkaWE6aGVpZ2h0PSIyNCIgaHJlZj0iaHR0cDovL2dzLmV4YW1wbGUub3JnOjQwNDAvdGhlbWUvbmVvLWdudS9kZWZhdWx0LWF2YXRhci1taW5pLnBuZyIvPgogIDxwb2NvOnByZWZlcnJlZFVzZXJuYW1lPmxhbWJkYTwvcG9jbzpwcmVmZXJyZWRVc2VybmFtZT4KICA8cG9jbzpkaXNwbGF5TmFtZT5sYW1iZGE8L3BvY286ZGlzcGxheU5hbWU-CiAgPGZvbGxvd2VycyB1cmw9Imh0dHA6Ly9ncy5leGFtcGxlLm9yZzo0MDQwL2luZGV4LnBocC9sYW1iZGEvc3Vic2NyaWJlcnMiPjwvZm9sbG93ZXJzPgogPC9hdXRob3I-CiA8YWN0aXZpdHk6b2JqZWN0PgogIDxhY3Rpdml0eTpvYmplY3QtdHlwZT5odHRwOi8vYWN0aXZpdHlzdHJlYS5tcy9zY2hlbWEvMS4wL25vdGU8L2FjdGl2aXR5Om9iamVjdC10eXBlPgogIDxpZD5odHRwOi8vcGxlcm9tYS5leGFtcGxlLm9yZzo0MDAwL29iamVjdHMvZTI4OTZmYzEtNjU4Yi00MmE3LWEzNjItZTI1OGQzOTA2ZGU5PC9pZD4KICA8dGl0bGU-TmV3IG5vdGUgYnkgbGFpbjI8L3RpdGxlPgogIDxjb250ZW50IHR5cGU9Imh0bWwiPkhlbGxvLjwvY29udGVudD4KICA8bGluayByZWw9ImFsdGVybmF0ZSIgdHlwZT0idGV4dC9odG1sIiBocmVmPSJodHRwOi8vcGxlcm9tYS5leGFtcGxlLm9yZzo0MDAwL29iamVjdHMvZTI4OTZmYzEtNjU4Yi00MmE3LWEzNjItZTI1OGQzOTA2ZGU5Ii8-CiAgPHN0YXR1c19uZXQgbm90aWNlX2lkPSI4Ij48L3N0YXR1c19uZXQ-CiA8L2FjdGl2aXR5Om9iamVjdD4KPC9lbnRyeT4K</me:data><me:encoding>base64url</me:encoding><me:alg>RSA-SHA256</me:alg><me:sig>ZXXHgp_ihTZIJnnFiQuJD0TSvo4OIqrpblHHQQwfpCy-85mtTf0QO1LclX3P3Ra8BqAmhs7j9nDxuEGLuVLTt53DvMP-pOjCtWYDKBbEZQtFIVnCcvBzGPW1HmimdN49M3VtAohbhfVilTrApQpGnI6kHvx7G1fQdQxHRtMsdNI=</me:sig></me:env>
\ No newline at end of file
defmodule Pleroma.Web.Salmon.SalmonTest do
use Pleroma.DataCase
alias Pleroma.Web.Salmon
@magickey "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwQhh-1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
@wrong_magickey "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwQhh-1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAA"
test "decodes a salmon" do
{:ok, salmon} = File.read("test/fixtures/salmon.xml")
{:ok, doc} = Salmon.decode_and_validate(@magickey, salmon)
assert Regex.match?(~r/xml/, doc)
end
test "errors on wrong magic key" do
{:ok, salmon} = File.read("test/fixtures/salmon.xml")
assert Salmon.decode_and_validate(@wrong_magickey, salmon) == :error
end
end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment