2020/12/06

[js]Buffer.from()に'hex'を使えるが0xはいらない

いらないというか、付けたらいかん、という話だ。
JavaScriptとしたが、Node.jsだけの話かもしれん(違いがよくわからん)。

 

ハッシュ関数にBufferを引数に使うものがあった。

最初は文字列のハッシュを取っていたのだが、16進数のハッシュを取りたくなった。
あれこれ調べていたのだが、Buffer.from()の第2引数にencodingで'hex'とすればよさそうだ。
かんたんかんたん。

 

と思ったのだが、なんかハッシュ値がサンプルと違う結果になった。
Bufferがおかしい?

01: const value = '0x0000000000000000000000000000000000000000000000000000000000000000';
02: console.log(Buffer.from(value, 'hex'))

$ node buf.js
<Buffer >

あれ?

01: const value = '0000000000000000000000000000000000000000000000000000000000000000';
02: console.log(Buffer.from(value, 'hex'))

$ node buf.js
<Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>

 

あー、第1引数を"0x"で始めてしまうと16進数ではない文字列ということでエラーにもならず処理してしまうのね・・・。

 

いくつか試してみたが、こんな感じだ。

"123" → 12
"1234jk56" → 12 34
"1y34" → (無し)

雰囲気だけでいえば、こうだ。

  • 先頭から偶数文字数で16進数文字列(0-9, A-F, a-f)だけ処理する
  • 文字列の途中で16進数文字列以外が現れたら、それより前の文字列を有効とする
    • それによって奇数文字数になるなら切り捨てる
  • エラーは出さない

 

Node.jsにも、その辺りのルールは書いてなかったのだが、共通仕様なのだろうか。

Buffer | Node.js v15.3.0 Documentation
https://nodejs.org/api/buffer.html#buffer_static_method_buffer_from_string_encoding

慎重にやるなら第1引数が16進数文字列かつ偶数であることをチェックするのだろうけど、JavaScript界隈の人なら格好良く処理できるのかもしれん。

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の表には"-"と"_"の方も載っているから、心配しなくても大丈夫だろう。