Erlang で自己署名証明書を生成する

Erlang で ECDSA な証明書を生成したい場合、どうするのか。あまり情報がないので書いていきたい。

もともとは自社製品で利用する自己署名証明書を定期的に動的に生成したいというのが目的なので自己署名証明書以外については書かない。

まず、Erlang で証明書を生成できるのかどうかという話だが、できる。

crypto:generate_key/2 を活用することで可能。この関数は公開鍵と秘密鍵を生成してくれる。ただこれだけではもちろん証明書としてはいろいろ足りていない。

そこで登場するのが public_key:pkix_test_root_cert/2 だ。これを使うことでさくっと自己署名証明書を生成することができる。

> RootCert = public_key:pkix_test_root_cert("abc", [{digest, sha256}]).
#{cert =>
<<48,130,1,209,48,130,1,147,160,3,2,1,2,2,1,4,48,17,6,8,
42,134,72,206,61,4,3,2,...>>,
key =>
{'ECPrivateKey',1,
<<107,254,170,136,171,156,101,19,133,113,14,18,220,89>>,
{namedCurve,{1,3,132,0,6}},
<<4,207,1,117,221,108,167,37,136,172,32,120,125,202,
250,14,112,184,59,71,136,186,231,...>>}}

マップ形式で返ってくるので、cert だけとりだして、pkix_decode_cert/2 で見てみれば、無事自己署名な証明書が生成されてるのがわかると思う。

> Cert = maps:get(cert, RootCert).
<<48,130,1,209,48,130,1,147,160,3,2,1,2,2,1,4,48,17,6,8,
42,134,72,206,61,4,3,2,6,...>>
> public_key:pkix_decode_cert(Cert, otp).
{'OTPCertificate',
{'OTPTBSCertificate',v3,4,
{'SignatureAlgorithm',
{1,2,840,10045,4,3,2},
{namedCurve,{1,3,132,0,6}}},
{rdnSequence,
[[{'AttributeTypeAndValue',
{1,2,840,113549,1,9,1},
"root@example.org"}],
[{'AttributeTypeAndValue',
{2,5,4,3},
{printableString,"abc"}}],
[{'AttributeTypeAndValue',
{2,5,4,7},
{printableString,"Stockholm"}}],
[{'AttributeTypeAndValue',{2,5,4,6},"SE"}],
[{'AttributeTypeAndValue',
{2,5,4,10},
{printableString,"erlang"}}],
[{'AttributeTypeAndValue',
{2,5,4,11},
{printableString,"automated testing"}}]]},
{'Validity',
{generalTime,"20180914000000Z"},
{generalTime,"20180922000000Z"}},
{rdnSequence,
[[{'AttributeTypeAndValue',
{1,2,840,113549,1,9,1},
"root@example.org"}],
[{'AttributeTypeAndValue',
{2,5,4,3},
{printableString,"abc"}}],
[{'AttributeTypeAndValue',
{2,5,4,7},
{printableString,"Stockholm"}}],
[{'AttributeTypeAndValue',{2,5,4,6},"SE"}],
[{'AttributeTypeAndValue',
{2,5,4,10},
{printableString,"erlang"}}],
[{'AttributeTypeAndValue',
{2,5,4,11},
{printableString,"automated testing"}}]]},
{'OTPSubjectPublicKeyInfo',
{'PublicKeyAlgorithm',
{1,2,840,10045,2,1},
{namedCurve,{1,3,132,0,6}}},
{'ECPoint',
<<4,207,1,117,221,108,167,37,136,172,32,120,125,202,...>>}},
asn1_NOVALUE,asn1_NOVALUE,
[{'Extension',{2,5,29,15},false,[keyCertSign,cRLSign]},
{'Extension',
{2,5,29,19},
true,
{'BasicConstraints',true,asn1_NOVALUE}}]},
{'SignatureAlgorithm',
{1,2,840,10045,4,3,2},
{namedCurve,{1,3,132,0,6}}},
<<48,34,2,15,0,206,97,80,245,245,2,26,169,78,12,194,161,
32,242,2,15,0,217,27,231,...>>}

ただ、この証明書見てもらうとわかるが {2,5,29,15} つまり id-ce-keyUsage しか拡張がついていない。また、それ以外の情報も適当だ。もちろん、これはテストに利用するものなので、文句を言ってはいけない。

一応 Opts として指定はできるようになっているが、それでも足りないのでやはり自前で頑張っていくのがオススメになる。

そこで、これらをいろいろいじるためにどうするか。1から作るのははっきり行って大変だ。

Erlang/OTP のコードの中にある erl_make_certs.erl を参考にしていろいろいじると良い。

digest の方式、Extensions の追加方法などが思ったよりきっちり書かれている。このコードを参考にすることで自分求める自己署名証明書を生成できるようになるだろう。

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store