ラベル tech の投稿を表示しています。 すべての投稿を表示
ラベル tech の投稿を表示しています。 すべての投稿を表示

2026年10月11日

SHA-256はわけわからん

しばしばハッシュ計算で SHA-256 を使う。
にも関わらずまったく何をやっているか知らないものどうかと思い、ちょっと調べた。

 

まずは原本っぽいものを探そうとしたが、どれかわからない。
NISTで定義してあるなら間違いはなかろう。

SHA-256 のことだけ書いてあるかと思ったが、SHA-2系というべきか SHA-384やSHA-512なども同じような計算になるためかまとめて書かれていた。 

和訳するのも面倒なので・・・やったことがある人のサイトを見た。

書かれているページ数はPDFでのページ数ではなくドキュメントのほうね。

 

自分で実装するのは、やめた。
ハッシュ計算の説明では、計算量はそこまで大したことがなさそうなニュアンスをかもし出していたような気がするので、実装するのも難しくないのだと考えていた。
いや、まあビットシフトとかAND/OR/XORとかそういうのばっかりという意味では難しくないしCPUが得意な計算ばかりかもしれん。

が、なんというか、なんなんだこの計算は??という気持ちになった。実装を知ったらSHA-256のことが多少わかるんじゃないかと思った自分が非常に甘かったのだ。これだけやれば元の数値とは似ても似つかぬ値が出てくるだろうというのはなんとなくわかる。しかしこういう計算で値の重複がここまで発生しない状況が生まれるのかがさっぱりわからん。

 

ハッシュ計算を破る、というのは意図したハッシュ値を生み出す方法を見つける、ということだったと思う。SHA-1系はもうダメだ。AI でハッキングしまくっている状況でもまだ SHA-2は保たれているので、そういう系統ではないと信じたいものだが、信じるだけではなんにもならん。が、ここまでわけがわからん計算だと思ってなかったので信じたいという気持ちだ。

 

2026年7月1日

ローカルでLM Studioを使う (9)

Googleの無料版はもう使えなくなったかと思っていたが、vscodeのExtensionが無料で使えなさそうというだけだった(調べてない)。

Google AI Studio で API Keyを取得すれば Continue から使用できた。YAMLファイルを直接いじらずとも、+ボタンでモデルを追加できる。Gemini 2.5 Flashは使えそうだ。Gemini 3 Flashはダメだった。 

 

name: LM Studio
version: 1.0.0
schema: v1
models:
  - name: Autodetect
    provider: lmstudio
    model: AUTODETECT
    apiBase: http://localhost:1234/v1/
  - name: Gemini 2.5 Flash
    provider: gemini
    model: gemini-2.5-flash
    apiKey: ............
    contextLength: 2097152
mcpServers:
  - name: DeepWiki
    type: streamable-http
    url: https://mcp.deepwiki.com/mcp

 

LM Studioに追加して選んでもらったほうが良いのかもしれんが、間は少ないほうが良かろう。できるかどうかも調べていない。

 

 

2026年5月3日

ローカルでLM Studioを使う (8)

LM Studioのチャット履歴を消したいときは、エクスプローラでJSONファイルを削除すると良いようだ。


さて、LM Studioをインストールしたものの使う機会がない。
気分を変えて、なんとなく手動でやっていたものを置き換えてみようと思った。

今回は、最近起こったニュースの概要だけ知りたい、だ。
文字にするとなんか堕落したような印象を受けてしまうが、違うのだ。何でもかんでもはできないので、ちょっとだけアンテナを張っておこうかなというくらいのニュースを見逃さないようにしたいだけなのだ。

Gemini協力の下、DuckDuckGoで検索した記事をLM Studioで概要まとめするという順で処理するようにした。 

https://github.com/hirokuma/lmstudio-ddgs-news

DDGSライブラリはDuckDuckGoが出しているわけではないのであまりバシバシ使うと迷惑がかかるかもしれない。


DuckDuckGoで広く検索してLM Studioでその中から選別するようになっているが、ニュース取得の期間を制限しているのでLM Studioは期限についてはしなくてよいのかも? でも、ニュースは続報として展開している可能性もあるので、発生した期間をちゃんと絞りたいならこれが良いのか。

env で SEARCH と QUERY を設定しているが、ニュース検索では両方使っている。LM Studioへのプロンプトには SEARCH だけ使っている。イメージとしては、SEARCH は一言、QUERY はスペース区切りでキーワードという感じだ。ああ KEYWORD にすればよかった。 


2026年2月28日

なんとなくLM Studioをインストールしてみる

ローカルで動かすAIってセキュリティに敏感な人がやるのかなあ、くらいに思っていたのだが、お試しでAI の API を使ったアプリを作ってもらって実際に動かしてみてわかった。たぶん、API を使いたくても無料版ではすぐに無料枠を使い切ってほとんどなにもできないし、有料版だとお試しで動かすにしてもお金がかかりすぎるからじゃないだろうか。

違うかもしれないけど、ローカルで動かすことができる LM Studio を試してみる。


LM-Studio-0.4.6-1-x64.exe をダウンロードしてインストール。空き容量は2GB くらいいるのだと。ちなみにうちには専用 GPU が載っている PC はない。
それでも何か推奨してきたのでそのまま使ってみよう。3.4GB くらいいるそうだ。

 

そのままはいはいと進めるとウィンドウが開いた。左下になにか表示されている。
リモートのインスタンスと接続というのは、あれか、家の外でも Bitcoin フルノードは自分が立てたのを参照したいというあれと同じようなものか。多分違うな。。。

 

たぶんダウンロードが終わるまでは何もできないだろうと放置。
終わったら Load するかどうか聞いていたのでそうする。 

 

さて、何を打ち込んだものだか・・・。
今まで自分で調べたことがなさそうなことが良かろうと適当に打ち込んだ。チャットのタイトルが「Long野市」・・・。インターフェースを英語のままにしているからだろうか? ちなみに私は長野市には行ったことがないと思う。

 昨年のことなので、適当に検索して調べてくれたらうれしいと思ったがそういうことはなかった。 

 

さて、いったいLM Studioは何ができるんだろうかとGemini氏に聞いてみた。
「私のような」ではなく「ChatGPTのような」と回答するのが控えめだ。 

 

質問していったが、LM Studioさん(あるいはそのモデルさん)が自己強化されたり学習されたりということはなく、モデルはもうダウンロードしたものがすべてで、あとは RAG というしくみでデータを読み込ませたり?ができるくらいだそうだ。LM Studioさんに聞いても同じような回答だった。こちらは RAG ではなく拡張機能という言葉を使っていたが、たぶん似たようなもんじゃないかな。

  • 使用しているLLMに大きく依存し、それを超えることはない
  • ユーザーがプロンプトに打ち込む内容が判断材料のすべてだが、同じチャット内ではその内容も考慮される
  • 拡張機能やRAGはプロンプトを補助するようなもので、ダウンロードしたLLMが学習したり強化されたりはしない 

この辺の工夫次第なところが、やりこみ感があるというか、熱心になるところなんだろう。


ちなみにインストールしたノートPC(ThinkPad T14s)はこんなスペックだ。GPUって専用GPUを指しているのかと思ったけどオンチップのも数に入れるんだね。

 

RAG

長野市の気温データを LLM が持っていないから答えられなかった。気象庁のホームページから各地域の気象データをダウンロードできるようになっていたので、長野市のここ5年くらいの気温情報をCSVファイルでダウンロード(2.7KB)し、それを与えた。

英語になったが 2025年は7月が一番高かったのでこれであってる。まあ30秒もかかっているから自分でやったほうが早いといえば早いのだが、そういうことではないのだ。

 

添付したデータが小さければそのまま読み込み、大きければ RAGとして扱うんだとか。

Chat with Documents | LM Studio Docs

アップロードできるファイルサイズは 1MBくらいとチャットの回答で返ってきた。が「ユーザーの間で」っていうのは google/gemma-3-4b が作られた時点の情報ってことだからさすがに違うのかな。

> LM Studio のチャット欄にファイルを添付できるサイズの上限については、公式な情報が公開されているわけではありません。しかし、ユーザーの間で共有されている情報や経験則から、おおよその目安を以下のように挙げることができます。 


WSL2からアクセスできない

せっかくなのでAPIをたたくくらいはやっておこうかと、Windows上でLM Studioを起動し、サーバーをRunningにしてWSLからアクセス・・・失敗。
Windowsのコマンドプロンプトから curl すると成功。

IPアドレスが 172.29.128.1 になってて、これは HyperV の vEthernet? 
設定も LANからアクセスするかどうかしかなくて、こんなアドレスじゃうちの LANからもアクセスできないよ!!

こちらを見てみたが、既に 0.0.0.0 だった。ならば Windows に割り当てている IP アドレスにしてしまえ、とやってみると反映はされた。されたのだが、よく考えると Nat モードなのでホスト側から WSL2 にアクセスできるが逆はできないのか・・・?

Mirrored にするとあっさりアクセスできた。

$ curl http://localhost:1234/v1/models
{
  "data": [
    {
      "id": "google/gemma-3-4b",
      "object": "model",
      "owned_by": "organization_owner"
    },
    {
      "id": "text-embedding-nomic-embed-text-v1.5",
      "object": "model",
      "owned_by": "organization_owner"
    }
  ],
  "object": "list"
}



サンプルにあったこれだけのコードの実行に 1m21.066s もかかるのだ。漠然としすぎた質問のせいかもしれんが、まあスペックに依存するということだ。

import lmstudio as lms

with lms.Client() as client:
    model = client.llm.model() 
    result = model.respond("特定のトピックについて詳しくなるための、おすすめの学習順序を教えて。")
    print(result.content)


おまけ

デスクトップPCのほうが性能が良かろうと思ったのだが、全然そんなことはなかった。

 

ただ、チャットに入力してから出力されるまではデスクトップPCの方が早かった。これは他のアプリについてもそうだから、ThinkPad T14sの方が単純にスペックが低いのかなあ。困ってはいないのだけど 、気になる。

最初に打ち込んだ「長野市の平均気温」もすぐに回答された。文言もほぼ同じだったのだが、こちらは 2023年の平均気温というデータを出してきた。・・・少なくとも気象庁のデータとは一致しなかった。載せていたURLも404だった。

CSVデータありならちゃんと回答するかと思ったが、これは平均気温のデータで最高気温のデータじゃない、とか言われてしまった。。。「平均気温が一番高い月」って言ってるのに。新しくチャットを開いてやってみたが、今度は各月のデータを列挙するまでは良かったものの何故か合計して年間平均気温を求めたあと、なぜか「それゆえ6月」と答えてきた。

やっぱりVRAMが512MB程度ではまともに動かないということだろうか。
むずかしいね。 

うちのZero TrustはWSL2のGitHubへのsshを通してくれない

前回、CloudflareのZero Trustについてちょっとだけ書いた。
今のうちの環境では、Zero Trustを有効にしたCloudflare WARPをオンにするとGitHubと接続できなくなる。ブラウザで見たりはできるのだが、とりあえず git pull は通らない。通らないと言うか鍵のパスフレーズ入力にもたどり着かない。
ちなみに、Cloudflare WARP アプリの名前は Cloudflare One Client という名前にリブランディングされるようだ。

 

そんなもんかと思っていたがこれは WSL2 環境で行った場合で、Windowsの方で git pull すると成功した。WSL2 のすべての通信がダメなわけではなく apt get などは問題なさそうだ。よくある ssh -T git@github.com が進まない。ローカル環境の Raspberry Pi に SSH するのは問題ない。ping github.com なども通るので DNS は問題ないのだと思う。

ssh -Tv git@github.com で詳細を見てみる。

...略...
debug1: Local version string SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.14
debug1: Remote protocol version 2.0, remote software version b15cbbe
debug1: compat_banner: no match: b15cbbe
debug1: Authenticating to github.com:22 as 'git'
debug1: load_hostkeys: fopen /home/xxx/.ssh/known_hosts2: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: sntrup761x25519-sha512@openssh.com
debug1: kex: host key algorithm: ssh-ed25519
debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY

ここで止まっている。 
鍵交換の応答を期待しているが返ってきていない?
-o KexAlgorithms=ecdh-sha2-nistp521 をつけるとうまくいったという人がいたのでまねしたが変わらず。
ログに出てくる sntrup761x25519-sha512 というのが暗号量子対策として変更された方式なのかな。

Post-quantum security for SSH access on GitHub - The GitHub Blog

$ ssh -v git@github.com exit 2>&1 | grep 'kex: algorithm:'
debug1: kex: algorithm: sntrup761x25519-sha512@openssh.com
^C 

そういうのはともかく、Zero Trust なのか Cloudflare WARP なのかわからないが、それを有効にすると NGになるし影響があるのは WSL2 での ssh だけというのが気になる。 

 

何もしてないのに。。。

あとは Windows で設定しているファイアウォールが影響しているとか?と思ってゆるい設定にすると通ってしまった!
そして設定を戻したのに通ってしまった!

な、何もしてないのに。。。

 

しかしその後もあまり調子よくない

その後はあまり気にせず使っていたのだが、PCの再起動をしてからまた調子が良くない気がする。SSH などは問題ないのだが winget のサイトと接続できない。Chrome もなんか時間かかったし DNS関係でなんかあるのかねぇ。


2026/02/24追記

よくわからないのだが、メーラーのThunderbirdに設定している Yahooメールのアカウントだけアクセスに失敗する。Gmailや他のアカウントもあるのだが失敗するのはYahooだけだ。「ログイン情報を送信しています...」のあとに失敗したダイアログが出てくる。ファイアウォールでこけているわけでもなさそうだし、パスワードの渡し方の設定を変更すると「対応してない」と出ているので通信自体はしているようだ。海外からのアクセスを許可しないようにしていたので無効にしたのだが関係ない。まあ、もう1台で動かしている Thunderbird の方は問題なく動いているから PC 側の設定だ。

ああ、いまわかった。

Windowsの IPv4 DNSサーバを 1.1.1.1 にしていたのだが、これを宅内のルータに設定すると動くようになった。
Cloudflare WARPをオンにするとダメになるから、DNS周りのなにかなんだろうなぁ。 

 

2026/02/28追記

Windows Firewall Control では WSL上でファイアウォールによるブロックが起きたときに通知が来ない。来たことはあるのかもしれないが記憶にないくらいには通知が出ない。ブロックしたログにも出てこないようだ。

SSHを使うのはほぼ WSL2からだったのだが、最近ブロックされていたのは 22番ポートを開けていなかったからのように思う。だったら「何もしてないのに直った」はおかしいのだが、Windowsファイアウォールの設定をリセットしてやり直している今はそんな状況だ。

Windows Firewall Control の推奨プロファイルは「レベル - 中」なのだが、これは送信を遮断側に倒す。「レベル - 低」がおそらく Windows の標準レベルでこちらは許可側にするようだ。なのでレベル中にしておくと送信失敗になってしまう。 

これで通知が出てくれれば気付くのだが、WSL2 は出てこないし他のアプリでもときどき出てこない。Windows Firewall Control のログにも出てこない。Windows ファイアウォールのログであれば出てきそうなのだが設定の変更ができない。設定を変更しなくても OK できない。注意事項に書いてある件が影響しているのだろうけど、Home版だと標準でグループポリシーオブジェクトを変更するツールは付属していないのでどれかのセキュリティツールが変更しているのだろうか。

 


ログは諦めて WSL2 側、正確には HyperV 側のファイアウォール設定に SSH などの送信許可を与えるようにした。

WSL2のファイアウォール設定 | hiro99ma blog

 

2026年2月23日

管理されたChrome

Google Workspaceのアカウントでログインしている Chrome だとこのような感じで組織によって管理されていることがわかる。

それはよいのだが、個人GoogleアカウントのChromeも管理されていることになっている。

 

よく見ると、どちらもブラウザは組織によって管理されているが、プロフィールが管理されているのは Google Workspace アカウントの方だ。

 

なぜ急に気にしだしたのかというと、前回 Cloudflare WARP(Cloudflare One Client) であれこれやっているときに DNSをどうしているのかがわからなくなったからだ。WARP(or Zero Trust)を有効にすると DNSはおそらく Cloudflare を見に行っている。Windowsの設定画面でも手動で設定していたDNSの方は見に行っていないというような記述に変わったからだ。

それはそれとしてブラウザはどうなっているのか Firefoxを見ると自前で設定を持っていた。では Chrome はというと「この設定は管理対象のブラウザでは無効です」とのことだ。 

組織ってどこよ??というのはわからんが、解除の方法は載っていた。
レジストリ削除がいるらしい。あ、これ Enterprise and Education だから私の環境とは一致しないな。やってみたが、いくつか削除できなかった。
これってレジストリとChromeのアカウントは関係なさそうだからアプリごと管理されることになるんだろうか。


SpywareBlasterで設定した項目が policy の画面に出てきてので、外部から設定されると「組織での管理」と思われてしまうのだろうか。あるいはCloudflare WARPのインストール?
わからん。。。


2026年2月21日

Cloudflare WARP

仕事の打ち合わせで、家のWiFi以外の環境でPCを使うかもしれない、ということがあった。よくセキュリティの話で「自分は大丈夫、と思う人ほど危ない」ということを聞くが、ではそう思わない人はどこまでやればいいのだ?と思ってしまう。今回だと、オープンなWiFi環境を使うのに何を心配したらいいのだろうかがよくわからない。

こそっとUSBに挿されるなどの心配を除けば無線で何かされるのを警戒すればよいはずだし、Bluetoothを受け付けないようにしておけばWiFiだけ気にすればよいはずだ。
ファイアウォールでアプリごとの接続はある程度管理しているつもりだが、 接続先が本当にそうなのかなどは家のルーターにお任せしているので外の世界だよくわからない。

そういうときはよく聞くVPNかなあと思うのだが、今回のためだけにお金払うのも何だし、かといって無料VPNが信用できるとも言えないし。

いろいろ考えたが、VPNはあきらめてVPNっぽいものを導入することにした。 

説明を見ても書いていないように、VPN、とは言っていない。
私の解釈では、通信先の直近がCloudflareになり、Cloudflareがチェックしてから接続先につながる、だ。
そこまでしなくても、DNSを 1.1.1.1 にするだけでよいのかもしれない。Google が 8.8.8.8 なので似たようなアドレスをみんな使っているのかもしれない。

悩ましい選択 

Cloudflareがよいか、Googleがよいか、自分のISPがよいか、あるいは他のDNSか、みたいな選択になるのかね。 どこかを使うことにはなるので選択するしか無い。
自己責任と言うか、選択の自由と言うか、ともかく悩ましいところだ。

 

Zero Trust

Cloudflare WARPの設定というか接続というか、Zero Trustというものがある。
これはどちらかというと会社のような複数端末で個別の設定ではなく共通の設定を使いたいときのサービスだと思う。 
Zero Trust自体はプライベートなネットワークにアクセスするときには必ず検証するというルールを敷くもので、Gatewayという機能がファイアウォールのような役割を果たすようだ。Email Security という機能だったり、他にもいくつか使える機能をまとめて Cloudflare One という名前になっているようだ。

 

これを有効にすると、Zero Trustサイトで設定しないと通信できなくなる。ブラウザは使えているから http や https はいけるのかな? Windows Update も通りそうだが winget はダメかも。GitHub に push したり Thunderbird でのメールチェックもダメだし、実は全然使いこなせていない。

ま、まあ家の外で使うならそのくらいの方が安全かもね。 

 

信用ではなく利用なんだ 

Cloudflareのアカウントがないと使用できないが、アカウントは個人で使用する分には無料でも作ることができる。商用とか非商用とかではなく小規模というところか。
私は、お名前.comでドメインを取ったが面倒になってきたのでCloudflareに移管した際にアカウントを作った。ついでに個人事業主のホームページも Cloudflare Pagesでつくったし、なんかもうズブズブになってしまった。

まあでも、そこは信用したのではなく利用しているだけという意識は強く持っておきたい。それこそ Zero Trust というか、Trustminimization というか。

 

おまけ

ドメイン管理をしているからか Pages を使っているからか、AIからのクローリングを許す・許さない設定がある。うちみたいなところでもクローリングされるのね。。。
なんとなく全部ブロックするようにした。 

 

 

2025年10月4日

"sample"か"example"か

自分の GitHub リポジトリを見ていた。
"sample" と "example" が混ざっていて落ち着かない。

【sample】見本、標本
【example】例、実例、手本

 「標本」という意味だと違ってくるが、見本とか手本とかだとどっちでもよくなってくる。

"sample code" で "code example" というのが多いかな?
でも Google で "Code samples" はあった。"example code" はそんなになさそう。

今度からは "example" 系の名前にしましょうかね。

2020年3月29日

うまく抽象化できてない

いまgolangで書こうとしているRC-S370のアプリというか何というかだが、どうにも抽象化がうまいことできていない。

全然golangとは関係なく、前からできていないと思っているものがまたやってきただけだ。

 

今日までのところ
https://github.com/hirokuma/go_pasori370/tree/e8289f371d29810a9c371eaa91232882f12d2a03

 

mainはどうでもいいとして、それ以外はdevとpcdに分けている。
devでRC-S370のコマンドを書いて、pcdではそれを組み合わせて呼び出すだけにしようかと考えている。

 

が、pcdは意味があるのだろうか。
RC-S370のコマンドを個別に書いたとして、それを呼び出す順番もまたRC-S370に依存していることがほとんどだ。
だとすると、pcdはもっと抽象化してタグを読み書きするインターフェースだけにして、どう呼び出すのかはdevに任せてしまった方がよいのではないか。

それだったら、devでインターフェースを切って、dev/rcs370、みたいな構成にしてしまえばいいんじゃないか。
pcdのように間に入る人がいらなくなる。

 

でもなぁ・・・タグの読み書きといっても、NFC-A, B, Fのような形だとそこは抽象化できないのだよな。
NDEFでやればいいのだろうけど、そこまで気力が湧かない。
偉大だな、NDEF。

 

というわけで、方向性が自分の中ですらモヤモヤしているというところであった。

2020年3月22日

受信とデコード

前回の続きではあるが、golangと関係ない話だ。

 

RC-S956は、PasoriのRC-S370に搭載されているチップで、RC-S620/Sも同じチップが載っている。
RC-S370とRC-S620/Sの違いは、インターフェースがUSBなのかUARTなのかだ(他にもあるが、使うだけならそれでいいだろう)。

 

RC-S956はNFC R/Wとして動作するチップだ。
詳しいことは知らんのだが、

  1. インターフェースを通してコマンドをユーザが送信
  2. コマンドのフォーマットが正しければチップがACKを送信
  3. レスポンスがあればチップがレスポンスデータを送信

ということになっている。

ただ、ACKやレスポンスを送信するといっても、受信してほしいデータがありますよフラグがあるわけでもなく、そういう取り決めになっているだけだ。
ACKを返すのも設定次第だし(今回は必ずある)、レスポンスデータも固定長では無いので、なんか嫌な感じだ。


では、どう実装するのがよいだろうか。

まず、受信サイズはInEndpointのパケットサイズの逓倍にするのがよかろう。
gousbのサンプルも10パケット分ということで10倍した領域を用意していたし。

幸いなことに、RC-S956からの1回分のレスポンスはサイズの上限が決まっている。
そして、コマンドに対してレスポンスを返すだけで、勝手にレスポンスだけを返すことはなかったはず。
Target系のメッセージがちょっと自信ないのだが、今回は忘れよう。
1コマンド送信に対して、ACK受信(6byte)とレスポンス受信(最大256byte=4パケット)。

ACKは、いい。
受信して最初のデータなので、受信データの先頭6byteをチェックすれば良い。

問題はレスポンスだ。
ACKと別USBパケットになると思うのだけど、100%の確信があるわけではない。
設定でACKを返さないようにできた気はするのだが、その設定をするまではACKが返ってくるので、あまりそこでがんばりたくない。


となると・・・USBの1パケット中にACKとレスポンスが混ざっていたとしてもデコードできるようにするし、ACKとレスポンスが別パケットになったとしても受信をそれぞれ行うようにする、というやり方しかないか。

文字にすると「当たり前やん」と言われそうなのだけど、そういうのが苦手なのだ。

 

コマンド送信後、まずUSB5パケット以上の受信を行う。
先頭の6byteをACKと比較する。
それ以上のデータがまだあればレスポンスとして比較し、残っていなければUSB4パケット以上を受信する。

おそらく、レスポンスが複数パケットになったとしても、1回の受信で全部取得できるだろう。
ACKと連続したパケットであろうとなかろうと、最初のパケットを読めばレスポンス長はわかるので、足りているかどうかはチェックできるのだけど・・・大丈夫じゃないの、と思ってしまうのよね・・・それがダメなのか・・・。

2018年5月6日

git merge --squashによるコミットまとめ

先日、こういう記事を書いた。

クラウド上のVMとのファイル同期はどうやるのがよいのだろう?
http://hiro99ma.blogspot.com/2018/05/vm.html


あれこれ考えたが、私にとってはgitを使った方が無難だという判断に至った。
性格的に、突然大きな変更なんかをやらかしてしまいがち(そして動かなくなる)なので、こまめにgit commitしていく方が安心なのだ。


が、コミットログが乱れるのはよろしくない。
今までは気にもしなかったのだが、そういうお年頃になったのだと思おう。


お仕事用のプロジェクトで、ほぼ自分しかリポジトリを触っていなかったので、直接commit・直接pull request・直接merge、と、やっていたのだ(githubを使っている)。
それを、forkしてからpull requestするタイプにすればよさそうだった。

参考にしたのは、こちら。

慣れてきたらコミットをまとめてPull Requestしよう(git merge --squash) | 株式会社グランフェアズ
https://www.granfairs.com/blog/cto/git-merge-squash


たぶんだが、forkせずに同じリポジトリで作業していたら、それはそれでログが汚れてしまいそうな気がしたのだ。
だ、だよね??

まあ、そうじゃなくてもよいのだ。
プロジェクト用のリポジトリだから、自分は自分のリポジトリで作業して、結果だけを残せば良いのである。


やり方は、リンク先を見た方がわかりやすい。


で、その後だ。

実は・・・forkして作業するというのをほとんどやったことがない。
pull requestがマージされると、fork先が先に進んでしまうけど、どうしたらよいのだか。。。

GitHubでFork/cloneしたリポジトリを本家リポジトリに追従する - Qiita
https://qiita.com/xtetsuji/items/555a1ef19ed21ee42873

ありがたい。


手元にbranchが3つ(upstreamのもの、作業中だったもの、作業中をsquashしたもの)が残り、upstreamはそのままだし、squashしたものもmergeしたからよいのだが、作業中だったものは "git branch -d xxx"では消せず、 "git branch -D xxx"にしなくてはならなかった。
squashされたものの履歴までは追わないのだろう。


しかし、今回はsubmoduleも変わってしまったためか、mergeしてもcommitしていないものが残ってしまった。
commitしてpushしたのだが、当然オリジナルとは別のcommit idになる。


もしかして・・・forkしないでやるべきものなのだろうか?
いや、今まではそうせずにやっていて、commitログが乱れたものになってしまったのだから、それだと期待通りではない。


ずっとローカルで作業できるのであれば、forkせずにいけるような気がする。
だが、私はpushしてしまいたいのだ。
そうなると、第2のローカルという感じで、forkして自分のリポジトリで作業することになると思う。



今日はもうpull requestしたくなるようなものがないので、次回試すしかないな。


pull requestするものができたので、試した。

流れを復習しておこう。

  1. 本体からfork
  2. 本体側でsubmoduleの更新が発生
  3. fork側でpull requestし、本体側でmerge
  4. fork側を本体側に同期させようとして、upstreamをfetchして、メインブランチにmerge
    1. submoduleに差分が出たので、commit


この状態で、fork側からpull requestしたのだが、fork側のsubmode差分によるcommitも対象になってしまった。
おかげで、本体側のcommitログには、submoduleの更新が複数出てきてしまっている。
やはりか。。。


そんなに神経質になるつもりもないのだが、回避できるのであればやりたい。

簡単なのは、手順4をせずに、forkしたものを削除して、新たにforkする、だろう。
本体と同じものになるから、悩むこともない。


upstreamというブランチは、本体側と同じものだ。
それと同じように、手順4でmergeなどせず、mergeしようとしたブランチ自体を捨てて、fetchしたあとのupstreamからブランチを作ってしまえば良いのか?

何か違う、という感触はあるのだが、何がどうダメなのかはわからん。。。


だいたい、forkやらpull requestって、githubやbitbucketの機能で、git自体の機能じゃないよなぁ。
cloneして、remote set-urlで変更するとかか? いや、それじゃ足りないか。。。

使えば使うほど、gitへの理解が足りてないのが身にしみるわ。

2018年5月4日

クラウド上のVMとのファイル同期はどうやるのがよいのだろう?

ソースファイルを、ローカルで編集したり、ビルドしたりする。
gitを使っているので、適当なタイミングでpushする。

Linux向けのプログラムなので、ローカルマシンがWindowsではあまり確認がちゃんとできない。
なので、Windowsで実装し、クラウド上のLinuxVMで実行する、ということをしばしば行う。
このとき、どうやってファイルを同期させるのが良いのだろう?
(オープンソースで開発しているので、セキュリティにはそんなに考慮しなくて良い前提)


git経由でやっていたのだが、コミットログが「Linuxで動作確認するためにpush」みたいな感じになってしまい、それで動いたならまだしも、動かないこともしばしば。。。
gitのことを検索すると「コミットログを汚さない方法」みたいなものが結構出てくるのだが、世の中ではそういうやり方をして、なるべく不要なコミットログを残さないように努力しているのだろうか??



あるいは、DropBoxみたいなものを使うという手段もあろう。
Googleドライブだと同期が遅いのでやりづらいのだが、DropBoxは比較的速いので、手元で編集したらすぐにアップされるようだ。
これなら、コミットせずにVMと連携できるし、ファイルを変更するだけでよいから手軽だ。

しかし・・・なんか抵抗がある。
なんかちょっと違うんじゃなかろうか、という、漠然とした思いだけだ。



クラウド上のファイルを正とする、というパターンもありだ。
なんでローカルで編集しているかというと、使い慣れたテキストエディタが使いたいというだけなのだ。
SFTPなんかで編集したいファイルを持ってきて、編集したらアップする、みたいなことはSFTPツールで実現しているものも多い(私はWinSCPでやってる)。
ちょっとした変更だったら、これでもよいのだ。
ただ、複数のファイルを扱ったり、テキストエディタの機能で置換を掛けようとしても、それはできない。

まるまるマウントできると、非常にありがたい。
そういうわけで、今日はAzure Filesを使って、Windowsのネットワークドライブとして接続してみた。
ルータのフィルタリングで445が止められているのに気付かなくて時間がかかったが、困ったのはそれくらいだ(ルータが止めているというのにたどり着くまでが非常に大変だったが)。

WindowsのExplorerから見えるようになって便利なのだが、いくつか問題が。
私の環境で大きい問題は、シンボリックリンク。
CIFSというファイルシステムだからだろうが、シンボリックリンクが使えないようだ。
実行権限なんかは生きているようだから、ファイルコピーすればよいのだけど、そのために作りを変えるのも負けた気がするので避けたい。

また、アクセスがちょっと遅い気がする。
これはVMの方が原因かもしれないので、はっきりしたことは言えない。

あと、ポート445を開けるというのも、ちょっと嫌かも。


いま思いつく方法は、このくらいだ。

なんかいい方法を模索していかねば。。。

2018年4月22日

[tech]組み込み向けにするのをあきらめるとき

お仕事でプログラムを作っている。

一人で作っているのだが、設計も何もせずにやっている。
よろしくはないのだが、そもそもどういう動きをするようになるのかわからずに作るという、試作の手前のようなものである。


で、最近見直していると、同じようなことをやるのになぜか3つの実装方法をわざわざ使っていることに気付いた。
「同じようなこと」は、データを次々にためておく方法だ。

  • キュー
  • リングバッファ
  • リスト

我ながら「はぁ?」となってしまった・・・。
まあ、キューもリストも似たようなものではあるのだが、「キュー」は自分で実装したのだが、「リスト」はLinuxのリストであるLIST_HEADやLIST_ENTRYを使っている。
作ったのが別の人ならまだしも、私しかいないのに、なぜ。。。


プライオリティがなければ、データの詰め込み方はFIFOかFILOか、キューかスタックか、くらいしかないと思う。
リングバッファは、FIFO型になるのか。


たぶん、私の思考過程からすると、最初に作った「キュー」は、そこまで数が増えないけど、数の予測が付かなかったので、自作したのだろう。
その次がリングバッファになったのは「増えすぎたらキャンセルしてしまえ」と思ったからではなかろうか。

とにかく、メモリサイズがはっきりしない状況が嫌だったのだ。
何とかして、サイズを支配したかったようだ。


最後に作ったのはLinuxのリストを使ったもので、この頃になると自作するのも嫌になったし、サイズを考えるのにも疲れてきたのだろう。
そう、設計どうこうではなく、疲れたのだ。
私らしいといえば、私らしい。


そして、もう1つ。
作っているうちに、こりゃLinuxが動くレベルのマシンじゃないと実装できない、ということに気付いたことだ。
Cortex-Mなどの組み込みソフトにしてしまうことをあきらめたのだ。
これはこれで「疲れた」と表現できるかもしれない。


Raspberry-Pi1くらいあれば動くが、そこは私にとってはもう大きめの組み込みになる。
ストレージを付けたり外付けメモリとかやればCortex-Mでもできなくもないのかもしれないが、そこまでして実現する意味はあまりないだろう。
ハードウェアを安めに仕立ててソフトウェアががんばる、という時代でも無いと思う。
そういうことずっとやってるから、いつまで経っても仕事が減らんのじゃー。


と、それっぽい結論で終わらせようとしたが、実装が3種類もあるのはよろしくないので、どれかにまとめよう。

2018年2月24日

[tech]お悩みのKVS DB

愚痴というか、悩みというか、反省談というか。


いま作っているシステムでは、lmdbというKey-Value Storeのデータベースを使っている。
というといろいろ考えて選択したように見えるが、

  • SQL使うほどでも無い
  • C言語で使えるもの
  • よく使われている

というところで選んだだけだ。
そもそも、私はストレージが使えない組み込みシステムをやることが多かったので、DB自体くわしくない。


lmdbは、NoSQLと呼ばれる類のDBらしい。
https://ja.wikipedia.org/wiki/NoSQL

DBという全体集合があり、その部分集合としてSQL DBがある。
そして、NoSQLは、その反転した集合になりそうな気がするのだが、Wikipediaに書いてある"Not only SQL"が語源だとするならば、SQLを含んでいてもよいし、含まなくてもよい、ということになりそうだ。


lmdbは、SQL文は使わない。
DBの要素としては、こういうものがある。

  • environment
  • DB
  • key
  • data

まず、environmentという大きな広場があり、その中にDBを複数持つことができる。
そして、DBの中にkey-dataのセットでデータが格納されていく。

「トランザクション」というアクセス単位は、environment単位になる。
これに気付かなくてねぇ・・・。
トランザクションってDB単位でやるものだろうと思い込んでいたので、DBのオープンAPIにトランザクションが必要だとわかったときはショックだったわ。

イメージとしては、ドライブとディレクトリみたいなものか。
environmentがドライブで、DBがディレクトリ。
そして、ロックを掛けられるのはドライブ単位だ、と。

どうしても同時にロックしたくて、でもシステム上うまいことやれそうにないなら、environment自体を分けてしまうしかない。
システムを作って半年以上あれこれいじっているが、設計がよくなかったのか、lmdb以外だったらうまくやれたのか、未だによくわかっていない。


結局、environmentを分けることで対応したのだが、未だにどうするのがよかったのか、あるいはどうする方がよいのか、私の中で結論が出ていない。

SQLとかリレーショナルとか、そういう関連性がないということだけはわかっている。
そして、C言語から使いたい。
あとはメンテナンスされていっているとか、枯れているとか、そのくらいか。


https://ja.wikipedia.org/wiki/NoSQL
https://en.wikipedia.org/wiki/NoSQL


うーん、jaとenのWikipediaを並べてみたのだが、内容はともかく、数が多い!
これだけあるということは、特色がそれぞれあって、望む形はいろいろあるということなのか・・・。
「Aである」という事象はAだけだが、「Aではない」という事象は無限にあるのと同じか。

つまり、私が"lmdbでよかったんだろうか"という悩みは、ある意味では当然のことというわけだ。
無限にあるものの中から正解を1つだけ見つける、ということはあり得ないからだ。

2018年2月17日

[btc]addwitnessaddressのアドレスからdumpprivkeyはできない

bitcoindの話だ。

bitcoin-cli getnewaddressすると、P2PKHのアドレスが返ってくる。
HDウォレットのインデックスがインクリメントされて新しいアドレスが生成されたということか。

そのアドレスについてbitcoin-cli addwitnessaddressすると、P2WPKHのアドレスが返ってくる。
ただし、現在(2018/02/17)のところ、bitcoindではnativeのP2WPKHアドレスを扱うことができない。
だから、P2WPKH nested in BIP16 P2SHというアドレスがが返ってきている。

nested in BIP16 P2SH形式のよいところは、見た目上はP2SHアドレスになっているというところだ。
これなら、segwitに対応していないウォレットであっても送金することができる。
じゃあ、その形式だけでいいじゃないか、となりそうだが、segwitのnativeアドレスには利点がある。
その場合には、トランザクションのサイズを小さくすることができるのだ。

nativeなP2WPKHの場合、今までのscriptSigの部分がまったく無くなり、witnessのセクションに移動する。
segwitにするとブロックに入るトランザクションの数が増えるというが、たしかにトランザクションの数は増えるものの、トランザクション自体のサイズについては別の話だ。
nested in BIP16 P2SH形式の場合、scriptSigにもデータを置かないと既存ウォレットとの互換性が無くなってしまうので、トランザクションとしてのサイズが多少増えてしまうのだ。
ブロックに入れる際にwitnessの部分は別の場所に入るため、そこまで影響は無いのかもしれんが、大きくなることはなるのだ。
これがnative形式だとトランザクション自体が別物という扱いになるからかscriptSigのサイズは0になり、署名などはすべてwitnessに押し込められる。


私が不勉強なので、ブロックに取り込むところなどのしくみをよくわかっていないのだが、まあ、そこはbitcoindなんかがやってくれるからいいや、と割り切っている。
フルノードの庇護を受けている間は、けっこう楽ができるのだ。


ただ、というか、しょうがないか、というところだが、addwitnessaddressでつくったアドレスはdumpprivkeyで秘密鍵が取って来れないのだ。
P2SHという時点であきらめてしまう気がする。


次の0.16ではBECH32形式のアドレスが使えるようになるとか。
そうなると、直接nativeの形式でアドレスを生成できるようになるのかもしれん。

2nd Layerというか、BOLTではfundingにnativeなアドレスを使うことになっているので、今の時点では何とかしてP2WPKHから送金させる必要があるのだった。

まあ、そういうこともあるさっ。

2018年2月11日

[btc]デフォルトのdust limitは546(2018/02/11)

Bitcoinで使用できる、voutのamount下限はいくつだっけ、といつも考えてしまう。
通常は気にしないくらいの値だが、2nd Layerとかやってると、ね。


今の時点のmasterのデフォルトでは、546satoshiでいいだろう。

https://github.com/bitcoin/bitcoin/blob/fe53d5f3636aed064823bc220d828c7ff08d1d52/src/test/transaction_tests.cpp#L695

BOOST_CHECK_EQUAL(nDustThreshold, 546);



固定値なら「546」で検索すれば出てきたのだろうが、どうやら計算して得るものらしい。
将来変わるかもしれんので、masterの方のリンクも載せておこう。
行は変わるかもしれんが、nDustThresholdで検索すればいいんじゃないかね。

https://github.com/bitcoin/bitcoin/blob/master/src/test/transaction_tests.cpp#L695



APIとしてはこれだろうか。
https://github.com/bitcoin/bitcoin/blob/5961b23898ee7c0af2626c46d5d70e80136578d3/src/policy/policy.cpp#L18

推測に推測を重ねてしまうが、判定はここか。

https://github.com/bitcoin/bitcoin/blob/5961b23898ee7c0af2626c46d5d70e80136578d3/src/policy/policy.cpp#L52-L55

bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
{
    return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
}

だとすると、546未満がNG、ということになるな。

Gmailのaddonで返信文を作る(が、Subjectが日本語だと化ける)

Gmailをブラウザで見ると、アドオンというものがあることに気付いた。
自分でも作ることができるらしい。


このクイックスタート通りにやれば、取りあえず何か動くものができる。
https://developers.google.com/gmail/add-ons/guides/quickstart

メールを1つ選択すると、その人からの直近のメールが5つ分リストに出てくるようだ。



ブラウザでGmailを使うことはほとんど無いのだが、あったらよいと思うのは文章のテンプレートだろうか。
「お世話になっております」みたいな、どうでもいいような文章を手で打ちたくないのだ。
Chromeのアドオンにそういうものがあったような気がするが、内部で実現できた方が安心だ。


サンプルがあるので、これの文面を入れ替えればよかろう。
https://developers.google.com/gmail/add-ons/how-tos/compose

・・・と思ったのだが、これの動かし方がわからない!
中を知らずに貼り付けるだけで動かそうという考えが甘かったようだ。


こんな感じにすると、動いた。

oauthScopesはいらないものがあるかも。
logoUrlはクイックスタートそのままだ。。。


image


もっと格好良く書けるのだろうが、文法を分かってないのでこの辺が限界だ。


やってみて分かったけど、ボタンを押してから文章が出てくるまでに、まあまあ時間がかかる。
もうちょっと長い文章のテンプレートだったらありがたみがあるけど、今回作った程度の長さだったらキーボードから入力してしまいそうだ。

まあ、動いたので私は満足である。


作るだけで満足してしまったが・・・送信するとタイトルが化けていることに気付いた。

image

なんだろう??


どうも、Subjectが日本語だと化けているようだ。
メーラのせいかと思ったが、ブラウザGmailで送信しても化けた。
JISをうまく処理できてない??

と思ったが、message.getSubject()のようにしてSubjectを取得し、それをbodyにするとちゃんと見えている。

URLエンコードでもダメ。
"あいうえお"と指定すると「BDFHJ」と出てきた。
"あ"が0x3042だから、そういう化け方をしているようだ。

"0u3042"にしても「B」だし、"0x42"でも「B」だから、こりゃどうしようも無いのかも。

2018年1月21日

ECDSAの署名+αから公開鍵を算出したい (10) - 完

まず、前回の修正から。


ハッシュ値のマイナスである-eを求めるとき、(0 - e)は不一致で、(N - e)で一致した、ということを書いた。
あれは、実装を間違えていた。
(0 - e)まではよくて、最後にmodするとき、mod Pでやってしまっていたのだ。
mod Nでやると、ちゃんと期待した値になった。
まあ、そうじゃないとbitcoinlib-jsでの計算がe.negate().mod(n)でうまくいくはずはないわな。


https://qiita.com/sh-miyoshi/items/7479f6e647a324638b9a
ここを読み、Nを法とした世界での-e値は、Nからのマイナス方向でe進んだところになるということがわかった。
つまり (N - e) となるので、最初の計算も間違いではないし、eがmod Nされた値であれば、N - eであればmodする必要はないということになる。


うーん、今までeの値そのものについてはハッシュ計算するだけで深く考えていなかったのだが、楕円曲線で使う場合にはmod Nしないといけないのだろうか?
心配になってきたので、実装としては (0 - e) mod Nにしておこう。


なお、mod Pしてしまった理由だが、mbedTLSは大きい数字のmod APIも持っているが、楕円曲線の場合はmod Pを高速に計算するAPIが別途用意されている。
https://github.com/ARMmbed/mbedtls/blob/mbedtls-2.6/include/mbedtls/ecp.h#L149

なので、なんか楕円曲線ではmodP()を使うものだと思い込んでしまったのだ。


では、mod Pだったりmod Nだったりする使い分けは何なのだろうか?

https://en.bitcoin.it/wiki/Secp256k1

p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F
n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141

桁数は同じ。
書き方としては、field pで、order nとなっている。

https://btcnews.jp/elliptc-curve-diy/

よって、楕円曲線の計算をする場合、整数の計算はNで限り、平面の座標を指す場合はPで限ります。

なにが「よって」なのかはわからないが、整数はmod N、座標はmod Pということらしい。

値としては、P > Nになるから、座標にした方が広く表されるようだ。
もしかしたら、基点GとNの乗算によって表される座標のXかYがPくらいになるということか?


sec1-v2.pdfを見てみた。

field p = { 0, 1, ..., p-1 }

h = #E(field p) / n

#E(field p)は、Eがfield pで定義されるならその曲線上の点、「order of the curve E」と呼ぶ

order n of Gなので、nは位数

位数nは、第7回で少し調べた。
n1~np-1で、mod pした値は重複しないという関係か。
order n of Gだから、mod pじゃなくてmod G?
でも、pは数字だけど、Gは楕円曲線上の点だ。
#E(field p)がorder of the curve Eだから、ここだと#G(field n)と表すのか?


うーん、mod Nとmod Pの使い分け根拠を知りたいだけなのだが。。。

x = r + jNは数字だけど、それをRのX座標にするので、mod P。
r-1は数字だから、mod N。
-RはRのY座標を反転させるのだが、座標だからmod P。

第6回で-Rを求めるのにP - R.Yを使ったのだが、これは最初に書いた-eと同じ話だ。
こちらはちゃんとmod Pとしていたのだが、使っている関数が高速なmodp()だった。
どうも、modp()は正の数じゃないと処理ができないようで、mbedtls_mpi_mod_mpi()を使うと0 - R.Yで計算できる。
R.YはPを法としているので、P - R.Yで値を外れることはないことになる(modp()しても変化しないのでうまくいってる)。


長くなったが、このシリーズはここで終わろう。

できれば、自作したくないところではあるのだが、APIが存在しないなら作るしかなかろう。
secp256k1ライブラリだけ独立しているなら使ってもよいのだが、bitcoindの中に入っているので悩んでしまうのだ。

2018年1月20日

ECDSAの署名+αから公開鍵を算出したい (9)

自作の公開鍵復元が動かないので、先生を動かすことにした。

https://github.com/bitcoinjs/bitcoinjs-lib/tree/v2.1.4


recoverPubKeyを持つのがv2なので、この辺りを使った。
こんな感じで書くと、動くことが分かった。


var ecdsa = require('./src/ecdsa')
var BigInteger = require('bigi')
var ECSignature = require('./src/ecsignature')


//pubkey= 03becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459
//hash=b881ab3c470b9398adb5ea6cb360d145df702fa0bc0a6c012219fa93e709adad
//  r=047c1b1111bbe0fc09cf2ed28dd1abd613c02b747af8edd1274886654259bbfb
//  s=1d00ca3fc10a111a5a3ea0669992e4ad9a2f1c402ec5fd29d9e1348ab0584fa2

var e = BigInteger.fromHex('b881ab3c470b9398adb5ea6cb360d145df702fa0bc0a6c012219fa93e709adad')
var r = BigInteger.fromHex('047c1b1111bbe0fc09cf2ed28dd1abd613c02b747af8edd1274886654259bbfb')
var s = BigInteger.fromHex('1d00ca3fc10a111a5a3ea0669992e4ad9a2f1c402ec5fd29d9e1348ab0584fa2')
var signature = new ECSignature(r, s)
var i = 0

var Qprime = ecdsa.recoverPubKey(e, signature, i)
var QprimeHex = Qprime.getEncoded().toString('hex')
console.log('Qprime=', QprimeHex)

$ node recover_pub.js
Qprime= 03becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459

さすが先生ですわ・・・。
自分の結果と比較するために、データを残しておこう。

i=0
03becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459

i=1
0383a8ef00cdbdc68b4176c72be1b2173b522633ba525f7a89334e4bab6cec89b4

i=2
03ccb2ec2eca77c75955cd5334e9f0248adf51dcb37744fef36a9152dd468cbe37

i=3
02082151f0695b3b98128e4326e7ddd1f44264448d39723b10ba56976c44fe5dba

i=4
例外発生

うちの子はこうだ。

i=0
0283a8ef00cdbdc68b4176c72be1b2173b522633ba525f7a89334e4bab6cec89b4

i=1
02becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459

i=2
03f23664e578b9cc1f8eb81e47ce3eb037043a5a92f0a3fc09ebd2ca121f862e05

i=3
03b06c50b0579e2142f56756c29445d7762539368be48918db2d6bd4f2f562b51d

i=0とi=1の結果が逆のような形になっている。
i=2と3は共通点がない。

この辺りに突破口がないだろうか。


うーん、-eの値が違う。

先生
e   = b881ab3c470b9398adb5ea6cb360d145df702fa0bc0a6c012219fa93e709adad
eNeg= 477e54c3b8f46c67524a15934c9f2eb8db3ead45f33e343a9db863f8e92c9394


私
e    = B881AB3C470B9398ADB5EA6CB360D145DF702FA0BC0A6C012219FA93E709ADAD
eNeg = 477E54C3B8F46C67524A15934C9F2EBA208FD05F43F593FEDDE6056B18F64E82

実は、前回まで私は (0 - e) % Pを計算していたのだが、ログに出してみるとeと同じ値だったのだ。。。
Y座標の符号を逆にするときの反省を生かして(P - e) % Pにしたのが今回。
それでも、微妙に値が違っている。


先生は、e.negate().mod(n)で計算している。
だいたい、一番最後の桁を足しても、0xD + 0x4は0じゃないやん。。。

やけになって、PではなくNでやってみた。

私
e    = B881AB3C470B9398ADB5EA6CB360D145DF702FA0BC0A6C012219FA93E709ADAD
eNeg = 477E54C3B8F46C67524A15934C9F2EB8DB3EAD45F33E343A9DB863F8E92C9394

理屈はわからんが、値が一致してしまったではないか。

i=0
03becec41f68d77fde9e972c79aa0e6e4e818bd3046276969e79374ec0561ba459

i=1
0383a8ef00cdbdc68b4176c72be1b2173b522633ba525f7a89334e4bab6cec89b4

i=2
02b06c50b0579e2142f56756c29445d7762539368be48918db2d6bd4f2f562b51d

i=3
02f23664e578b9cc1f8eb81e47ce3eb037043a5a92f0a3fc09ebd2ca121f862e05

うーん、i=2と3がまだ不一致だ。


これは、Rが不一致なためのようだ。

先生(i=2)
x= 01047c1b1111bbe0fc09cf2ed28dd1abd4ce6f085b2a418e0ce71ae4f2128ffd3c
R= 02047c1b1111bbe0fc09cf2ed28dd1abd4ce6f085b2a418e0ce71ae4f31290010d

私
x = 01047C1B1111BBE0FC09CF2ED28DD1ABD4CE6F085B2A418E0CE71AE4F2128FFD3C
R.x = 01047C1B1111BBE0FC09CF2ED28DD1ABD4CE6F085B2A418E0CE71AE4F2128FFD
R.y = 7F6ACBA2D227DCA73DDC17A895454F00A97F34A87967BECB6535287E0E5C436C

xは同じ値で、Rはxの先頭に0x02を付けたもののはずだが、先生はそうしていない。
そして、私もそうなっていないのだが、なんでだ??

あ、表示桁が足りてない・・・。
xにNを足したとき、33byteになってしまったのだ。
単純なバグだな。

i=2
03ccb2ec2eca77c75955cd5334e9f0248adf51dcb37744fef36a9152dd468cbe37

i=3
02082151f0695b3b98128e4326e7ddd1f44264448d39723b10ba56976c44fe5dba

一致した。


で、だ。

ハッシュ値eに対する-eを求めるとき、N - eして値が一致したけど、それでよいのだろうか?
secp256k1の法に従うことにはなるのだろうけど、そこが感覚的に分かっていない。

(sR - eG)を求めるとき、APIとしては (a * P + b * Q)しかないためにbをマイナスにしようとしただけなのだ。
だから、単純に(0 - e)を求めたのだが、これは当然負の数で、それは0~N-1の世界にいないからダメなのか?


「module 負」で検索すると、そういう計算自体が微妙なところらしい。
言語間で違うということは、ライブラリだと言語に関係なく違いが生じるということか。

うーん、難しいことはやらずにAPIだけ使い回して完了させる予定だったのに、最後に悩みが残る結果になってしまった。
楕円曲線の簡単な説明をしてくれるサイトでも読むか。

2018年1月18日

ECDSAの署名+αから公開鍵を算出したい (8)

このシリーズも、早8回目。
すぐにあきらめて終わるだろうと思ったのだが、意外と粘り強いようだ。
粘り強いというか、粘着質というか・・・。


Bitcoinなどで使っている楕円曲線暗号の計算は、楕円曲線のグラフそのままではなく、剰余で範囲を制限した値空間になるということと、その空間ではX座標に対してY座標が正負にあるのではなく、なんだかわからないが偶数/奇数になる、ということが前回分かった。

分かったというか、分からないところも多かったので、そのまま受け入れたというところだ。


では、前回0x02と0x03が逆になったのは、それに関して何か間違っていたのではないかと思うだろう。
よって、今回はY座標の値も見てみた。

・・・偶数/奇数と0x02/0x03の関係は間違っていない。
よく考えたら、非圧縮公開鍵を圧縮公開鍵に変換するのはAPIを使っているから、そこは間違えないのだった。


なのに。。。なぜ。。。


移植元になったjavascriptのライブラリを動かしてみようとしたのだが、さっっっぱりわからん。
動かないということはわかったのだけど、何をして良いのかわからんのだ。


https://stackoverflow.com/questions/28400459/referenceerror-describe-is-not-defined-nodejs
ここにならって、npmでmochaをインストールし、`mocha` とやってみたのだが無いと怒られたので、sudo apt install npmでインストール。。。しようとしたら、404 Not Foundでインストールできず。

たいがいにしとけや、きさーん!と思ったが、こちらにもインストールの方法が載っていた。
https://qiita.com/TsutomuNakamura/items/0eb50bf7622a3906e101

npmにsudoして、-gもやってやらんといかんのか。
このディレクトリだけ動けばいいから-gをつけてないのがいかんかったか。。

そして、一番上のディレクトリで「mocha」を実行すると、何か進んだ。
よかったよかった。


。。。よくない。
ソースはいじってないのに、見たいところがピンポイントでエラーになっているではないか。

1) ecdsa
      recoverPubKey
        throws on Invalid i value (> 3) (Expected UInt2, got Number 4):
    Error: Expected property "2" of type UInt2, got Number 4
     at tfSubError (node_modules/typeforce/errors.js:93:9)
     at node_modules/typeforce/index.js:159:17
     at Array.every (<anonymous>)
     at _tuple (node_modules/typeforce/index.js:155:20)
     at typeforce (node_modules/typeforce/index.js:196:9)
     at Object.recoverPubKey (src/ecdsa.js:166:3)
     at test/ecdsa.js:129:17
     at tryBlock (assert.js:619:5)
     at innerThrows (assert.js:638:18)
     at Function.throws (assert.js:662:3)
     at Context.<anonymous> (test/ecdsa.js:128:16)

UInt2を期待したけど4が来た?
うーん、UInt2って書いてあると、0~65535までOKのような気がしたが、javascriptは違うんだろうか。
2がbitの2だったら、0~3というのは納得できるが、そもそもこのtestをがんばって意味があるのか。。。

最新版のbitcoinjs-libだったら、書いてあるとおりにやればよいのかもしれんが、recovery pubkeyがあるのは古いバージョンだけなのだ。


残念だが、思考が定まらんし、今回はここまでだ。