BigIntegerの素数生成メソッドprobablePrimeはどの程度素数生成をミスるのか。

BigIntegerにこんなコンストラクタがあります。

public BigInteger(int bitLength,
int certainty,
Random rnd)

ランダムに生成された (おそらく素数である) 正の BigInteger を、指定したビット数で構築します。
確率を指定する必要がない場合は、このコンストラクタではなく probablePrime メソッドを使用することをお勧めします。

パラメータ:
bitLength - 返される BigInteger のビット長
certainty - 呼び出し側が許容しない確率の尺度。新しい BigInteger が素数である確率は、(1 - 1/2^certainty) より大きい。このインストラクタの実行時間はこのパラメータの値に比例する
rnd - 素数度をテストする候補の選択で使用されるランダムビットのソース

「ランダムに生成された (おそらく素数である) 正の BigInteger」
このおそらく素数ってのが気になります。

中で何をやっているのかとソースを追っていくと「isProbablePrime」という関数でミラーラビン素数判定法を使って素数チェックをしていると分かります。
Source for java.math.BigInteger (GNU Classpath 0.95 Documentation)


ミラーラビン素数判定法についてはWikiでも読みましょう。
ミラー–ラビン素数判定法 - Wikipedia


で、実際どれぐらいミスるのかというのですが「素数である確率は、(1 - 1/2^certainty) より大きい」といわれても実感わかないなーとおもったのでやってみたら
certaintyが1の時でも20万回~50万回に1回ぐらいしか失敗しなかった。。

デフォで使うとcertaintyは100なのでほぼほぼ素数といって問題なさそうですね。

Proxy環境下でnodeをインストールする時はnコマンドに注意。

Proxy環境下でUbuntus にnodeをインストールする際にnコマンドを使うと
途中プロキシを使ってくれないことがあるので注意しましょうというお話。

途中のnコマンドのエラーがこんなのがでて、何が原因かぱっとわからず時間がかかってしまった。

$ n stable
cp: '/usr/local/n/versions/node//bin' を stat できません: そのようなファイルやディレクトリはありません
cp: '/usr/local/n/versions/node//lib' を stat できません: そのようなファイルやディレクトリはありません
cp: '/usr/local/n/versions/node//include' を stat できません: そのようなファイルやディレクトリはありません
cp: '/usr/local/n/versions/node//share' を stat できません: そのようなファイルやディレクトリはありません

ぷろきしなんて大嫌いだ!

正しい手順はこちら。

$ sudo apt-get install -y nodejs npm
$ sudo npm -g config set proxy http://proxy:8080
$ sudo npm -g config set https-proxy http://proxy:8080
$ sudo npm cache clean
$ sudo npm install n -g
$ sudo su
# export  http_proxy=http://proxy:8080
# export https_proxy=http://proxy:8080
# n stable
# ln -sf /usr/local/bin/node /usr/bin/node
#node -v
v7.2.1
# npm -v
3.5.2


半年前の自分に助けられるとは。。。。。
garapon.hatenablog.com

OpenIDConnectとOAuth2.0

OpenIDConnectとOAuth2.0について調べてみた。

端的にまとめると、

  • OpenIDは紹介状で、OAuthは合鍵」
  • OAuth2.0のImplicit Flowはトークン置き換え攻撃のリスクがあるのでそんな時はOpenIDConnctを使いましょう

OpneIDによる認証

公証人(Identity Provider。Google等)に紹介状を書いてもらい
自分が自分である事を証明する。
氏名とメールアドレスに署名を打つイメージ

OAuthによる身分確認もどき

Oauthサーバ(Twitter等)は認証情報ではなく、合鍵を渡す。
合鍵で入れるから相手が本人だと理解する。
⇒合鍵を渡していることになり非常に危険

OpneIDConnectによる認証

家の合鍵ではなく紹介状のコピーの入っているロッカーの鍵を渡す。
受け取る側のフローはOAuthと同じ。しかし家には入れない。
またそのロッカーをUserInfo Endpointと呼ぶ。
「どういう認証(身元確認)をしたのか」などの本人の身元確認についての情報(メタデータ)をUserInfoロッカーの鍵と一緒に、紹介状にして送ります。
ここで送られてくる紹介状のことを、OpenIDトークンといいます。

OAuth2.0の問題点

クライアントシークレットを安全に保存できないImplicit Flowにおいて「トークン置き換え攻撃」が成立してしまいます。
アクセストークンだけでユーザ認証を行おうとしていることがだめなのですが、これはOAuth自体の問題ではありません。
認可のプロトコルであるOAuthをつかって認証もどきをおこなっているところが諸悪の根源です。

詳しくは以下ページにまとまっています。
単なる OAuth 2.0 を認証に使うと、車が通れるほどのどでかいセキュリティー・ホールができる | @_Nat Zone


なお、理解するに当たって「OpenIDは紹介状で、OAuthは合鍵」であるという概念を理解しておくと非常に頭に入りやすい。
紹介状ではないので、別の合鍵を渡してしまえば検証できないということです。
非技術者のためのOAuth認証(?)とOpenIDの違い入門 | @_Nat Zone
ちなみに↑の崎村さんはOpenIDFoundationの理事長。どうりで分かりやすい。

問題の悪さ部分については以下のスライドも分かりやすい
Idcon11 implicit demo

対策

まあすでに上記のページで色々解説がされておりますが、OpenIDConnectを使うといい。
なぜかというとアクセストークンが置き換えられたとしてもIDトークンと合致しないので不正を検出できます。

まあつまり、認証は認証で認可は認可でちゃんとやりましょう。

その他

OepnIDConnectがどうして今の形式になったのかというのが以下にまとまっていた。
既存のユーザたちが出来るだけ影響少なく考えた結果こうなったのですね。
OpenIDファウンデーション・ジャパン — OpenID Connect, ふたつのトークンの物語

ショートカットを書き換えるスクリプト

ファイルサーバが移行してファイルサーバのパスが変わったとか理不尽なことをいわれたので
ショートカットを書き換えるスクリプトを書いた。
書き方がVBSっぽくないのはきにしちゃだめ。

使い方

L3.4の "\\beforeserver\share" が "\\afterserver\share" に変わることになるので必要に応じて書き換えて下さい。

以下ソースを任意のフォルダに「ショートカット書き換え.vbs」などの名前で保存をして書き換えたいショートカットを複数選択してドラッグアンドドロップしてください。
ファイルを置き換えるので事前にバックアップを取っておくことをオススメします。

Option Explicit
 
'ここを書き換える
Const OLD_LINK = "\\beforeserver\share"
Const NEW_LINK = "\\afterserver\share"
 
Call Main()
 
Private Sub Main()
   Dim objFileSys
   Dim filePath
    
   Set objFileSys = CreateObject("Scripting.FileSystemObject")
    
   For Each filePath In WScript.Arguments
      If objFileSys.GetExtensionName(filePath) = "lnk" Then
         Call Rewrite(filePath, objFileSys)
      End If
   Next
   Wscript.Echo "完了"
    
End Sub

Function Rewrite(filePath, objFileSys)
   On Error Resume Next
 
   Dim wshShell
   Dim targetShortcut
   Dim targetPath
   Dim newLink
    
   set wshShell = CreateObject("WScript.Shell")
   set targetShortcut = wshShell.CreateShortcut(filePath)
   targetPath = targetShortcut.TargetPath
  
   If UCase(Left(targetPath,Len(OLD_LINK))) = UCase(OLD_LINK) Then
      newLink = Replace(targetPath,OLD_LINK,NEW_LINK,1,1,1)
      objFileSys.DeleteFile filePath
      set targetShortcut = wshShell.CreateShortcut(filePath)
      targetShortcut.TargetPath = newLink
      targetShortcut.Save()
      'Wscript.Echo "書き換えたよ" + targetShortcut.TargetPath
   End If
   If Err <> 0 Then
      WScript.Echo "PATH:" & filePath & " [" & Err.Number & "][" & Err.Description & "]"
   End If
End Function

注意点

当初ネットに転がっていたものを流用しようとしたのだが、Win7ではうまく動かなかったので
ショートカットを一旦削除して再作成するように変更した。
また再作成しているが、引き継いでいるのは「TargetPath」だけなので作業フォルダとかショートカットとか設定している場合は消えてしまうので注意が必要。

プレゼン資料の作り方。

プレゼン資料の作り方研修を受けてきたらこれがなかなか良い研修であった。

・何故相手の心に刺さるプレゼンにならないのか。
・何故話がぶれてしまうのか

といった課題についてよい解決策を提示してくれていた。

忘れないように大事なところを自分でメモメモ。

プレゼンをつくる流れ

骨子を作る

骨子は相手がきになることで構成される。
そのため相手になったつもりでとにかく付箋に質問を書き出してみる。
そしてそのQに対するAをシンプルに同じ付箋に記載する。

ここでは相手の立場になって考えることが大事。
相手の立場で考えにくければ似たような立場の人に実際にヒアリングすると良い。

ストーリーを作る

骨子で出来たQとAを並びかえてストーリーを作る。
Q⇒A の連鎖でストーリーが出来るはず。またその途中で重要でないQは捨て、必要に応じてQを追加する。

各スライドを作成する

各スライドは1つのQに対応するように作成する。
各スライドの中はQである「論点」Aである「メッセージ」その理由でありサブメッセージである「Body」で構成される。

プレゼン実施

上記ながれでプレゼンを作成していれば論点もメッセージも明確になっている。

Q&A

最初の骨子で考えつくせていれば想定外のQAがくることは限りなく少なく出来る。
またQAは以下の流れで実施する。なぜならQAの質問は表面的事象を捉えて質問されることが多く、真の事象を探る必要があるからである。
1、真の論点を確認(復唱or言い換え)
2、答える
3、答えになっているか確認する

終わり

これで相手の関心事からスタートしたプレゼンが出来る。

IMEのENとJPの切り替えショートカット


IMEがふとした瞬間にENに切り替わってしまっていてマウスで直さないといけなくて不便だとおもっていたらショートカットで直せた!

[Alt] + [Shift] で切り替えられる

こりゃ便利だわー
今までなんで調べなかったんだろうか。

ちなみに[Ctrl] + [Shift]でIMEGoogle日本語入力 とか使用するIMEも切り替えられる。

SwaggerでAPIを定義してモックアップを作る

REST APIの仕様定義には色々ありますが、Open API Initiativeでも標準ツールとして採用されている SwaggerをつかってAPI仕様を記載しモックアップを作ってみましょう。
Swaggerはユーザが多いのもあって周辺ツールの充実と多言語対応が良いので今から採用するならオススメです。

Swagger.yamlAPI仕様を記述する。

SwaggerではAPIの仕様をswagger.yamlで記載しますが、
swagger-editorというツールが非常に便利です。
ツールとしてインストールも出来ますし、オンラインでも使えます。
http://editor.swagger.io/#/

まずはこんなyamlを書いてみます。

swagger: '2.0'
info:
  version: "0.0.0"
  title: サンプル api
# Describe your paths here
paths:
  # This is a path endpoint. Change it.
  /users:
    get:
      description: |
        メンバ一覧取得API.
      parameters:
        -
          name: size
          in: query
          description: Size of array
          required: false
          type: number
          format: number
      responses:
        # Response code
        200:
          description: ユーザデータ(List)
          schema:
            title: ArrayOfUsers
            type: array
            items:
              $ref: '#/definitions/User'
  /users/{id}:
    get:
      description: |
        メンバ取得API.
      parameters:
        -
          name: id
          in: path
          description: user id
          required: true
          type: number
          format: number
      responses:
        # Response code
        200:
          description: ユーザデータ
          schema:
            $ref: '#/definitions/User'
definitions:
 User:
  type: object
  properties:
    id:
      type: number
    name:
      type: string
    age:
      type: number

簡単に言うと、
「/users」で一覧が取得できて
「/users/{id}」でUserID指定のデータが取得出来るというものです。
またdefinitionsのところでUserデータ型を指定しています。

ソースの生成

これで、Springのソースを出力してみましょう。
SwaggerからはNode、GoServer、JAX-RSPythonRails等色々な言語の実装を自動生成できますが、SpringBootだと起動が楽なので今回はSpringでいきます。
「Generate Server」から「spring」を選ぶと出来たソースがZipで落ちてくるので解凍するとMavenプロジェクトになっています。
もうこれでサーバの基礎は動きます。
楽勝ですね。

それでは動かしていきます。
まずはPomを開いて42行目あたりの「provided」行を削除しましょう。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>       ←この行削除
        </dependency>

レスポンス内容をそれらしく作る

Swaggerで生成されるモックはレスポンス内容は空っぽで生成されます。
なのでレスポンス内容は自分でモックコードを書く必要があります。

ソースの中のio.swagger.api.UsersApiControllerを開いて「// do some magic!」と書かれているところにモックコードをこんな感じで書きます。

@javax.annotation.Generated(value = "class io.swagger.codegen.languages.SpringCodegen", date = "2016-11-08T06:41:55.099Z")
@Controller
public class UsersApiController implements UsersApi {
    public ResponseEntity<List<User>> usersGet(@ApiParam(value = "Size of array") @RequestParam(value = "size", required = false) BigDecimal size
    ) {
        // do some magic!
        User user1 = new User();
        user1.setId(BigDecimal.ONE);
        user1.setName("aaa");
        User user2 = new User();
        user2.setId(BigDecimal.TEN);
        user2.setName("bbb");
        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        return new ResponseEntity<>(list,HttpStatus.OK);
    }

    public ResponseEntity<User> usersIdGet(@ApiParam(value = "user id", required = true) @PathVariable("id") BigDecimal id ) {
        // do some magic!
        User user1 = new User();
        user1.setId(BigDecimal.ONE);
        user1.setName("aaa");
        return new ResponseEntity<>(user1, HttpStatus.OK);
    }

これでOK。
あとは起動して、「http://localhost:8080/」にアクセスすればSwaggerUIがみれます。
f:id:GARAPON:20161108172530p:plain

TryItOutをおしてみると
f:id:GARAPON:20161108172537p:plain

こんな感じで動いていますね。