Open voltone opened 6 years ago
@voltone Have you ever figured out how to define custom extensions with Erlang's certificate support?
Some extensions are already decoded by Erlang's :public_key
, such as those mentioned at the top of this ticket, I just haven't added convenience functions to X509.Certificate.Extension
for them yet. You can still look them up and work with the Erlang record directly, e.g.:
iex(3)> aia = {1, 3, 6, 1, 5, 5, 7, 1, 1}
iex(4)> pem |> X509.Certificate.from_pem!() |> X509.Certificate.extension(aia)
{:Extension, {1, 3, 6, 1, 5, 5, 7, 1, 1}, false,
[
{:AccessDescription, {1, 3, 6, 1, 5, 5, 7, 48, 1},
{:uniformResourceIdentifier, 'http://ocsp.starfieldtech.com/'}},
{:AccessDescription, {1, 3, 6, 1, 5, 5, 7, 48, 2},
{:uniformResourceIdentifier,
'http://certificates.starfieldtech.com/repository/sfig2.crt'}}
]}
Same thing for encoding certificates with additional extensions.
Any unknown extensions are represented as DER binaries, which you can encode/decode manually with a suitable ASN.1 encoder.
Is there any particular extension you are interested in @GalaxyGorilla?
@voltone thanks for the answer! However, I meant custom extensions, e.g. not standard extensions. I want to create my own extensions for client certificates. I'll test around throughout the week and check what's possible.
Unfortunately I'm developing in Erlang, so I can't use your lib at all :(.
@voltone thanks for the answer! However, I meant custom extensions, e.g. not standard extensions. I want to create my own extensions for client certificates. I'll test around throughout the week and check what's possible.
You basically just need an OID and a blob of DER-encoded data. You can mint your own OIDs within the enterprise namespace if you have an OUI. Producing a DER version of some data structure may require defining some ASN.1 syntax and generating the encoder and decoder functions, along with a header file for the record. Or you can cheat by using the undocumented asn1rt_nif
module, e.g. to wrap an arbitrary binary:
1> Hello = <<"Hello, world!">>.
<<"Hello, world!">>
2> asn1rt_nif:encode_ber_tlv({16, [{131072, Hello}]}).
<<48,15,128,13,72,101,108,108,111,44,32,119,111,114,108,
100,33>>
Unfortunately I'm developing in Erlang, so I can't use your lib at all :(.
I actually have a branch somewhere that rewrites much of the code to Erlang, with the Elixir code becoming a thin wrapper and adapter to Elixir data types (e.g. DateTime
). When pulled in from a Mix project it builds everything, but from Rebar3 it builds just the Erlang core. It's not quite done yet, I need some encouragement to allocate time to finish it...
You basically just need an OID and a blob of DER-encoded data. You can mint your own OIDs within the enterprise namespace if you have an OUI. Producing a DER version of some data structure may require defining some ASN.1 syntax and generating the encoder and decoder functions, along with a header file for the record. Or you can cheat by using the undocumented
asn1rt_nif
module, e.g. to wrap an arbitrary binary:
Thanks! Just being able to use a {OID, value}
was exactly what I was hoping for, I did not know about asn1rt_nif
:). If that really works out also using the public_key API then this would be sufficient for me. I only use it within my own SaaS system so there's no necessity for an official OUI.
I actually have a branch somewhere that rewrites much of the code to Erlang, with the Elixir code becoming a thin wrapper and adapter to Elixir data types (e.g.
DateTime
). When pulled in from a Mix project it builds everything, but from Rebar3 it builds just the Erlang core. It's not quite done yet, I need some encouragement to allocate time to finish it...
Sounds super cool and I think this would help the Erlang community a lot! I actually built my own little library for GRiSP as part of a larger PKI component, see https://github.com/GalaxyGorilla/grisp_cryptoauth. But that little library is not extensive for certificates at all, just tailored to our needs for GRiSP client certificates.
If that really works out also using the public_key API then this would be sufficient for me.
It should. Let's say you have a macro that defines the OID value as a tuple and you want to support a single binary value, you can just wrap that in an Extension record and use that alongside other extension in a Certificate or OTPCertificate record:
my_extension(Value) ->
%% ASN.1 universal tag value 4: Octet String
DER = asn1rt_nif:encode_ber_tlv({16, [{4, Value}]}),
#'Extension'{extnID = ?my_extension_oid, extnValue = DER}.
Encoding non-binary values, such as integers, is a bit harder as encode_ber_tlv
does not take care of the type-specific conversion.
my_extension(Value) -> %% ASN.1 universal tag value 4: Octet String DER = asn1rt_nif:encode_ber_tlv({16, [{4, Value}]}), #'Extension'{extnID = ?my_extension_oid, extnValue = DER}.
What does {16, [{4, Value}]}
actually represent? Which is the ASN.1 tag number?
Encoding non-binary values, such as integers, is a bit harder as
encode_ber_tlv
does not take care of the type-specific conversion.
That's exactly what I need for e.g. device serial numbers. I found the OTP-PUB-KEY
module helpful here, but it also doesn't provide support for the basic types (like Integer). But you can just use types which are directly derived from those like this:
3> 'OTP-PUB-KEY':encode('CertificateSerialNumber', 128).
{ok,<<2,2,0,128>>}
What does {16, [{4, Value}]} actually represent? Which is the ASN.1 tag number?
This is basically a Sequence (tag value 16) with a single element of type Octet String (tag value 4). I think the top-level type should always be a sequence, even if you only want to encode a single value.
Hmmm are you sure about the top level type being always a sequence? What I can find just always speaks about 'DER encoded'.
Hmmm are you sure about the top level type being always a sequence? What I can find just always speaks about 'DER encoded'.
I thought it was a convention among standard extensions at least, but I now noticed that SubjectKeyIdentifier is defined as a plain octet string, without a sequence. So feel free to drop the sequence :)
Haha, I also looked on the SubjectKeyIdentifier, that got me suspicious ;)
Such as
cRLDistributionPoints
,authorityInfoAccess
(AIA) andcertificatePolicies
...