Wen
中国の伝統音楽に興味ある方へのおすすめYoutubeチャンネル

以下、もちろんいずれも私の独断と偏見になります。😀

今回紹介したいのは 自得琴社 Zi De Guqin Studio というチャンネルです。

80 年 90 年代生まれの若者たちを中心に中国の伝統楽器で作曲したり演奏したりしてます。

曲については、中国のものだけでなく、

以下のような 「ドラエモンの歌」中国の古楽器で弾いてみようハリー・ポッター とか外国の歌を面白く再現したり創意工夫されています。

「ドラエモンの歌」中国の古楽器で弾いてみよう

ハリー・ポッター

ゆっくりご観賞ください。

他におすすめしたいようなチャンネルがありましたらまた随時更新します。

Golang-ユニットテストにおける正しい後処理の書き方:t.Cleanup()

ユニットテストの後処理を行う場合、

defer並列で動いているサブテストの終了を待たずに実行されてしまう問題がある。

全てのサブテストが終了してから後処理を行たいなら t.Cleanup() を使おう。

Deferによる後処理の例

package main

import (
    "log"
    "testing"
)

func TestDefer(t *testing.T) {
    tcs := map[string]string{
        "A": "1",
        "B": "2",
        "C": "3",
    }

    defer log.Printf("End")

    for tn, tc := range tcs {
        tc := tc
        t.Run(tn, func(t *testing.T) {
            t.Parallel()
            log.Println(tc)
        })
    }
}

そのログの抜粋:

2009/11/10 23:00:00 End
2009/11/10 23:00:00 1
2009/11/10 23:00:00 3
2009/11/10 23:00:00 2

demo

t.Cleanup() による後処理

package main

import (
    "log"
    "testing"
)

func TestCleanup(t *testing.T) {
    tcs := map[string]string{
        "A": "1",
        "B": "2",
        "C": "3",
    }

    t.Cleanup(func() {
        log.Printf("End")
    })

    for tn, tc := range tcs {
        tc := tc
        t.Run(tn, func(t *testing.T) {
            t.Parallel()
            log.Println(tc)
        })
    }
}

そのログの抜粋:

2009/11/10 23:00:00 1
2009/11/10 23:00:00 3
2009/11/10 23:00:00 2
2009/11/10 23:00:00 End

demo

参考

Go 言語でのテストの並列化 〜t.Parallel()メソッドを理解する

t.Cleanup()で並列に動かすことのできるテーブルドリブンテストを書く

Bash:あまり知られてないBashの2つの裏ワザ

シェルの展開(EXPANSION)

以下、 mv コマンドによる例で説明していますが、他のコマンドにも使えます。

$ mv README.{txt,md}
// 効果は以下と同様
$ mv README.txt README.md

$ mv data/{models,ml}
// 効果は以下と同様
$ mv data/models data/ml

$ mkdir data{0..2}
// 効果は以下と同様
$ mkdir data0 data1 data2

コマンドの素早い置換

タイプミスとかでコマンドを間違って実行した直後に修正したい場合に

$ ssh aaplee@server
$ ^aaplee^aaple

$ ^old^new$ !!:s/old/new に相当します。

!! は最後に実行されたコマンドで、:s/old/newoldnew に入れ替えることを意味します。

最後に一言

より少ない入力(type less)で、

  • 仕事のスピードアップ
  • より正確な作業
  • ミスを減らす
  • 疲れている手のストレスを軽減する

参考記事

シェルの展開(EXPANSION)を学ぶ

3 Uncommon Bash Tricks That You Should Know

Golang-構造体にあるパスワードなどのセキュリティ情報をログに出力しないようにする方法

構造体をログに出力する際に、パスワードとかのようなセキュリティ情報を出力したくない場合は、方法の一つは 構造体の埋め込み(Embedded) 特性を利用することです。

構造体の埋め込みの形は、次のような形になります。

type 埋め込み構造体名 struct {
    フィールド名 型名
    フィールド名 型名
}

type 構造体名 struct {
    **埋め込み構造体名**
    フィールド名 型名
}

以下のような例で説明しますと、

RequestSanitized.PasswordRequest.Password を上書きすることになります。

Password を出力したくなければ、あえてRequestSanitized.Password を空値にすれば良いです。

type Request struct {
    Name   string      `json:"user"`
    Password string `json:"password"`
}

type RequestSanitized struct {
    Request
    Password   string `json:"password"`
}

以下、完全なる例です。

package main

import (
    "encoding/json"
    "fmt"

)

type Request struct {
    Name   string      `json:"user"`
    Password string `json:"password"`
}

type RequestSanitized struct {
    Request
    Password   string `json:"password"`
}

func main() {
    request := Request{Name: "wen", Password: "123"}
    requestSanitized := &RequestSanitized{
        Request: request,
    }

    requestSanitizedJson, _ := json.Marshal(requestSanitized)

    fmt.Println(string(requestSanitizedJson)) // {"user":"wen","password":""}
}

Go Playground デモ

Golangによるパスワードの保存

パスワードの保存方法として、

平文のパスワードを単方向ハッシュにかけて保存するのが一般的です。

ハッシュアルゴリズムにはSHA-256SHA-1MD5等があります。

Golang は crypto パッケージで簡単に実装することが可能です。

以下、 sha256 によるの実装例です。

//import "crypto/sha256"
h := sha256.New()
io.WriteString(h, "my password")
fmt.Printf("% x", h.Sum(nil))

より良い方法

大抵の場合は、暗号化時に使用されたハッシュアルゴリズムが上記のような公開されているものであることが原因で、かつ技術の進歩によりパソコンの計算力も上がり、ハッカーがrainbow tableを使用することで上記の方法でハッシュされたパスワードをクラックすることが(時間的に)難しく無くなってきたのが現状です。

rainbow table :ハッシュ結果(ダイジェスト)のデータベース

直接的な解決方法の一つは、自分でハッシュアルゴリズムをデザインすることです。

しかしながら、優良なハッシュアルゴリズムはとてもデザインが難しいのです。

そのため、実際のアプリケーションでは既存のハッシュアルゴリズムを利用して複数回ハッシュすることが行われます。

しかし単純な複数回ハッシュでは、ハッカーも当然思いつきます。

そこで、管理者自身だけが知っているランダムな文字列をさらに追加して再度ハッシュします。

そのランダム文字列を salt **(ソルト → 塩)と言います。料理に塩***を*ひとふりするだけでグンとおいしさが増すように、ハッシュからパスワードをクラックする難易度もグンと上がります。

//import "crypto/md5"
h := md5.New()
io.WriteString(h, "your password")

pw_md5 :=fmt.Sprintf("%x", h.Sum(nil))

//saltを指定します
salt := "your salt"

//salt1+ユーザ名+salt2+MD5を連結します。
io.WriteString(h, salt)
//io.WriteString(h, "username") // ユーザ名を連結しても良い
//io.WriteString(h, salt2) // saltは複数かけても良い
io.WriteString(h, pw_md5)

result :=fmt.Sprintf("%x", h.Sum(nil))

これで、saltが漏洩していなければ、ハッカーはもし暗号化された文字列を手に入れてもオリジナルのパスワードが何だったのか推測するのはほとんど不可能です。

もっと安全な方法

しかし、並列計算能力の向上によりrainbow tableを作成するだけの十分なリソースがあればこのような攻撃はすでにまったくもって可能です。

そこで、故意にパスワードの計算に必要となるリソースと時間を増加させることによって、誰にもrainbow tableを作成するのに必要となるリソースを与えないという方法があります。

この方法、アルゴリズムの因子(パラメータ)を調整することで計算強度を上げることにより実現できます。

Golang には既にscrypt というライブラリが用意されていて、以下のその例です。

package main

import (
    "encoding/base64"
    "fmt"
    "log"

    "golang.org/x/crypto/scrypt"
)

func main() {
  password = "your password"

    // saltはご自身のものに入れ替えてください
    salt := "your salt"

    dk, err := scrypt.Key([]byte(password), []byte(salt), 1<<15, 8, 1, 32)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(base64.StdEncoding.EncodeToString(dk))
}

scryptの詳細については、こちらに論文があります。

参考記事

Build web application with Golang

php:安全なパスワードハッシュ

キャンプ道具-初心者がまず買うべきオススメ

なぜこの記事を書こうと思った理由

  • その1: ほぼ毎晩 Youtube でアウトドアやキャンプ道具に関連する動画を見る私がまとめなきゃと
    😀 まあもうお酒 🍺 のおつまみみたいなもんになっちゃっているかも。
  • その2: 友人がキャンプを始めるからと言うのもある。

その一覧

ということで、今回はまず初心者におすすめのキャンプ道具を紹介したいと。

(1). シート/マット

キャプテンスタッグ(CAPTAIN STAG) キャンプマット レジャーシート EVA フォーム マット

現時点 2022 年 02 月 26 日の amazon の値段 💰: ¥ 1,845

おすすめの理由としては、

  • 柔らかくて超軽量 270g
  • 厚くて冬とかの寒い時期に特に重宝する
  • 折り畳めて携帯しやすい
  • コスパ最高
  • 現時点アマゾン 10,200 個の評価で 星 5 つ中の 4.3…

家族の場合は、ダブルサイズを選ぶと良いかも。
ただし、シングルサイズの 2 倍以上かかるのでシングルサイズ2枚にするにもあり。

(2). バーナー/ストーブ

ソト(SOTO) レギュレーターストーブ ST-310

現時点 2022 年 02 月 26 日の amazon 在庫無し 価格の最安値💰: ¥ 6,800。コロナの影響もありだいぶ上がった。

おすすめの理由としては、

  • ガスバーナーならこちらが定番、海外製の安いものも色々とあるが熱い飯食えるか命関係しているんで慎重に w
  • ガスは CB 缶を使用可能(スーパやコンビニで 100 円ぐらいで入手簡単)。ちなみに SOTO さんもガスを 3 本パック 800 円ぐらいの値段で販売。普通の 100 円ぐらいのブランドよりは燃焼率はちょっと良いようだが私はやすい方を使用してて大差を感じない。注意点して、CB 缶は、気温 10 度以下 or 標高 2000m 以上から、機能が落ちる。
  • 折り畳めてコンパクトだが耐荷重が 5kg までも。
  • アルコールストーブという選択肢もあるが初心者にはガスバーナーが扱いやすいかも。

(3). クッカーセット

正直にクッカーはどれでも良い。予算があればチタン製(超軽量で錆びない)をおす。
一応候補として


参考にした動画や記事など

3 種類の燃料が使えるアルコールストーブ【ヴァーゴ トライアド】VARGO TRIAD MULTI-FUEL STOVE の開封と燃焼実験
「キャンプ道具」面白いアルコールストーブ3種を比較
🔥 超人気ガスバーナー 8 選 🔥 激安 3 千円から 1 万円のものまで!!プリムス・SOTO・ EPI・鹿番長・イワタニなど!
イワタニカセットボンベ”と”超格安ボンベ”の違いに目を疑った検証
[CB 缶]シングルバーナーってどれ買えばいいの?【Amazon 最安 vs 一番人気】
【キャンプ道具】初心者がまず買うべきオススメは 2 つだけ【比較と選び方】

[vscode] fatal: could not read username

現象

  • 環境
    sw_vers
    ProductName:    Mac OS X
    ProductVersion:    10.15.7
    Visual Studio Code: 1.62.3 (Universal)
    

VSCode の Status 欄に以下のようなエラーがあった。

fatal: could not read Username for '[https://github.com](https://github.com/)'

原因

go.modgo get プライベートリポジトリがあり、

go getでモジュールをダウンロードする際は通常http通信をしているため、

GitHub のプライベートリポジトリへは認証が通らず、エラーになってた。

解決策

Step1: Github のDeveloper settings 画面でトークンPersonal access tokens)を作成。

Step2:git config設定。

以下のコマンドの < your personal access token > を入れ替えた上で実行。

$ git config --global url."https://< your personal access token >:x-oauth-basic@github.com/".insteadOf "https://github.com/"

実行をすると、~/.gitconfigに追記されて、go getをすることができるようになる。

Reference

https://www.yuyagishita.com/tech/golang/go-get-github-private-repository/

[vscode] Error loading workspace: You are outside a module

現象

  • 環境
sw_vers
ProductName:    Mac OS X
ProductVersion:    10.15.7
Visual Studio Code: 1.62.3 (Universal)

VSCode の Status 欄で以下のようなエラーがあった。

Error loading workspace: You are outside a module and outside of $GOPATH/src

vscode loading workspace error

import 文もそれで lint error になる。
golang-import-error

原因

gopls"go.useLanguageServer": true で有効)を使いながら、

go.mod をサブディレクトリに置いて、プロジェクトのルートディレクトリから VSCode を開いてたのが原因だった。

例えば、VSCode で以下のような構成となる projects フォルダを開くと、

.../projects/aaa_proj
.../projects/bbb_proj

aaa_proj 配下に go.mod ファイルがあるため outside of module error エラーになる。

Solution

aaa_projbbb_proj に入ってから VSCode を開く。

Reference

https://daido.hatenablog.jp/entry/2020/09/17/154228

ssh-addをPC起動する度に自動的に実行させるための設定

環境

sw_vers
ProductName:    Mac OS X
ProductVersion:    10.15.7

問題

macOS の ssh-agent には特別に keychain に秘密鍵を登録する -K オプションがあり、それを使うと再起動のたびに ssh-add する手間を省くことができてましたが、

$ ssh-add -K ~/.ssh/{your private key name}

Sierra (10.12) 以降では keychain に保存はされるものの、再起動時に自動では読み込まれなくなりました。

解決方法

~/.ssh/config に以下のように追記します。

Host *
    UseKeychain yes
    AddKeysToAgent yes
    IdentityFile ~/.ssh/{your private key name}
  • {your private key name} : ご自身の秘密キーに置き換えてください。デフォルト名 id_rsa の場合は、IdentityFile を指定しなくても良いです。

Reference

https://qiita.com/sonots/items/a6dec06f95fca4757d4a

[Go言語] JSONパッケージがHTML文字をエスケープしてしまう問題の解消方法

現象

JSONパッケージで文字列をエンコードすると、HTML文字がエスケープされてしまうようです。

package main

import (
    "encoding/json"
    "fmt"
    "bytes"
)

func main() {
    data := "{'a': 'x < y'}"
    raw, _ := json.Marshal(data)
    fmt.Println(string(raw))
    //output: "{'a': 'x \u003c y'}" ← おそらく期待したものではないでしょう
}

解消方法

package main

import (
    "encoding/json"
    "fmt"
    "bytes"
)

func main() {
    data := "{'a': 'x < y'}"

    var buffer bytes.Buffer
    enc := json.NewEncoder(&buffer)
    enc.SetEscapeHTML(false)
    enc.Encode(data)
    fmt.Println(buffer.String())
    //output: "{'a': 'x < y'}"
}