FM牛鍵屋本舗

プログラマ(弱)の日々精進系ブログ

Go言語のTLSのHTTP実装:オレオレ証明書をコード中で登録する

Real World HTTPで GO言語でTLSの簡易HTTPサーバ、クライアントを実装しよう、というトピックがありました。

説明の通り、OpenSSLコマンドでルートCA、サーバ、クライアントの鍵と証明書を作りました。(コマンドの意味は理解できておらず…この辺りも学んでおかないと…)

本来、無条件に信頼するルートCAはOSに登録されていたり、ツールや言語によってはn内部に含まれていたりするそうです。今回のオレオレ証明書curlで叩くならコマンドラインで渡すなどの方法もとれるそうですが、、GO言語のデフォルトではOSのを参照してしまうそう。

それも面倒なので、プログラムコード内で登録します。 サーバ認証の場合、検証するのはクライアント側になるので、クライアントコードにルートCA追加処理を記述します。これは上記書籍にサンプルソースがありました。 *tls.ConfigRootCAsを使うそうです。

抜粋ですが。

   cert, err := ioutil.ReadFile("ca.crt")
    if err != nil {
        log.Println(err)
    }
    certPool := x509.NewCertPool()
    certPool.AppendCertsFromPEM(cert)

    tlsConfig := &tls.Config{
        ClientAuth: tls.RequireAndVerifyClientCert,
        MinVersion: tls.VersionTLS12,
        ClientCAs:  certPool,
    }
    tlsConfig.BuildNameToCertificate()

    server := &http.Server{
        TLSConfig: tlsConfig,
        Addr:      ":18443",
    }

じゃあクライアント認証も…ってことで、写経してみましたが動かない。

018/01/27 14:57:59 http: TLS handshake error from [::1]:57397: tls: failed to verify client's certificate: x509: certificate signed by unknown authority

むむ、CAが信頼できない、と。 じゃあどうやるんだろうってことで、crypto/tlsのドキュメントを読んだところ解決。ClientCAsを使用します。

   cert, err := ioutil.ReadFile("ca.crt")
    if err != nil {
        log.Println(err)
    }
    certPool := x509.NewCertPool()
    certPool.AppendCertsFromPEM(cert)

    tlsConfig := &tls.Config{
        ClientAuth: tls.RequireAndVerifyClientCert,
        MinVersion: tls.VersionTLS12,
        ClientCAs:  certPool,
    }
    tlsConfig.BuildNameToCertificate()

    server := &http.Server{
        TLSConfig: tlsConfig,
        Addr:      ":18443",
    }

アロー関数

去年末からずっと渋川よしきさんのRealWorldHTTPという本を読んでるんですが、 なかなか読了できず。。。

FetchAPIのサンプルを拝読していたら、
見慣れぬ構文が…。

// (中略)
.then((response) => {
    return response.json();
})
// (後略)

lamdaっぽい…

ということで、調べてみたら
ECMA6からアロー関数というのが追加されたっぽいですね。
目的は二点。

  • 関数を短く記述
  • thisを束縛しない

ふむ。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title></title>
  <script type="text/javascript">
    function myFunc(sub) {
      console.log(sub('aaaa'));
    }
    myFunc((str) => {return str + 'help';});

    // 別に戻り値を返さなくてもいいし、こういうことも出来る。
    var lamda = (val) => {console.log(val);}
    lamda('take me');

    // JSオブジェクトを返すときは()で囲む。構文の{}と区別つけるためかな
    var obj = () => {return ({hoge : 'moge'});}
    console.log(obj());

    // こうすることで、引数のJSオブジェクトのプロパティにアクセス出来る
    obj = ({hoge}) => {return hoge;}
    console.log(obj({hoge : 'Giant'}));
    
    // thisの束縛について
    // 本来、thisのスコープはレシーバになる。
    // => なんか違った気がする…
    function testThis() {
      console.log('[outer]' + this.name);
      var self = this;
      function inner() {
        console.log('[inner]' + this.name);
        console.log('[inner-self]' + self.name);
      }
      inner();
    }
    testThis.call({name : 'testThis'});

    // アロー関数ではthisは外側のthisになる
    function testThisLamda() {
      console.log('[outer]' + this.name);
      var self = this;
      var inner = () => {
        console.log('[inner]' + this.name);
      }
      inner();
    }
    testThisLamda.call({name : 'testThisLamda'});
  </script>
</head>
<body>
</body>
</html>
aaaahelp
arrow.html:8:7
take me
arrow.html:13:27
Object { hoge: "moge" }
arrow.html:18:5
Giant
arrow.html:22:5
[outer]testThis
arrow.html:27:7
[inner]
arrow.html:30:9
[inner-self]testThis
arrow.html:31:9
[outer]testThisLamda
arrow.html:38:7
[inner]testThisLamda
arrow.html:41:9

synchronizedブロックとwaitに関する仮説

JavaGoldの資格勉強してて、 「なんでsynchronizedブロックでしかwait/notify/notifyAll使えないんだろう?」 と疑問に思ったので考えてみた。

間違ってるとは思うのでツッコミ待ち。

メソッド名から考えてみる

まず、Threadを一時中止するメソッドとして

java.lang.Thread.sleep

がある。 上記のクラス、メソッド名で考えると「Treadが眠る」となる。

一方、

java.lang.Object#wait

こちらは、「オブジェクトが待つ」。 何を待つか。おそらく状態の変化だ。

つまり、いずれも自身へのCPU割当を解除し、他Treadへ移譲するように JVMに指示するメソッドではあるが、 目的語があるかどうか、すなわち他と関連するかどうか、という点で異なっている。

synchronized

synchronizedは「オブジェクトにロックをかける」修飾子。 リソースにロックをかけて処理の原子性とリソースの完全性を担保する。 逆に言うと、synchronizedブロック外は(マルチスレッド環境においては) いつ何時他のThreadの処理が行われても構わない、ということになる。

組み合わせで考えてみる

synchronizedの有無とsleep/waitの組み合わせで考えてみる。

① synchronizedなしのsleep

よくあるパターン(かどうかはわからないが)。 単にちょっと待って他のTreadに何らかの処理をさせる。 他の処理の結果は、原則的に当該処理に影響が出ない。 まあinterrup()とかしたら別だけど…。

② synchronizedなしのwait

※ もちろん実際にはIllegalMonitorStateExceptionが発生する。 他の処理に何かを期待して待つ。 あるとき、自Threadが望んだ状態になる。 しかし、その後の処理を行って居る際に割り込みが発生し、望んだ状態でなくなるかもしれない。 それを防ぐには、synchronizedを使うしかない…。

③ synchronizedありのsleep

対象リソースはロックされているので、それが変更されることはないが 一時的に自身の処理を止めることは出来る。

④ synchronizedありのwait

自身が望む状態を他のTreadに作り出してほしい。 なので、ロック対象のオブジェクトを変更する許可を出す。

こんな感じ?

Facebookが自殺投稿前に検知するAIを初公開

自殺的な投稿に備えて全投稿を走査して、必要ならピンチな本人や友人にメンタルヘルス資材を送ったり、地域の初動対応者に連絡を取ってくれたりして、AIを使うことで人力よりも迅速に助力できるとか。

Facebook rolls out AI to detect suicidal posts before they’re reported


  • for:前置詞難しい。「備えて」か?
  • flag:旗を立てるという意味もあるけど、「合図する」
  • proactive:積極的な
  • artifical:人工の。artifical intelligenceでAI。

emmet.vimでhtml5のスニペット呼び出し

インストー

deinを使っているので、.vimrc

call dein#add('mattn/emmet-vim')

からの

:call dein#install()

html5スニペット展開

insert modeでここまで打って、

html:5

そのまま<C-y>,でどーん

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  
</body>
</html>

lang属性を"ja"にしたい

マニュアルに書いてある通りではなんだか出来なかったので、
こちらを参考にさせて頂きました。

.vimrc

let g:user_emmet_settings = {
\ 'variables' : {
\  'lang' : "ja"
\ }
\}

variablesがよく分からない。
VimScript特有のプロパティ名なのか(たぶん違うと思うけど)、
プラグイン特有のものなのか…。

Haskellことはじめのその1

漠然と、次に覚える言語は今使ってるJava(や、JavaScriptとかPerlとか)以外のパラダイムの言語にしたいなー
と思っていて、ぱっと思い浮かんだのがちょっと前にやけに流行っていた関数型言語

と、いっても関数型言語って結構あるし、どうしよう…。 Lispもいいし、仕事のこと考えるとScalaとか覚えるのもいいかも知れない…。

結論。

理由。

  • なんとなく

環境。

  • mac OSX 10.12.5
  • homebrew 0.9.9

Haskell Platformの公式っぽいところみたら、
普通にインストール方法について親切な記載が。
brewで書きたかったので、

$ brew cask install haskell-platform

でけたー。

$ ghci
GHCi, version 8.0.1: http://www.haskell.org/ghc/  :? for help
Prelude> 
Prelude>sum[1,2,3]
6
Prelude>

native修飾子を使ってみる(JNI)

javaの勉強を始めた頃に 存在を知ったnative修飾子。 java.lang.Systemのソースなどなど 結構使われていたので、ちょっと学んでみました。

以下をはじめ、いろんな情報源を参考にさせてもらいました。
link

そもそもnative修飾子とは

link

nativeのメソッドは一般的にCのような別の言語で書かれた プラットホームに依存するコードにて実装されます(超意訳)

プラットホームに依存した方が 高速な演算の実現は可能、だけど
一方で環境ごとのライブラリが必要になるから “Write once, run anywhere"の思想からは外れる。
まあ元々WORAは言うほどでもないそうですが。

JNIとは

link Javaネイティブメソッドを書いたり、 Java仮想マシンをネイティブアプリケーションに組み込む 標準プログラミングインターフェース。
JREに含まれてます。

とりあえず試してみる

Javaでnativeメソッドを書いてみる

package hoge;

public class Hoge {
  
  // staticイニシャライザ
  static {
    // 共有ライブラリを読み込む
    System.loadLibrary("<span style="color:#FF0000">HogeHoge</span>");
  }

  public static void main(String[] args) {

    Hoge hoge = new Hoge();
    hoge.call();

  }

  // natice修飾子を付与したメソッド
  // 処理内容は記載しない(interface的な感じ)
  public <span style="color:#FF0000">native</span> void call();

}

普通にclassを生成する

javac hoge/Hoge.java

classファイルからヘッダファイルを生成する

javah -jni hoge.Hoge

結果として、以下のファイルが出力される。

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class hoge_Hoge */

#ifndef _Included_hoge_Hoge
#define _Included_hoge_Hoge
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     hoge_Hoge
 * Method:    call
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_hoge_Hoge_call
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

実装コードを作成する

#include "hoge_Hoge.h"

JNIEXPORT void JNICALL Java_hoge_Hoge_call (JNIEnv *env, jobject obj) {
  printf("Hello, World!"); 
}

ライブラリを作る

僕の環境はMacOSXなのですが、 どうやらライブラリというのは各プラットフォームで色々違うようで。
例えば、WindowsだとDLL形式だとか、Linuxだとlib〜.soだとか。
このあたりは別途詳しく調べるとして、 Macだとdylibというらしいです。

gcc -shared -I /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/include -o lib<span style="color:#FF0000">HogeHoge</span>.dylib hoge_Hoge.c
  • sharedは共有ライブラリを作るオプション
  • -Iは使用するinclude対象を見に行く先。 今回は"jni.h"とそこから参照される"jni_md.h"が必要になるみたい。 find / -name “jni*.h"で探したけど、どうもJDKのinclude及びinclude/darwinにあるみたい。 sudo ln -sでinclude直下にjni_md.hのシンボリックリンクを作りました。
  • Macの場合、共有ライブラリはlib.dylibにしないといけないみたい。 そして、の部分がSystem.loadLibraryの引数になる、と…。

実行する

java -Djava.library.path=. hoge.Hoge

実行結果

hoge$java -Djava.library.path=. hoge.Hoge
Hello, World!%