diff --git a/include/DSTU.hrl b/include/DSTU.hrl index 1a870e7..7247fb0 100644 --- a/include/DSTU.hrl +++ b/include/DSTU.hrl @@ -1,4 +1,4 @@ -%% Generated by the Erlang ASN.1 compiler. Version: 5.2.2 +%% Generated by the Erlang ASN.1 compiler. Version: 5.0.17 %% Purpose: Erlang record definitions for each named and unnamed %% SEQUENCE and SET, and macro definitions for each value %% definition in module DSTU. @@ -13,7 +13,7 @@ }). -record('TBSCertificate', { - version, + version = asn1_DEFAULT, serialNumber, signature, issuer, diff --git a/lib/services/crt.ex b/lib/services/crt.ex index 0c7b4bd..2515c4c 100644 --- a/lib/services/crt.ex +++ b/lib/services/crt.ex @@ -108,28 +108,28 @@ defmodule CA.CRT do 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 rdn({2, 5, 4, 3}), do: :"cn" # "commonName" - def rdn({2, 5, 4, 4}), do: :"sn" # "surename" - def rdn({2, 5, 4, 6}), do: :"c" # "country" - def rdn({2, 5, 4, 7}), do: :"l" # "localityName" - def rdn({2, 5, 4, 10}), do: :"o" # "organization" - def rdn({2, 5, 4, 11}), do: :"ou" # "organizationalUnit" - - def rdn({2, 5, 4, 5}), do: :"serialNumber" - def rdn({2, 5, 4, 8}), do: :"stateOrProvinceName" - def rdn({2, 5, 4, 12}), do: :"title" - def rdn({2, 5, 4, 13}), do: :"description" - def rdn({2, 5, 4, 14}), do: :"device" - def rdn({2, 5, 4, 15}), do: :"businessCategory" - def rdn({2, 5, 4, 42}), do: :"givenName" - def rdn({2, 5, 4, 97}), do: :"organizationIdentifier" - def rdn({2, 5, 6, 3}), do: :"locality" - def rdn({2, 5, 6, 4}), do: :"organization" - def rdn({2, 5, 6, 5}), do: :"organizationalUnit" - def rdn({2, 5, 6, 6}), do: :"person" - def rdn({2, 5, 6, 7}), do: :"organizationalPerson" - def rdn({2, 5, 6, 8}), do: :"organizationalRole" - def rdn({2, 5, 6, 9}), do: :"groupOfNames" + def rdn({2, 5, 4, 3}), do: :cn # "commonName" + def rdn({2, 5, 4, 4}), do: :sn # "surename" + def rdn({2, 5, 4, 6}), do: :c # "country" + def rdn({2, 5, 4, 7}), do: :l # "localityName" + def rdn({2, 5, 4, 10}), do: :o # "organization" + def rdn({2, 5, 4, 11}), do: :ou # "organizationalUnit" + + def rdn({2, 5, 4, 5}), do: :serialNumber + def rdn({2, 5, 4, 8}), do: :stateOrProvinceName + def rdn({2, 5, 4, 12}), do: :title + def rdn({2, 5, 4, 13}), do: :description + def rdn({2, 5, 4, 14}), do: :device + def rdn({2, 5, 4, 15}), do: :businessCategory + def rdn({2, 5, 4, 42}), do: :givenName + def rdn({2, 5, 4, 97}), do: :organizationIdentifier + def rdn({2, 5, 6, 3}), do: :locality + def rdn({2, 5, 6, 4}), do: :organization + def rdn({2, 5, 6, 5}), do: :organizationalUnit + def rdn({2, 5, 6, 6}), do: :person + def rdn({2, 5, 6, 7}), do: :organizationalPerson + def rdn({2, 5, 6, 8}), do: :organizationalRole + def rdn({2, 5, 6, 9}), do: :groupOfNames def rdn({0,9,2342,19200300,100,1,25}), do: "dc" # "domainComponent" def rdn({:rdnSequence, list}) do @@ -146,27 +146,35 @@ defmodule CA.CRT do {_,oid, list} -> "#{rdn(oid)}=#{list}" end, list), "/" end - def decodePointFromPublic(oid0,oid,publicKey) do + def baseLength(oid) when is_tuple(oid) do CA.Curve.getLength(CA.KnownCurves.getCurveByOid(oid)) end + def baseLength(_) do 256 end + + def decodePointFromPublic(agreement,params,publicKey) do bin = :binary.part(publicKey,1,:erlang.size(publicKey)-1) - curve = CA.KnownCurves.getCurveByOid(oid) - baseLength = CA.Curve.getLength(curve) + baseLength = baseLength(params) xs = :binary.part(bin, 0, baseLength) ys = :binary.part(bin, baseLength, :erlang.size(bin) - baseLength) - [ scheme: :erlang.element(1,CA.ALG.lookup(oid0)), - curve: :erlang.element(1,CA.ALG.lookup(oid)), - x: CA.ECDSA.numberFromString(xs), - y: CA.ECDSA.numberFromString(ys) + [ x: CA.ECDSA.numberFromString(xs), + y: CA.ECDSA.numberFromString(ys), + scheme: CA.AT.oid(agreement), + curve: CA.AT.oid(params), ] end - def decodePublicKey(oid,oid2,publicKey) do - case oid do - {1,2,804,2,1,1,1,1,3,6,1,1} -> :base64.encode publicKey - {1,2,804,2,1,1,1,1,3,1,1} -> :base64.encode publicKey - {1,2,840,10045,2,1} -> decodePointFromPublic(oid, CA.EST.decodeObjectIdentifier(oid2),publicKey) - {1,2,840,113549,1,1,1} -> {:ok, key} = :"PKCS-1".decode(:'RSAPublicKey', publicKey) ; key - _ -> :io.format 'new publicKey oid: ~p~n', [oid] - :base64.encode publicKey + def decodePublicKey(agreement,{:asn1_OPENTYPE, params},publicKey) do decodePublicKey(agreement,params,publicKey) end + def decodePublicKey(agreement,params,publicKey) do + case agreement do + {1,2,804,2,1,1,1,1,3,1,1} -> # ДСТУ-4145 + {:ok,p} = :DSTU.decode(:DSTU4145Params, params) + [key: publicKey, scheme: CA.AT.oid(agreement), field: p] + {1,2,840,10045,2,1} -> # ECDSA + params = CA.EST.decodeObjectIdentifier(params) + decodePointFromPublic(agreement,params,publicKey) + {1,2,840,113549,1,1,1} -> # RSA + {:ok, key} = :"PKCS-1".decode(:'RSAPublicKey', publicKey) + [key: key, scheme: :RSA] + _ -> :io.format 'new publicKey agreement scheme detected: ~p~n', [agreement] + :base64.encode publicKey end end @@ -184,7 +192,7 @@ defmodule CA.CRT do end {_, ver, serial, {_,alg,_}, issuer, {_,{_,nb},{_,na}}, issuee, - {:SubjectPublicKeyInfo, {_, oid, oid2}, publicKey}, _b, _c, exts} = tbs + {:SubjectPublicKeyInfo, {_, agreement, params}, publicKey}, _b, _c, exts} = tbs extensions = :lists.map(fn {:Extension,code,_x,b} -> oid(code, :lists.flatten(flat(code,:asn1rt_nif.decode_ber_tlv(b),[]))) end, exts) @@ -195,7 +203,7 @@ defmodule CA.CRT do issuer: rdn(unsubj(issuer)), serial: :base64.encode(CA.EST.integer(serial)), validity: [from: nb, to: na], - publicKey: decodePublicKey(oid, oid2, publicKey), + publicKey: decodePublicKey(agreement, params, publicKey), extensions: extensions ] end diff --git a/priv/csr/DSTU.asn1 b/priv/csr/DSTU.asn1 index 23e0b23..69cc3f6 100644 --- a/priv/csr/DSTU.asn1 +++ b/priv/csr/DSTU.asn1 @@ -40,7 +40,7 @@ Extension ::= SEQUENCE { extnvalue OCTET STRING } AttributeType ::= OBJECT IDENTIFIER -AttributeValue ::= ANY DEFINED BY AttributeType +AttributeValue ::= ANY --DEFINED BY AttributeType DirectoryString ::= CHOICE { printableString PrintableString, utf8String UTF8String, @@ -65,6 +65,8 @@ AlgorithmIdentifier ::= SEQUENCE { parameters ANY } -- DEFINED BY algorithm OPTIONAL +OctetString ::= OCTET STRING + DSTU4145Params::= SEQUENCE { definition CHOICE { ecbinary ECBinary, namedCurve OBJECT IDENTIFIER }, dke OCTET STRING OPTIONAL } diff --git a/src/DSTU.erl b/src/DSTU.erl index 7010148..11f1c24 100644 --- a/src/DSTU.erl +++ b/src/DSTU.erl @@ -1,4 +1,4 @@ -%% Generated by the Erlang ASN.1 BER compiler. Version: 5.2.2 +%% Generated by the Erlang ASN.1 BER compiler. Version: 5.0.17 %% Purpose: Encoding and decoding of the types in DSTU. -module('DSTU'). @@ -6,13 +6,13 @@ -dialyzer(no_improper_lists). -dialyzer(no_match). -include_lib("ca/include/DSTU.hrl"). --asn1_info([{vsn,'5.2.2'}, +-asn1_info([{vsn,'5.0.17'}, {module,'DSTU'}, {options,[warnings,ber,errors, - {cwd,"/Users/5ht/depot/arvo-computer/ca/priv/csr"}, - {outdir,"/Users/5ht/depot/arvo-computer/ca/priv/csr"}, + {cwd,"/home/maxim/depot/arvo-computer/ca/priv/csr"}, + {outdir,"/home/maxim/depot/arvo-computer/ca/priv/csr"}, {i,"."}, - {i,"/Users/5ht/depot/arvo-computer/ca/priv/csr"}]}]). + {i,"/home/maxim/depot/arvo-computer/ca/priv/csr"}]}]). -export([encoding_rule/0,maps/0,bit_string_format/0, legacy_erlang_types/0]). @@ -37,6 +37,7 @@ enc_Validity/2, enc_Time/2, enc_SubjectPublicKeyInfo/2, enc_AlgorithmIdentifier/2, +enc_OctetString/2, enc_DSTU4145Params/2, enc_ECBinary/2, enc_BinaryField/2, @@ -64,6 +65,7 @@ dec_Validity/2, dec_Time/2, dec_SubjectPublicKeyInfo/2, dec_AlgorithmIdentifier/2, +dec_OctetString/2, dec_DSTU4145Params/2, dec_ECBinary/2, dec_BinaryField/2, @@ -134,6 +136,7 @@ encode_disp('Validity', Data) -> enc_Validity(Data); encode_disp('Time', Data) -> enc_Time(Data); encode_disp('SubjectPublicKeyInfo', Data) -> enc_SubjectPublicKeyInfo(Data); encode_disp('AlgorithmIdentifier', Data) -> enc_AlgorithmIdentifier(Data); +encode_disp('OctetString', Data) -> enc_OctetString(Data); encode_disp('DSTU4145Params', Data) -> enc_DSTU4145Params(Data); encode_disp('ECBinary', Data) -> enc_ECBinary(Data); encode_disp('BinaryField', Data) -> enc_BinaryField(Data); @@ -160,6 +163,7 @@ decode_disp('Validity', Data) -> dec_Validity(Data); decode_disp('Time', Data) -> dec_Time(Data); decode_disp('SubjectPublicKeyInfo', Data) -> dec_SubjectPublicKeyInfo(Data); decode_disp('AlgorithmIdentifier', Data) -> dec_AlgorithmIdentifier(Data); +decode_disp('OctetString', Data) -> dec_OctetString(Data); decode_disp('DSTU4145Params', Data) -> dec_DSTU4145Params(Data); decode_disp('ECBinary', Data) -> dec_ECBinary(Data); decode_disp('BinaryField', Data) -> dec_BinaryField(Data); @@ -1058,6 +1062,24 @@ Res1 = {'AlgorithmIdentifier',Term1,Term2}, Res1. +%%================================ +%% OctetString +%%================================ +enc_OctetString(Val) -> + enc_OctetString(Val, [<<4>>]). + +enc_OctetString(Val, TagIn) -> +encode_restricted_string(Val, TagIn). + + +dec_OctetString(Tlv) -> + dec_OctetString(Tlv, [4]). + +dec_OctetString(Tlv, TagIn) -> +decode_octet_string(Tlv, TagIn). + + + %%================================ %% DSTU4145Params %%================================ @@ -1609,7 +1631,7 @@ encode_integer(Val, Tag) when is_integer(Val) -> encode_integer(Val, _Tag) -> exit({error, {asn1, {encode_integer, Val}}}). -encode_integer_neg(-1, [B1 | _T] = L) when B1 > 127 -> +encode_integer_neg(- 1, [B1 | _T] = L) when B1 > 127 -> L; encode_integer_neg(N, Acc) -> encode_integer_neg(N bsr 8, [N band 255 | Acc]).