defmodule CA.KEP do
require Record
Record.defrecord(:certAttrs, serial: "", cn: "", givenName: "", surname: "", o: "", title: "", ou: "", c: "", locality: "")
def extract(code, person) do
case :lists.keyfind(code, 2, person) do
false -> ""
{_, _, {:printable, str}} -> str
{_, _, {:utf8, str}} -> str
end
end
def parseSignData(bin) do
{_, {:ContentInfo, _, ci}} = :KEP.decode(:ContentInfo, bin)
{:ok, {:SignedData, _, alg, x, c, x1, x2}} = :KEP.decode(:SignedData, ci)
parseSignDataCert({alg,x,c,x1,x2})
end
def parseSignDataCert({_,_,:asn1_NOVALUE,_,_}), do: []
def parseSignDataCert({_,_,[cert],_,_}), do: parseCert(cert)
def parseAttrs(attrs) do
certAttrs(
o: extract({2, 5, 4, 10}, attrs),
ou: extract({2, 5, 4, 11}, attrs),
title: extract({2, 5, 4, 12}, attrs),
cn: extract({2, 5, 4, 3}, attrs),
givenName: extract({2, 5, 4, 42}, attrs),
surname: extract({2, 5, 4, 4}, attrs),
locality: extract({2, 5, 4, 7}, attrs),
serial: extract({2, 5, 4, 5}, attrs),
c: extract({2, 5, 4, 6}, attrs)
)
end
def pair([],acc), do: acc
def pair([x],acc), do: [x|acc]
def pair([a,b|t],acc), do: pair(t,[{:oid.decode(a),b}|acc])
def oid({1,3,6,1,5,5,7,1,1}, v), do: {:authorityInfoAccess, pair(v,[])}
def oid({1,3,6,1,5,5,7,1,3}, [v]), do: {:qcStatements, :oid.decode v}
def oid({1,3,6,1,5,5,7,1,11},v), do: {:subjectInfoAccess, pair(v,[])}
def oid({2,5,29,9},v), do: {:subjectDirectoryAttributes, pair(v,[])}
def oid({2,5,29,14},v), do: {:subjectKeyIdentifier, pair(v,[])}
def oid({2,5,29,15},v), do: {:keyUsage, pair(v,[])}
def oid({2,5,29,16},v), do: {:privateKeyUsagePeriod, v}
def oid({2,5,29,17},v), do: {:subjectAltName, pair(v,[])}
def oid({2,5,29,19},v), do: {:basicConstraints, pair(v,[])}
def oid({2,5,29,31},v), do: {:cRLDistributionPoints, pair(v,[])}
def oid({2,5,29,32},[v]), do: {:certificatePolicies, :oid.decode v}
def oid({2,5,29,35},v), do: {:authorityKeyIdentifier, pair(v,[])}
def oid({2,5,29,46},v), do: {:freshestCRL, pair(v,[])}
def oid(x,v) when is_binary(x), do: {:oid.decode(x),pair(v,[])}
def oid(x,v), do: {x,v}
def flat(code,{k,v},acc) when is_integer(k), do: [flat(code,v,acc)|acc]
def flat(code,{k,_v},acc), do: [flat(code,k,acc)|acc]
def flat(code,k,acc) when is_list(k), do: [:lists.map(fn x -> flat(code,x,acc) end, k)|acc]
def flat(_code,k,acc) when is_binary(k), do: [k|acc]
def parseCert(cert) do
{:Certificate, a, _, _} = cert
{:Certificate_toBeSigned, _ver, _sel, _alg, issuer, _val, issuee, _, _, _, exts} = a
extensions = :lists.map(fn {:Extension,code,_,b} ->
oid(code, :lists.flatten(flat(code,:asn1rt_nif.decode_ber_tlv(b),[])))
end, exts)
person = :lists.flatten(:erlang.element(2, issuee))
ca = :lists.flatten(:erlang.element(2, issuer))
{parseAttrs(person),parseAttrs(ca),extensions}
end
end