Giter Site home page Giter Site logo

esaml's Introduction

An implementation of the Security Assertion Markup Language (SAML) in Erlang. So far this supports enough of the standard to act as a Service Provider (SP) to perform authentication with SAML. It has been tested extensively against the SimpleSAMLPHP IdP and can be used in production.

Supported protocols

The SAML standard refers to a flow of request/responses that make up one concrete action as a "protocol". Currently all of the basic Single-Sign-On and Single-Logout protocols are supported. There is no support at present for the optional Artifact Resolution, NameID Management, or NameID Mapping protocols.

Future work may add support for the Assertion Query protocol (which is useful to check if SSO is already available for a user without demanding they authenticate immediately).

Single sign-on protocols:

  • SP: send AuthnRequest (REDIRECT or POST) -> receive Response + Assertion (POST)

Single log-out protocols:

  • SP: send LogoutRequest (REDIRECT) -> receive LogoutResponse (REDIRECT or POST)
  • SP: receive LogoutRequest (REDIRECT OR POST) -> send LogoutResponse (REDIRECT)

esaml supports RSA+SHA1/SHA256 signing of all SP payloads, and validates signatures on all IdP responses. Compatibility flags are available to disable verification where IdP implementations lack support (see the esaml_sp record, and members such as idp_signs_logout_requests).

API documentation

Edoc documentation for the whole API is available at:

http://arekinath.github.io/esaml/

Licensing

2-clause BSD

Getting started

The simplest way to use esaml in your app is with the esaml_cowboy module. There is an example under examples/sp that shows how to make a simple SAML SP in this way.

Each of the protocols you wish to support will normally require at least one distinct URL endpoint, plus one additional URL for the SAML SP metadata. In the sp example, only one protocol is used: the single-sign-on SP AuthnRequest -> Response + Assertion protocol.

The typical approach is to use a single Cowboy route for all SAML endpoints:

Dispatch = cowboy_router:compile([
    {'_', [
        {"/saml/:operation", sp_handler, []}
    ]}
])

Then, based on the value of the operation binding, you can decide which protocol to proceed with, by matching these up with the URIs you supply to esaml_sp:setup/1.

init(_Transport, Req, _Args) ->
    ...
    SP = esaml_sp:setup(#esaml_sp{
        consume_uri = Base ++ "/consume",
        metadata_uri = Base ++ "/metadata",
        ...
    }),
    ...

handle(Req, S = #state{}) ->
    {Operation, Req2} = cowboy_req:binding(operation, Req),
    {Method, Req3} = cowboy_req:method(Req2),
    handle(Method, Operation, Req3, S).

handle(<<"GET">>, <<"metadata">>, Req, S) ->
    ...

handle(<<"POST">>, <<"consume">>, Req, S) ->
    ...

The functions on the esaml_cowboy module can either parse and validate an incoming SAML payload, or generate one and reply to the request with it.

For example, the way the metadata endpoint is handled in the example is to unconditionally call esaml_cowboy:reply_with_metadata/2, which generates the SP metadata and replies to the request:

handle(<<"GET">>, <<"metadata">>, Req, S = #state{sp = SP}) ->
    {ok, Req2} = esaml_cowboy:reply_with_metadata(SP, Req),
    {ok, Req2, S};

On the other hand, the consumer endpoint (which handles the second step in the SSO protocol, receiving the Response + Assertion from the IdP) has to validate its payload before replying:

handle(<<"POST">>, <<"consume">>, Req, S = #state{sp = SP}) ->
    case esaml_cowboy:validate_assertion(SP, Req) of
        {ok, Assertion, RelayState, Req2} ->
            % authentication success!
            ...;

        {error, Reason, Req2} ->
            {ok, Req3} = cowboy_req:reply(403, [{<<"content-type">>, <<"text/plain">>}],
                ["Access denied, assertion failed validation\n"], Req2),
            {ok, Req3, S}
    end;

More complex configurations, including multiple IdPs, dynamic retrieval of IdP metadata, and integration with many kinds of application authentication systems are possible.

The second esaml example, sp_with_logout demonstrates the addition endpoints necessary to enable Single Log-out protocol support. It also shows how you can build a bridge from esaml to local application session storage, by generating session cookies for each user that logs in (and storing them in ETS).

More advanced usage

You can also tap straight into lower-level APIs in esaml if esaml_cowboy doesn't meet your needs. The esaml_binding and esaml_sp modules are the interface used by esaml_cowboy itself, and contain all the basic primitives to generate and parse SAML payloads.

This is particularly useful if you want to implement SOAP endpoints using SAML.

Contributions

Pull requests are always welcome for bug fixes and improvements. Fixes that enable compatibility with different IdP implementations are usually welcome, but please ensure they do not come at the expense of compatibility with another IdP. esaml prefers to follow as closely to the SAML standards as possible.

Bugs/issues opened without patches are also welcome, but might take a lot longer to be looked at. ;)

esaml's People

Contributors

arekinath avatar igorkarymov avatar jlarky avatar petrohi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

esaml's Issues

inconsistency with sp_private_key and sp_certificate values

I see in some places those options can be undefined, but in others none. My usecase is to not use sp_private_key, but if I set it to undefined, but it becomes none and later check done for not (SP#esaml_sp.key =:= undefined) and it fails fails

Xpath search failing - failure to validate assertion in xmerl_dsig:verify

Using Erlang 18, and Okta dev endpoint for a test SAML response. Handler code is using the esaml SP sample as the reference.

Response validation fails with this message:

Access denied, assertion failed validation:
{{badmatch,[]},
 [{xmerl_dsig,verify,2,
              [{file,"/mnt/sync/delivery/server/deps/esaml/src/xmerl_dsig.erl"},
               {line,169}]},
  {esaml_sp,'-validate_assertion/3-fun-1-',4,
            [{file,"src/esaml_sp.erl"},{line,209}]},
  {esaml_util,threaduntil,2,[{file,"src/esaml_util.erl"},{line,88}]},
  {esaml_cowboy,validate_assertion,3,
                [{file,"src/esaml_cowboy.erl"},{line,168}]},
  {deliv_hand_saml_consume,handle_post,3,
                           [{file,"src/deliv_hand_saml_consume.erl"},
                            {line,41}]},
  {cowboy_handler,handler_handle,4,
                  [{file,"src/cowboy_handler.erl"},{line,111}]},
  {cowboy_protocol,execute,4,[{file,"src/cowboy_protocol.erl"},{line,435}]}]}

Debugging into the code, the failure is at line 169, in xmerl_dsig.erl:

 [#xmlAttribute{value = SignatureMethodAlgorithm}] = xmerl_xpath:string("ds:Signature/ds:SignedInfo/ds:SignatureMethod/@Algorithm", Element, [{namespace, DsNs}]),

The problem is that the xpath is not finding anything, just returning an empty element.
Changing the search string to be "//ds:Signature/ds:SignedInfo/ds:SignatureMethod/@Algorithm" fixes the problem.

A sample response XML that illustrates the problem is below.

<samlp:Assertion xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_nmT8siYgDw0GAxhwwyEIJR29z50CCCJv" IssueInstant="2016-05-05T21:14:48.906Z">
  <saml:Issuer>http://example.com/saml/acs/example</saml:Issuer>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <Reference URI="#_nmT8siYgDw0GAxhwwyEIJR29z50CCCJv">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>717x5bSFCJyKOf04gycEXhWSyLs=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>Uo7qsqdQ8+DoPkQIQ6JKMeKLPvh3/KwtKogneQr9eZr8lMoeWJwjw8HYpQoc45/2lCjDh5bugJf952688ug9Gyc5Bvfqvi0ms/OVagyOFBmoNG/hgtw9uvPD/Z8jI/WLWQUcA/zGMZFhUoVdputNRHtU7vr53Sr9Gh9EtrqMv9cbbT3yQKGAwFNAYKJNb/znSG16xEoAVs4QZxSBPcSCGNoTtNpGfuKgtdMNnQKHFvyqq3gtGdhRIeqQHy2Q6C0xTYXfzoqvpRBFsIZiPfxi1rdNW/O9NRO4bwI5CWG1ssjTjTAvdhYBFLMyPdLXjvDl9qT51dXtuIeSVIuo0XolPg==</SignatureValue>
    <KeyInfo>
      <X509Data>
        <X509Certificate>MIIDPDCCAiQCCQDydJgOlszqbzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEQMA4GA1UEChMHSmFua3lDbzESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE0MDMxMjE5NDYzM1oXDTI3MTExOTE5NDYzM1owYDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEDAOBgNVBAoTB0phbmt5Q28xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGvJpRTTasRUSPqcbqCG+ZnTAurnu0vVpIG9lzExnh11o/BGmzu7lB+yLHcEdwrKBBmpepDBPCYxpVajvuEhZdKFx/Fdy6j5mH3rrW0Bh/zd36CoUNjbbhHyTjeM7FN2yF3u9lcyubuvOzr3B3gX66IwJlU46+wzcQVhSOlMk2tXR+fIKQExFrOuK9tbX3JIBUqItpI+HnAow509CnM134svw8PTFLkR6/CcMqnDfDK1m993PyoC1Y+N4X9XkhSmEQoAlAHPI5LHrvuujM13nvtoVYvKYoj7ScgumkpWNEvX652LfXOnKYlkB8ZybuxmFfIkzedQrbJsyOhfL03cMECAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAeHwzqwnzGEkxjzSD47imXaTqtYyETZow7XwBc0ZaFS50qRFJUgKTAmKS1xQBP/qHpStsROT35DUxJAE6NY1Kbq3ZbCuhGoSlY0L7VzVT5tpu4EY8+Dq/u2EjRmmhoL7UkskvIZ2n1DdERtd+YUMTeqYl9co43csZwDno/IKomeN5qaPc39IZjikJ+nUC6kPFKeu/3j9rgHNlRtocI6S1FdtFz9OZMQlpr0JbUt2T3xS/YoQJn6coDmJL5GTiiKM6cOe+Ur1VwzS1JEDbSS2TWWhzq8ojLdrotYLGd9JOsoQhElmz+tMfCFQUFLExinPAyy7YHlSiVX13QH2XTu/iQQ==</X509Certificate>
      </X509Data>
    </KeyInfo>
  </Signature>
  <saml:Subject>
    <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">[email protected]</saml:NameID>
    <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
      <saml:SubjectConfirmationData NotOnOrAfter="2016-05-05T22:14:48.906Z" Recipient="http://192.168.33.66/api/v0/e/cd/saml/consume" InResponseTo="5e0b9802-1306-11e6-9037-080027c97816" />
    </saml:SubjectConfirmation>
  </saml:Subject>
  <saml:Conditions NotBefore="2016-05-05T21:14:48.906Z" NotOnOrAfter="2016-05-05T22:14:48.906Z">
    <saml:AudienceRestriction>
      <saml:Audience>http://example.com/saml/acs/example</saml:Audience>
    </saml:AudienceRestriction>
  </saml:Conditions>
  <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <saml:Attribute Name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
      <saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="Email">
      <saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="FirstName">
      <saml:AttributeValue xsi:type="xs:anyType">Ilango</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="LastName">
      <saml:AttributeValue xsi:type="xs:anyType">Chinnasamy</saml:AttributeValue>
    </saml:Attribute>
  </saml:AttributeStatement>
  <saml:AuthnStatement AuthnInstant="2016-05-05T21:14:48.906Z">
    <saml:AuthnContext>
      <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
    </saml:AuthnContext>
  </saml:AuthnStatement>
</samlp:Assertion>

xmldsig is not working with unicode atributes

i got {error, bad_digest} in the case when assertion displayName was setted in "Игорь Карымов" value.
Actually i'm not sure that bug in esaml library because it's also possible that issue in simplesamlphp library (i use 1.8.2-1 version).

ID generation is not compatible with Azure AD

According to the Azure AD SAML spec at https://msdn.microsoft.com/en-us/library/azure/dn195589.aspx:

"Azure Active Directory uses the value of the ID attribute to populate the InResponseTo attribute of the SAML Response that it returns. The SAML specification requires that the value of ID must not begin with a number. A common strategy to generate a value for the ID attribute is to prepend a predefined string, such as "id", to the string representation of a GUID."

However, eSAML generates a UUID:
-spec add_xml_id(xml()) -> xml().
add_xml_id(Xml) ->
Xml#xmlElement{attributes = Xml#xmlElement.attributes ++ [
#xmlAttribute{name = 'ID',
value = uuid:to_string(uuid:uuid1()),
namespace = #xmlNamespace{}}
]}.

Eg:"2451eff2-13d4-11e6-b78e-080027c97816"

This looks like it may be the cause of Azure AD rejecting AuthnN requests sent by eSAML.

okta service integration {error, bad_digest} (lack of support of InclusiveNamespaces?)

Signature verification is working fine when AttributeStatement is not presented.
But if okta started send user attributes i got {error,bad_digest} error.
I noticed that difference between this responses in additional child for Transform element:

<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"></ec:InclusiveNamespaces>
</ds:Transform>

https://drive.google.com/#folders/0BzsH_XaDBRd7SV9XLWVLLWlzMlk

Work with Azure AD

Hi there.

Trying to get esaml (branch develop) to work with Azure, the following things came up:

  1. the c14n issue already fixed by @zuckschwerdt in #15,
  2. the Azure IdP rejects Authn Requests that include a Subject (although the docs claim that it'd be ignored)
  3. by default, Azure's AD doesn't respond with NameId of format urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

There's a combined commit for 2. and 3. here, but this solution might not be the only possible one. What do you think is the best way for azure compatibility? Just remove the Subject (2.) and let the user cope with that NameID comes in the response, or expose the NameIdPolicy to make it configurable (in esaml_sp)?

Thanks

Assertion validation fails for Microsoft Azure IdP Authn response

Erlang 18.

Calling esaml_cowboy:validate_assertion(SP, Req) fails. In xmerl_dsig.erl, it fails at the point of calling
public_key:verify(Data, HashFunction, Sig, Key), which returns false (this fails at crypto:verify).

Everything works fine if Okta is the IdP. The only difference between the Okta and Azure IdP seems to be the key length (Azure is 2048 bits), as well as use of SHA1 (Azure is not using SHA1) in the signature computation.

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            40:d5:eb:9b:38:4b:37:85:46:95:45:c3:60:24:53:df
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=accounts.accesscontrol.windows.net
        Validity
            Not Before: Oct 28 00:00:00 2014 GMT
            Not After : Oct 27 00:00:00 2016 GMT
        Subject: CN=accounts.accesscontrol.windows.net
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:bc:8a:b3:fb:8f:84:47:fb:cd:58:b3:8d:f7:2b:
                    fc:84:86:15:ef:7e:c9:43:aa:c2:97:a5:df:cc:e0:
                    ba:db:cb:1e:61:43:df:d1:36:86:93:dd:42:17:17:
                    9f:87:38:76:dd:5f:53:92:af:91:b7:03:75:56:cf:
                    f3:e7:b8:4e:f3:69:24:cc:bf:9c:40:76:57:dd:b3:
                    09:0f:e1:84:18:e2:97:08:45:d4:44:de:d5:33:26:
                    56:30:0b:b3:42:85:bd:bc:56:f5:93:77:11:d5:15:
                    bf:11:6f:cf:f8:2f:1b:6f:67:42:19:78:41:62:a3:
                    df:1f:28:a6:bf:3d:96:6a:b5:e1:9e:d3:d2:6c:ce:
                    57:c9:2e:6f:e7:20:b0:e5:3f:d5:bb:0a:aa:b2:2a:
                    37:57:cc:28:a1:61:8c:a6:9e:b5:cb:5d:8d:84:df:
                    1b:35:50:d0:02:40:cf:36:ed:83:4f:d0:d7:07:58:
                    34:09:e1:48:36:9f:ca:01:2f:ea:43:62:aa:e9:34:
                    af:44:72:6a:c5:14:7a:f1:17:b3:62:d8:de:f4:a0:
                    2a:c2:ac:78:8f:19:66:54:04:32:d1:3d:fe:4f:e2:
                    00:6e:c9:35:c1:1b:56:0e:77:61:3b:ab:35:3a:cf:
                    9d:72:4e:53:cf:26:7f:74:d3:a1:7d:78:1e:96:2c:
                    4b:51
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         7e:89:71:e3:9c:34:8b:c0:9d:01:48:e3:78:06:98:76:11:bd:
         f8:d0:c7:c6:8a:74:52:f3:4e:aa:51:aa:60:97:b1:a8:f2:ee:
         bd:7f:22:c9:46:98:c4:d1:b3:67:11:60:18:8d:c6:a4:a7:e6:
         40:fd:89:41:64:35:13:92:6d:63:f9:fc:88:d2:ce:29:13:30:
         aa:4b:b1:48:22:89:c5:92:6a:e1:29:7f:9b:f6:2f:ed:34:b5:
         3f:92:cd:80:08:fc:40:b0:b2:a7:1b:16:ad:30:26:ab:61:d2:
         a6:47:92:93:82:41:b6:c6:31:5f:ab:a1:6c:63:3f:2b:5b:04:
         92:d2:b2:6d:54:c7:bb:6d:bf:ed:39:91:a9:64:e6:39:4c:bd:
         c1:0b:cc:8c:96:f6:21:77:4c:18:b1:b7:85:59:ed:37:f5:96:
         72:ce:70:f2:f6:ed:d6:2f:0a:93:aa:35:f5:6d:8c:8d:9f:79:
         25:a1:02:2a:30:43:61:19:61:1b:52:a6:48:1b:6b:b0:ab:02:
         05:0a:01:cf:01:ff:ad:77:e4:b1:33:bd:26:85:18:2d:78:96:
         d0:8a:69:07:b0:e1:34:7e:0f:27:98:59:23:dd:51:f2:b4:74:
         1f:7f:db:2a:42:d2:b8:36:8a:2d:64:aa:32:1a:33:76:15:ec:
         20:82:af:25

Here is some debug output:

Data: <<"<ds:SignedInfo xmlns="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#\"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#\">/ds:CanonicalizationMethod<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\">/ds:SignatureMethod<ds:Reference URI="#_2ded4e62-67bd-4a07-9e41-3307ff40b6e5">ds:Transforms<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature\">/ds:Transform<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#\">/ds:Transform/ds:Transforms<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256\">/ds:DigestMethodds:DigestValueujwSqga3Io7RgnLVHAFnZqCuS9UBhZazFp7tTmJYKds=/ds:DigestValue/ds:Reference/ds:SignedInfo">>
HashFunction: sha256
Sig: <<84,170,226,155,114,237,132,105,192,71,242,254,39,250,196,46,160,178,30,
51,41,11,171,152,227,152,104,116,134,247,9,231,141,131,173,159,104,47,
152,103,113,21,122,203,169,25,196,107,137,170,25,250,43,44,40,79,230,
224,56,216,36,151,173,173,241,207,74,123,76,77,188,90,119,208,92,64,214,
120,17,8,132,126,229,154,70,72,136,142,141,34,77,214,136,185,218,24,225,
42,18,51,237,39,18,145,98,10,110,5,173,148,13,228,203,196,178,127,27,
103,130,46,1,250,75,87,189,2,237,220,189,161,180,225,245,65,68,156,85,
233,99,60,41,34,133,123,197,188,93,0,175,41,89,63,39,68,77,172,56,224,1,
3,96,27,157,111,244,140,160,40,149,73,105,73,161,74,17,93,22,125,100,
121,241,182,148,24,68,214,45,12,68,110,231,53,154,81,202,69,115,182,9,
237,110,100,88,88,15,241,9,96,203,215,5,241,223,191,99,199,12,233,32,39,
209,80,156,114,174,149,46,250,145,148,145,106,148,73,103,101,99,148,149,
62,148,148,2,75,9,47,120,45,98,214,6,39,14,45,14,55>>
Key: {'RSAPublicKey',23801198360346180032294480920715767764472197020631570074480649915781538912816195975417363780765112968383673580578571989252090383113994304028563474394397459725649506248716739361908616836476913309708506822850917404774975668734124236432466647775976571217892167355716913557523437407297392112679627645666491794339857374054870860501484016751889383673483750306612278874647610454856410468740384624100471457481543991766630885386515400127553119191608234405247675208060619388776358270769904028886336830442777210583872889885286842313649680068015006466942721801737282566078347249842971299237584314259050491201295146063321006623569,
65537}

unused dependency: lager

i didn't find any usage of lager in the code.
So it will be better if top level release decide what logger should be used.

xmerl_dsig fails due to mismatched SubjectPublicKeyInfo record format

Using Erlang 18.

xmerl_dsig line 204 is:

       {_, KeyBin} = Cert#'Certificate'.tbsCertificate#'TBSCertificate'.subjectPublicKeyInfo#'SubjectPublicKeyInfo'.subjectPublicKey,

This does not match the record definition for SubjectPublicKeyInfo from the erlang docs site:

#'SubjectPublicKeyInfo'{
      algorithm,       % #AlgorithmIdentifier{} 
      subjectPublicKey % binary() 
     }.

so it’s expecting a {any(), binary()} and getting a binary()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.