Symbol-Testnet@0.10.0.3でnode.key.pemの公開鍵を取得する

自前でないノードのやつです

委任ハーベストをするときに、どうやらノードの公開鍵が必要となっているみたいで。しかも、RESTの`/node/info`に出てくるものではなくて、`symbol-bootstrap`を走らせたときにできる`node.key.pem`に書かれているものが必要だそうです。

そんなのどうやって取得するんだって思ったので、方法を探してみました。

<hr />

SymbolのノードはTLSを使ってやりとりしているので、まぁそのときの鍵として使われているんだろうなと。

なので、戦略としては、ノードに直接TLS接続したら、証明書が送られてくるだろうから、その中にあるという方針でいきます。

ここにサンプルが書いてあるので、これをどうにかして取得を試みます
https://github.com/nemtech/symbol-docs/issues/532

例えば

`beacon-01.us-east-1.0.10.0.x.symboldev.network`

に接続して

`2a40f7895f56389be40c063b897e9e66e64705d55b19fc43c8ceb5f7f14abe59`

を取得できればOKと。

<hr />

Nodejs v14.4.0でやります。

結論としては、`serverSocket.enableTrace()`を使うことで欲しいものを見ることができました。
https://nodejs.org/docs/latest-v14.x/api/tls.html#tls_tlssocket_enabletrace

これにより、接続のハンドシェイクログが全部出てくるので、その中にある証明書に書いてありました。

以下のコードを実行します。

```javascript
const tls = require('tls');

const node = {
    port: 7900,
    host: "beacon-01.us-east-1.0.10.0.x.symboldev.network"
}

const contextOptions = {
    minVersion: 'TLSv1.3',
    sigalgs: 'ed25519'
};

const connectionOptions = {
    host: node.host,
    port: node.port,
    secureContext: tls.createSecureContext(contextOptions),
    // skip hostname checks since this is not a web-https case
    checkServerIdentity: () => undefined
};

const serverSocket = tls.connect(connectionOptions);

serverSocket.enableTrace();

new Promise((resolve, reject) => {
    serverSocket
        .on('error', err => {
            console.log('error');
            reject(err);
        })
        .once('close', () => {
            console.log('connection close');
            serverSocket.destroy();
        });
})
    .then(() => {
        serverSocket.end();
    })
    .catch((e) => {
        console.log(e);
    });
```

さて、画面に表示された情報のなかで、TLSの証明書を探します。

証明書は複数送られてくるのですが、最初の１つ目を見てみます。

（全体の結果は最後に置いてます。）

```
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            6b:7a:80:4a:d2:44:74:c2:44:41:2f:01:d4:b8:c1:08:26:ab:1a
        Signature Algorithm: ED25519
        Issuer: CN = peer-node-0-account
        Validity
            Not Before: Sep 20 21:38:52 2020 GMT
            Not After : Sep 30 21:38:52 2021 GMT
        Subject: CN = peer-node-0
        Subject Public Key Info:
            Public Key Algorithm: ED25519
                ED25519 Public-Key:
                pub:
                    2a:40:f7:89:5f:56:38:9b:e4:0c:06:3b:89:7e:9e:
                    66:e6:47:05:d5:5b:19:fc:43:c8:ce:b5:f7:f1:4a:
                    be:59
    Signature Algorithm: ED25519
         85:a3:d2:07:b7:c4:75:d7:ce:f9:3b:ee:6b:2b:97:e9:1b:bd:
         f7:9b:8e:de:08:c7:b6:8a:cf:55:26:01:e6:51:2c:f2:dd:5b:
         96:15:1d:53:d6:61:2b:01:48:e1:4d:86:70:64:68:f8:72:95:
         41:b7:e6:aa:1f:c6:55:46:35:0a
```

`beacon-01.us-east-1.0.10.0.x.symboldev.network`に接続してますので、欲しい値はこれです。`2a40f7895f56389be40c063b897e9e66e64705d55b19fc43c8ceb5f7f14abe59`

`Subject Public Key Info:`の`pub`のところにしっかりと載ってます。

あとはこれを好きなノードに使うことで、もしかしたら委任ハーベストできるかもしれません。

<hr />

以下は実行結果の全部です。

標準出力と標準エラー出力が混ざってます。
最後に、証明書のチェックでエラーになってます。自己署名証明書なので。
今回は目的が達成されているので、エラーになっても問題ありません。

```
Sent Record
Header:
  Version = TLS 1.0 (0x301)    
  Content Type = Handshake (22)
  Length = 184
    ClientHello, Length=180
      client_version=0x303 (TLS 1.2)
      Random:
        gmt_unix_time=0x7EC9C4EB
        random_bytes (len=28): 502219238755C9CF4E0DE0D626DB09E4E56DC10821DFA7B2543293DC
      session_id (len=32): BBDBC1DF57080F92CA99DF5134FF23787939F059B9F5048C841CA87B98E3EE5B
      cipher_suites (len=8)
        {0x13, 0x02} TLS_AES_256_GCM_SHA384
        {0x13, 0x03} TLS_CHACHA20_POLY1305_SHA256
        {0x13, 0x01} TLS_AES_128_GCM_SHA256
        {0x00, 0xFF} TLS_EMPTY_RENEGOTIATION_INFO_SCSV
      compression_methods (len=1)
        No Compression (0x00)
      extensions, length = 99
        extension_type=ec_point_formats(11), length=4
          uncompressed (0)
          ansiX962_compressed_prime (1)
          ansiX962_compressed_char2 (2)
        extension_type=supported_groups(10), length=12
          ecdh_x25519 (29)
          secp256r1 (P-256) (23)
          ecdh_x448 (30)
          secp521r1 (P-521) (25)
          secp384r1 (P-384) (24)
        extension_type=session_ticket(35), length=0
        extension_type=encrypt_then_mac(22), length=0
        extension_type=extended_master_secret(23), length=0
        extension_type=signature_algorithms(13), length=4
          ed25519 (0x0807)
        extension_type=supported_versions(43), length=3
          TLS 1.3 (772)
        extension_type=psk_key_exchange_modes(45), length=2
          psk_dhe_ke (1)
        extension_type=key_share(51), length=38
            NamedGroup: ecdh_x25519 (29)
            key_exchange:  (len=32): 80AA930BA1E04936B773AE2EC551653482235BAA442D3413B2C25DCE8B1FCB6A

Received Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = Handshake (22)
  Length = 122
    ServerHello, Length=118
      server_version=0x303 (TLS 1.2)
      Random:
        gmt_unix_time=0x79EBDD76
        random_bytes (len=28): BC3F924CF4A96C6AA7A442593D2A804299C59B2DD0D92A53A7CF2359
      session_id (len=32): BBDBC1DF57080F92CA99DF5134FF23787939F059B9F5048C841CA87B98E3EE5B
      cipher_suite {0x13, 0x02} TLS_AES_256_GCM_SHA384
      compression_method: No Compression (0x00)
      extensions, length = 46
        extension_type=supported_versions(43), length=2
            TLS 1.3 (772)
        extension_type=key_share(51), length=36
            NamedGroup: ecdh_x25519 (29)
            key_exchange:  (len=32): D286A63FB499B7C240A127AB5C458C173A5BE3F99A188378F713C1F755F7C440

Received Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ChangeCipherSpec (20)
  Length = 1
Received Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ApplicationData (23)
  Length = 23
  Inner Content Type = Handshake (22)
    EncryptedExtensions, Length=2
      No extensions

Received Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ApplicationData (23)
  Length = 66
  Inner Content Type = Handshake (22)
    CertificateRequest, Length=45
      request_context (len=0):
      extensions, length = 42
        extension_type=signature_algorithms(13), length=38
          ecdsa_secp256r1_sha256 (0x0403)
          ecdsa_secp384r1_sha384 (0x0503)
          ecdsa_secp521r1_sha512 (0x0603)
          ed25519 (0x0807)
          ed448 (0x0808)
          rsa_pss_pss_sha256 (0x0809)
          rsa_pss_pss_sha384 (0x080a)
          rsa_pss_pss_sha512 (0x080b)
          rsa_pss_rsae_sha256 (0x0804)
          rsa_pss_rsae_sha384 (0x0805)
          rsa_pss_rsae_sha512 (0x0806)
          rsa_pkcs1_sha256 (0x0401)
          rsa_pkcs1_sha384 (0x0501)
          rsa_pkcs1_sha512 (0x0601)
          ecdsa_sha224 (0x0303)
          ecdsa_sha1 (0x0203)
          rsa_pkcs1_sha224 (0x0301)
          rsa_pkcs1_sha1 (0x0201)

Received Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ApplicationData (23)
  Length = 524
  Inner Content Type = Handshake (22)
    Certificate, Length=503
      context (len=0):
      certificate_list, length=499
        ASN.1Cert, length=240
------details-----
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            6b:7a:80:4a:d2:44:74:c2:44:41:2f:01:d4:b8:c1:08:26:ab:1a
        Signature Algorithm: ED25519
        Issuer: CN = peer-node-0-account
        Validity
            Not Before: Sep 20 21:38:52 2020 GMT
            Not After : Sep 30 21:38:52 2021 GMT
        Subject: CN = peer-node-0
        Subject Public Key Info:
            Public Key Algorithm: ED25519
                ED25519 Public-Key:
                pub:
                    2a:40:f7:89:5f:56:38:9b:e4:0c:06:3b:89:7e:9e:
                    66:e6:47:05:d5:5b:19:fc:43:c8:ce:b5:f7:f1:4a:
                    be:59
    Signature Algorithm: ED25519
         85:a3:d2:07:b7:c4:75:d7:ce:f9:3b:ee:6b:2b:97:e9:1b:bd:
         f7:9b:8e:de:08:c7:b6:8a:cf:55:26:01:e6:51:2c:f2:dd:5b:
         96:15:1d:53:d6:61:2b:01:48:e1:4d:86:70:64:68:f8:72:95:
         41:b7:e6:aa:1f:c6:55:46:35:0a
-----BEGIN CERTIFICATE-----
MIHtMIGgAhNreoBK0kR0wkRBLwHUuMEIJqsaMAUGAytlcDAeMRwwGgYDVQQDDBNw
ZWVyLW5vZGUtMC1hY2NvdW50MB4XDTIwMDkyMDIxMzg1MloXDTIxMDkzMDIxMzg1
MlowFjEUMBIGA1UEAwwLcGVlci1ub2RlLTAwKjAFBgMrZXADIQAqQPeJX1Y4m+QM
BjuJfp5m5kcF1VsZ/EPIzrX38Uq+WTAFBgMrZXADQQCFo9IHt8R11875O+5rK5fp
G733m47eCMe2is9VJgHmUSzy3VuWFR1T1mErAUjhTYZwZGj4cpVBt+aqH8ZVRjUK
-----END CERTIFICATE-----
------------------
        No extensions
        ASN.1Cert, length=249
------details-----
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            11:d7:f6:11:96:04:21:c2:55:21:37:eb:ae:c7:92:3e:0f:6a:a5:53
        Signature Algorithm: ED25519
        Issuer: CN = peer-node-0-account
        Validity
            Not Before: Sep 20 21:38:52 2020 GMT
            Not After : Sep 15 21:38:52 2040 GMT
        Subject: CN = peer-node-0-account
        Subject Public Key Info:
            Public Key Algorithm: ED25519
                ED25519 Public-Key:
                pub:
                    f8:d2:c5:69:c6:d3:0f:66:5f:e5:04:ee:8b:26:fa:
                    90:6a:29:e2:d6:e1:55:5d:20:78:a9:e0:1b:43:90:
                    08:c0
    Signature Algorithm: ED25519
         d1:d3:2e:27:ea:96:c7:7b:bf:03:24:5d:da:e6:7e:f9:71:3f:
         5e:83:3d:b5:1d:03:88:0a:ba:f9:ef:79:35:95:d8:29:8e:2e:
         32:1f:18:b5:de:6c:fd:b2:b8:a2:46:76:c6:6c:b7:e8:77:e2:
         53:42:99:c5:54:33:9a:49:f5:02
-----BEGIN CERTIFICATE-----
MIH2MIGpAhQR1/YRlgQhwlUhN+uux5I+D2qlUzAFBgMrZXAwHjEcMBoGA1UEAwwT
cGVlci1ub2RlLTAtYWNjb3VudDAeFw0yMDA5MjAyMTM4NTJaFw00MDA5MTUyMTM4
NTJaMB4xHDAaBgNVBAMME3BlZXItbm9kZS0wLWFjY291bnQwKjAFBgMrZXADIQD4
0sVpxtMPZl/lBO6LJvqQaini1uFVXSB4qeAbQ5AIwDAFBgMrZXADQQDR0y4n6pbH
e78DJF3a5n75cT9egz21HQOICrr573k1ldgpji4yHxi13mz9sriiRnbGbLfod+JT
QpnFVDOaSfUC
-----END CERTIFICATE-----
------------------
        No extensions

Received Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ApplicationData (23)
  Length = 89
  Inner Content Type = Handshake (22)
    CertificateVerify, Length=68
      Signature Algorithm: ed25519 (0x0807)
      Signature (len=64): 6E3E70C09469692F4F5C54BB3269E004E4C02DC96E90BB3C948E173B5D24E51B4240BDD2422B0A521DBF6FFDBA9ED2904ABAF499F741E05B1B321386C4562908

Received Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ApplicationData (23)
  Length = 69
  Inner Content Type = Handshake (22)
    Finished, Length=48
      verify_data (len=48): A23FEE7BE67C9878D7906069203C7047D5903B82651FF24E40D241C931CEAC2F0014DCEDAADC2DC7707E402ADC8CE35E

Sent Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ChangeCipherSpec (20)
  Length = 1
    change_cipher_spec (1)

Sent Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ApplicationData (23)
  Length = 25
  Inner Content Type = Handshake (22)
    Certificate, Length=4
      context (len=0):
      certificate_list, length=0

Sent Record
Header:
  Version = TLS 1.2 (0x303)
  Content Type = ApplicationData (23)
  Length = 69
  Inner Content Type = Handshake (22)
    Finished, Length=48
      verify_data (len=48): 08AC1910F06C4579E2B87ED2D4FF5D1CAC8390E05E8F5F076D456CE8BA18E63974842600BDBFF47D1AF3AF521C2A9B79

error
Error: self signed certificate in certificate chain
    at TLSSocket.onConnectSecure (_tls_wrap.js:1496:34)
    at TLSSocket.emit (events.js:315:20)
    at TLSSocket._finishInit (_tls_wrap.js:931:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:705:12) {
  code: 'SELF_SIGNED_CERT_IN_CHAIN'
}
connection close
```