2020/11/15

[node]バイナリをHEX形式でconsole.logする

まだまだ初心者の域を出ない・・・というか、出るつもりがあまりなさそうなNode.js。
なんとなく書いて、なんとなく動いてしまうので、もういいんじゃないか、と思ってしまってね・・・。
それに、困ったらCやgolangで書きゃいいんじゃないの、と割り切ってしまっているのも原因だろう。
そもそも、必要がない限りNode.js使ってないし。

 

というわけで、今回はバイナリをHEX文字列でダンプしたいことについてだ。
Pythonのときもいろいろやったのだが、文字列ではないデータを扱うことが多いので、16進数を16進数のままコンソールに出力する手段がほしいのだ。


最初に出てきたのが、Bufferを使うやり方。

01: const data = "abc\x12\x34\x56def";
02: const dbuf = Buffer.from(data);
03: console.log(dbuf.toString("hex"));

$ node xx.js
616263123456646566

デバッグのためにBufferオブジェクトを作るのは嫌なのだが、デバッグと割り切ってしまえば良かろう。
デバッグ用の関数にしてしまうとかすれば心も痛むまい。

 

次に、文字列を1つ1つ16進数文字列に置き換える方式を考えたのだけど、こうなった。

01: const data = "abc\x12\x34\x56def";
02: for (let lp = 0; lp < data.length; lp++) {
03:     process.stdout.write(data.charCodeAt(lp).toString(16));
04: }
05: console.log();

$ node xx.js
616263123456646566

これのテストで「data.charCodeAt(lp)」をprocess.stdout.write()で出力させようとしていて、ずっとエラーになっていてね・・・。
consol.log()だと出力されるということに気付くのにかなり時間がかかった。
文字化けしたら考えよう、というやり方はよくないのだろう。

 

けど、「変なデータでも何でもいいから出力しやがれ」とは思ってしまうのだ。
それで動いてしまうと危険だから、ということなんだろうから、まあ文化の違いだろうね。

2020/11/04

[vbox]おそるべしネステッド

数日前、WSL2とVirtualBoxを両方動かすためにネステッドなんとかをオフにした。

これはオンに戻した後の設定だが、この2つ。

image

image

 

ネステッドVT-x/AMD-Vを無効にすると両方とも無効になる。

で、その状態でゲストOS(ホストはWindows10で、ゲストはLubuntu18.04)を起動したのだが、どうにも遅い。
動いている間は気にならないのだが、起動するまでがとても遅い。

ただ、いつも立ち上がるまで他のことをしているので、ネステッドは関係ないかもしれない。

 

というわけで、目視で計測した。

  • ネステッドを両方オフ:2分くらい
  • ネステッドを両方オン:40秒くらい

うん、ここまで違うとは思わんかったよ。

 

ネステッドを一度オフにすると、GUIからはオンにできないようだ。
コンソールからできる。
Windowsだとパスも通ってるし、管理者権限とかもいらん。

virtualization - Virtualbox enable nested vtx/amd-v greyed out - Stack Overflow
https://stackoverflow.com/questions/54251855/virtualbox-enable-nested-vtx-amd-v-greyed-out

2020/11/03

WSL2とVirtualBox 6.1.16(11月あたま)

前回、WSL2とVirtualBoxを試して失敗した。

hiro99ma blog: [wsl]何も考えずにWSL2にしたらVirtualBoxが起動しなくなった
https://hiro99ma.blogspot.com/2020/08/wslwsl2virtualbox.html

あれから2ヶ月ちょっと経ったが、どうなっただろうか?
失敗しても問題ない環境があったので、そこで試そう。

 

image

image

まず、「Windowsの機能の有効化または無効化」

  • Linux用Windowsサブシステム
  • Windowsハイパーバイザープラットフォーム

 

再起動して、まずWSL2をインストールする前にVirtualBoxのゲストOSを起動させる。
・・・エラーダイアログは表示されないが、起動の途中で止まったままになってしまった。

 

ネステッドページングをオフにしたら起動した。
前回もそうだったが、ネステッドVT-x/AMD-Vを有効化しないようになったおかげかもしれない。

そして、立ち上がりはするのだが、ゲストOSの動作が遅く感じる。
気のせいだろうか・・・。


元に戻す気がするので、ベンチマークを測っておこう。
そういえばLinuxでベンチマーク計測を行おうとするのは初めてだな。

CPUやメモリなどのシステム性能を比較するベンチマークツール | さくらのナレッジ
https://knowledge.sakura.ad.jp/1048/

こちらで、UnixBenchというものが紹介されていた。

https://github.com/kdlucas/byte-unixbench

cloneして、cdして、makeしたら"./Run"を走らせるだけで自動的にテストが開始される。

テストしたまま忘れて数時間放置していたが、最後は1218.8というスコアが出ていた。

 

次は、WindowsハイパーバイザープラットフォームだけをOFFにして、ゲストOSのネステッドVT-x/AMD-Vを有効化し、ネステッドページングも有効にした。

OFFにしても再起動を促されなかったが、ゲストOSを起動すると怒られた。
再起動すると起動できたので、まあよかろう。

今度のスコアは1278.4だった。
約60上がったのだが、これは有意な差なのだろうか?

正直なところ、このくらいだとよくわからんな・・・。

[node]base64urlのデコード

データで、base64urlでエンコードされている項目があった。

base64は、主にバイナリを文字列に置き換えたいときに使うものだ。
8bitの3バイトデータを、6bitの4バイトデータにする。同じ24bitだから。
6bitは64個なので、64個の文字列に当てはめる。A~Zとa~zで52個、0~9で10個。あと2個は”+”と”/”。

base64urlは、”+”と”/”を、”-“と”_”にしただけのものだ。
base64も最初からそうしておけば・・・と思わなくもないが、まあ時代的に仕方なかろう。

 

最初、base64urlというライブラリを使っていた。

https://www.npmjs.com/package/base64url

でも、なんか結果がおかしい(使い方が悪かっただけなのだが、このときはわからなかった)。

自信がないので、普通のbase64デコード方法で試そうとBufferを使うことにした。

https://nodejs.org/api/buffer.html#buffer_static_method_buffer_from_string_encoding

Buffer.from()にエンコードとして”base64”を指定すると、うまいことやってくれる。
固定文字列だったので、自分で”-“や”_”を置き換え、4文字ごとになっていなかったので”=”を追加。
そうすると、ちゃんと期待した値になった。

せっかくなので、base64urlの文字列でどういう例外が出るのかを確認しようとしたのだが・・・エラーにならない。
変な値になるわけでもなく、ちゃんとデコードできている。
あれ、そういうものなの??

仕様としてできるのか、偶然できただけなのか、APIの説明では分からんな。。。

 

ちなみに、base64urlライブラリでもちゃんとできた。

Buffer.from(base64url.decode(“base64url文字列”))

のようにやっていたのだが、

base64url.toBuffer(“base64url文字列”)

だけでよかった。

でも、

Buffer.from(“base64url文字列”, "base64")

だけで済むのなら、それに越したことはないな。

 

GitHubを検索したら、base64はURLやファイル名で安全な文字列もいけるようなことが書いてあった。

https://github.com/nodejs/node/pull/5243/files

creatingとかencodingしか書いてないけど、decodeもいけるよね・・・?

探しづらいのだが、Node.jsのページだとここら辺だ。

https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings

 

'base64': Base64 encoding. When creating a Buffer from a string, this encoding will also correctly accept "URL and Filename Safe Alphabet" as specified in RFC 4648, Section 5. Whitespace characters such as spaces, tabs, and new lines contained within the base64-encoded string are ignored.

ここのencodingは、エンコード・デコードの方じゃなくて、いわゆるエンコーディングだろう(そのまんまだが)。
それに、リンクが載っているRFC-4648 section5の表には"-"と"_"の方も載っているから、心配しなくても大丈夫だろう。

2020/11/01

JWT

JWTという形式のデータが現れた。
現れたといっても、仕事の中で言葉が出てきたというだけだが。

JWTのJはJSONのJ、ということがわかって満足していたのだが、どうもちゃんと調べないとダメらしい。
ちっ。


JSON Web Tokenの略で、JWT。

JSON Web Tokens - jwt.io
https://jwt.io/

RFC 7519にもなっているので、私が知らなかっただけで巷では有名なのかもしれん。
AbstractだけDeepLで翻訳しておこう。

JSON Web Token (JWT) は、2 つの当事者間で転送されるクレームを表現するためのコンパクトで URL 安全な手段です。JWTのクレームは、JSON Web Signature(JWS)構造体のペイロードとして、またはJSON Web Encryption(JWE)構造体の平文として使用されるJSONオブジェクトとしてエンコードされ、クレームがデジタル署名されるか、メッセージ認証コード(MAC)で保護されるか、および/または暗号化されることを可能にする。

クレームというと、お店に文句を付けるというネガティブなイメージになるのだが、”claim”という単語としては「主張、要求、権利、資格」のようなもので、苦情っぽい要素はない。
和製英語だったら別に構わないのだけど、日本語で使うときに意味が変わるというのは止めてほしいな・・・。

 

JSON-RPCのリクエストみたいな使い方をするのだろうか?
使い道は後で調べるとして、まずは文法というかフォーマットを知っておきたい。


RFCは長いのでまだ読みたくない・・・ので、導入のドキュメントを見ておく。
無料のEBOOKもあるようなのだが、メールアドレスだけじゃなくてCompanyとかの入力もあったので、面倒なのでやめた。

JSON Web Token Introduction - jwt.io
https://jwt.io/introduction/

Introductionでは署名するタイプのJWTに焦点を当てるそうだ。まあ、単にJSONをJWTのフォーマットにするだけだとありがたみがあまり無いのだろう。

JWTの使いどころは、AuthorizationとInformation Exchange。承認と情報交換。
他にもあるのだろうけど、まあよかろう。

 

そしてフォーマット。

<Header>.<Payload>.<Signature>と、3つの部分をドットで区切ってあるそうだ。

Header

Base64Urlでエンコードされる。
エンコードするのはJSONデータで、JSONのところは署名アルゴリズムとトークンのタイプを載せる想定のようだ。他にitemがあってもよいのだろうが、”alg”と”typ”はたぶん必須だ。

”typ”は”JWT”でよいとして、”alg”は何が使えるかというと、RFC-7518の3.1章にJWSの”alg”ヘッダパラメータの一覧があった。
サンプルは“HS256”となっているが、これはHMAC SHA-256のことのようだ。

https://www.rfc-editor.org/rfc/rfc7518.html#section-3.1

 

そういえばHMACのしくみをよく知らない。
いつも使う署名といえば、署名する人が秘密鍵を持っていて、データをSHA256のようなハッシュ関数でハッシュ値を求め、それに対して署名計算している。データ長を気にせず署名できる計算があるのかどうか知らないが、私が知っているタイプはデータ長が決まっているので事前にハッシュ計算してデータ長を整えるのだ。

 

HMACの場合は共通鍵のようだ。
じゃあ、JWTというかJWSというか、署名がついてHMACの場合には事前に鍵を決めるというシーケンスがいるのだろうか?
それはそれで面倒だ。

ただ、署名は無視することもできる。
送っている方が「俺だよ、おれおれ」っていう証明を付けてきて、確かに俺さんの秘密鍵を持っていないと作ることが難しいデータを付加しているだけなので、その人が受信した人が思っている俺さんかどうかわからないし、そのデータが正常かどうかなどというのはさらに関係が無い。

“HS256”だけはRequiredなので、これだけはどの環境でも使えないとRFC-7518を名乗ることができないはずだ。

 

Payload

ここにはclaimが入っている。claimには3タイプある。

  • Registered claims
  • Public claims
  • Private claims

PayloadもBase64Urlでエンコードされている。

 

 

Signature

HeaderとPayloadをまとめて署名する。
HMAC-SHA256の例が載っているのがわかりやすかろう。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

かなり省略した。。。すまぬ。
HMACのときにどうやって署名検証するかが気になって、残りがどうでも良くなってきたのだ。

JSON Web Token(JWT)の紹介とYahoo! JAPANにおけるJWTの活用 - Yahoo! JAPAN Tech Blog
https://techblog.yahoo.co.jp/advent-calendar-2017/jwt/

ここを読むと、”kid”というところで公開鍵を参照したりするそうだ。
しかし、HMACって共通鍵だから・・・?

 

まあ、今回は概要を知りたかっただけなので、これでよしとしよう。
あとは会社で詳しい人に聞くとするかね。