miyasakura’s diary

日記です。

振り返り:2017年の仕事

使った技術とか振り返る。12月は(飲み会で)忙しくて書くの忘れがちなので思いったった今のうちに簡単にまとめる。

やったこと

  • 会計システムを作ってるところで常駐
    • 去年から引き続き
    • 使った技術: AWS全般, Docker, Scala, Java
  • スタートアップでiOSアプリ開発
    • 週2で2ヶ月という内容だったのであまり価値を残せなかった
    • Swift
  • Web系のインフラ構築
    • サーバ周りの知識やAWSの導入サポートなど
    • AWSとかXAMPPとか
  • Web系のアプリ開発
    • 緊急とのことで頼まれたので
    • PHP
  • なんかセブ島に語学留学に行ったらそこで知り合った人と組むことになった案件
    • 会社と絡んで進めている
    • Rails使ったり営業先についていったり
  • その他個人/チームで作っているもの
    • 2~3個
    • Rails, Node.js, Reactあたり

技術について

  • アプリ開発で言うと今までBtoCなものをやってきたせいもあり、設計とかどうでも良いと思ってた派なんですが、会計システムをいじってるとどうしてもビジネスロジックは複雑化するので設計とか大事だなとあらためて気付かされた
  • 言語としては Rails, Node, Java, Scala, PHP まで色々と触れたのは良かった
  • インフラ周りというかAWSはそれなりにわかってきた
  • フリーランス2年目でやっと技術について少し詳しくなってきた気がする
  • とはいえDDDもクリーンアーキテクチャ関数型プログラミングも自分の中であまり消化できていないので色々と課題がある

これから

少しずつ自分の向き/不向き・やりたい/やりたくないがわかってきたので、そろそろ何でもやってみるではなくて自分の方向性を決めていきたい。

Spring SecurityでAES暗号化された文字列をRubyで復号してみた

AESで暗号化されたテキストを手元で復号しようと思ったけど意外とAESのことを知らなくて苦労したので簡単にメモ。(勉強を兼ねて無理矢理RubyでやっただけでSpringで普通に復号すれば良いだけなので実用性は無いと思う。)

Spring Securityでの暗号化

こんな感じで暗号化されたもの。

package com.example.security;

import org.springframework.security.crypto.encrypt.Encryptors;
import org.springframework.security.crypto.encrypt.TextEncryptor;
import org.springframework.stereotype.Component;

@Component
public class Encryption {
    public String encrypt(String password, String plainText) {
        String salt = "0123456789abcdef"
        TextEncryptor encrypt = Encryptors.text(password, salt);
        return encrypt.encrypt(plainText);
    }
}

詳細な暗号化方式はと言うと、下記がドキュメントに書いてあった。

Spring Securityでは、共通鍵暗号化方式を使用した暗号化および復号の機能を提供している。
暗号化アルゴリズムは256-bit AES using PKCS #5’s PBKDF2 (Password-Based Key Derivation Function #2) である。
暗号利用モードはCBC、パディング方式はPKCS5Paddingである。

なるほど、わからん。Wikipediaとかみつつ方式について理解してみる。

  • 256は鍵の長さで、128, 196, 256から選べるうち256bitのものを使っている。鍵の長さが長いほうが(計算量が多くなるので)セキュリティ的に良い
  • 暗号利用モードとはブロック暗号化のメカニズムのことでCBC(Cipher Block Chaining)は前のブロックのXORを取ることでブロック単位での一致を判定することをできなくする
    • CBCの初期ブロックはIV(Initialization Vector:初期化ベクトル)を用いることでメッセージごとのユニーク性を確保する
  • PKCS #5は[暗号化]ブロック暗号とは(AES/DES/Blowfish PKCS5Padding ECB/CBC IV) - [技術資料 + 技術資料] ぺんたん info によると余ったブロックをどう埋めるかという方式
  • PBKDF2というのはパスワードから何かしらの鍵を生成するときに計算量を増やして総当りをしづらくする方式とのこと。パスワードとソルトを使ったハッシュ化を複数回イテレーションすることで実現する。
    • ハッシュ化の繰り返し回数はパラメータぽい

それぞれはわかったので全体の処理の流れを調べると Closure Library の暗号化モジュールの使い方 - WebOS Goodies この図がわかりやすかった。

saltとpasswordからpbkdf2を使ってkeyを生成 → 平文データをIVとkeyを使ってCBC方式によりブロック単位にAES暗号化 という流れ。

復号化にあたっては暗号化の方式がわかった上で、

  • 復号対象のテキスト
  • PBKDF2の
    • 繰り返し回数
    • Salt
    • Password
  • CBCのIV

がわかれば良さそう。上記の内、Spring Securityで外側から指定しないのは繰り返し回数とIVなのでこれが分かれば他の環境でも復号はできるはず。

Spring Securityのパラメータを調べてみる

Ruby で復号する

これらを踏まえてRubyで復号してみる。 class OpenSSL::Cipher (Ruby 2.6.0) を見つつ実装すると下記のようになった。

pack関数でバイト列に変換してあげないとダメだったところでややハマった。

require 'openssl'

salt = ['0123456789abcdef'].pack('H*') # 8バイト
password = 'somepassword'  # 暗号化時に入力したパスワード
cipher = '7bc2a6f8e684a2963285064524a0f85fb3b47bc6300c699699fe99387a9f7b10' # Spring Securityから出力された文字列

# PBKDF2によるkeyの作成。256は鍵の長さ。
key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(password, salt, 1024, 256)

# IVを取り出す(16バイトだがhex文字列になっているので32文字)
iv = [cipher[0, 32]].pack('H*')

# AESによる暗号文本体
encrypted = [cipher[32, cipher.length]].pack('H*')

dec = OpenSSL::Cipher.new("AES-256-CBC")
dec.decrypt
dec.key = key
dec.iv = iv

decrypted = dec.update(encrypted) + dec.final

puts(decrypted)

ちなみにSpring Securityと同等の暗号化をRubyでしたい場合はこんな感じ。

require 'openssl'
require 'securerandom'

salt = ['0123456789abcdef'].pack('H*')
password = 'somepassword'
text = 'hirabun'

key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(password, salt, 1024, 256)
iv = SecureRandom.random_bytes(16)

enc = OpenSSL::Cipher.new("AES-256-CBC")
enc.encrypt
enc.key = key
enc.iv = iv

encrypted = enc.update(text) + enc.final
cipher = (iv + encrypted).unpack('H*').first

puts(cipher)

感想

AES本体のアルゴリズムには踏み込んでいないものの、それでも結構知らない部分が多かったので勉強になった。ちなみにSpring SecurityのAES暗号時にはstrongという指定できるようでそちらだと AES with GCMとなって今回のCBC方式とは違うらしい。

何となくわかったつもりでブログにまとめようとしたら意外と理解していない部分が多かったので調べ直した部分も多く、やはりこういうアウトプットは大事だなぁと改めて思った次第です。

LINE WAVE先行体験版の雑感 - Amazon Echo、Google Homeと比較して

先日LINE WAVEが無事届きました。同じスマートスピーカーであるAmazon Echo, Google Homeの両方を持っているので相違点を中心に感想をまとめました。

EchoもHomeも年内には日本語対応してくるみたいですが、まだ英語でしか使えていないので、その点をご注意ください。

f:id:miyasakura:20170903110043j:plain

※写真一番右はAI搭載英会話学習ロボットのMusioさんです

LINE WAVEでできること

今はまだ音楽再生と天気予報とアラームくらいです。ニュースを流そうとすると「いま準備をしています」となるので、これから色々進化していくことでしょう。

Amazon Echoは自社サイトでのショッピングができたり様々なSkillで拡張できたり、Googleは自社サービスとの連携(Googleカレンダーの予定を読んでくれたり)が簡単だったりという特徴があると考えると、LINE WAVEも独自性をどう出していくか気になるところです。

ハードウェア周りについて

電源コネクタが刺しづらくかなりしっかり入れないと充電がされないのがいただけないところです。最初電源ケーブルがちゃんと入ってなかったようで、充電がされない状態でした。その後ちょっと移動させたタイミングでまた半分抜けてしまっていたようで朝になったら電池ゼロで落ちてしまいました。

大きさについては最初の印象は"でかいな"と思いました。高さはAmazon Echoより小さいですが幅を取っています。バッテリーがあるのとスピーカーに良いのを積んでいるのもあるのでしょうが、製品を小さくするコストは想像以上なんだろうなと勝手に思ってます。

赤外線で家電を操作できる機能はまだ試せていませんが、便利に使えそうで期待です。それよりも日本の家電メーカーがさっさとWifiBluetoothで操作できる機能をつけて欲しいと思うわけですが。赤外線での操作に満足しているとまたガラパゴス状態になる気がします。

物理ボタンが裏側に電源ボタンとマイクオフボタン、あと上部に6つの操作ボタンがあります。ボリュームの上げ下げと曲送りがあり、残り3つはショートカットキーを設定できる予定のようですが現在は固定で、プレイリスト再生と「クローバ」の呼び名を省略して音声操作できるというものです。

他製品は電源とマイクオフ、ボリューム操作くらいしか物理で操作するものはありません。必要ないと思うんだけどなぁ。。。まぁスマートスピーカーというよりは音楽再生ガジェットとして物理ボタンをつけたということでしょう。

ソフトウェア周りについて

Amazon Echo, Google Homeと比べると、応答が1秒程度遅いです。2製品は2秒弱程度で応答が始まるのに対し、WAVEは3秒弱かかります。この差は実際に体験してみると大きな差です。

Amazon Echoの開発時にベゾスは応答速度3秒以内を実現しろといってかなりこだわったらしいです。

そのラインは達成しているので使用感として大きく不満ということは無いのですが、普段Google Homeを使っていてその速度に慣れていると明確に「遅い」と体感できる差があります。

日本語の処理部分については、呼びかけても反応してくれなかったり、クラシック音楽を再生してほしいのに「クラシック」という名前の曲を再生したりもどかしい思いをすることがままありますが、日本語特有の難しさもあると思うので、ここは英語対応の他製品と比較しても仕方ないですね。

理解できない内容についても人工知能がなんとか答えようとしてくれます。他製品は「Sorry, I couldn't help with that.」と答えるところを、「私もそう思います」みたいな会話をしようとしてきます。

こういったところは個人的には求めていないのですが、日本市場には受けそうな気もするのでGoogle Homeなどとの戦いになったときに消費者がどちらを選ぶのかは気になるところです。

とはいえ人工知能自然言語を理解して会話ができるようになるには技術的なブレークスルーが必要なわけで、どんな内容にも答えさせようとするのはまだ時期尚早じゃないかなとは思います。

Clovaアプリについて

ここは流石LINEといったところで最初からクオリティ高いですね。とはいえ普段からClovaアプリを使うことも無いので、これが良いからといって製品の評価がすごく上がるというものでも無い気はします。

LINE WAVEという製品について思ったこと

これから出てくるであろう他社製品との差別化というところで、LINEの新着を教えてくれたりとか、お気に入りのLINE LIVEの時間を知らせてくれたりとか、今後はそういったLNIE製品群を活かしたパーソナライズに強みを持てると思います。

ただそうなるとあまり他人がいる状況で使うことが考えられず、持ち出して使うケースが少なくなって、バッテリーのメリットが無くなってしまいます。

という感じで、家に置いといてほしい製品なのか、持ち出してどこでも使って欲しい製品なのかがよくわからない製品だなぁというのが正直な印象です。

個人的にはスマートスピーカーは家においておき、ニュースを聞いたり予定を確認したりと、アシスタントとして使うものだと思っていて、補完的な製品としてAmazon Tapのような持ち運び用途のものを出すのが正しいかなと。

色々詰め込むと値段も高くなりますしサイズも大きくなって良いこと無いですからね。

「ホームアシスタント」「どこでも便利に音楽再生」という二兎を追ってしまった感じがあるので、これが吉と出る凶と出るかといったところです。

おわりに

スマホがあっても家でインターネットするならPCでいいじゃんと思っていたら、今となってはPCを立ち上げるのが面倒でスマホを使っています。同じように音声操作の便利さを一度覚えてしまうと、スマホを立ち上げるのすら面倒になって当たり前のように音声操作を使うようになっていくのではないでしょうか。

そういう意味で一家に一台スマートスピーカーという時代は来ると思っていて、それをどの製品が実現するのかという行方が気になります。

今回のLINE WAVEはそういうスマートスピーカーというジャンルに直球勝負を挑むのではなく、音楽再生というところに寄せてきている印象を受けました。

新しいジャンルではあるので一般消費者に受け入れやすいように敢えてそうしたのか、それとも直球勝負だとGoogleなどのプレーヤーに勝てないと判断したのかはちょっとわかりませんが、今後の進化の方向性に注目です。

写真とか

いくつか写真をとったので最後に貼り付けておきます。

f:id:miyasakura:20170903110621j:plain

外箱

f:id:miyasakura:20170903110635j:plain

内箱

f:id:miyasakura:20170903110646j:plain

開けるとこんな感じ。

f:id:miyasakura:20170903110700j:plain

サイズ比較。

f:id:miyasakura:20170903110712j:plain

後ろ側に電源ケーブルを挿すところと電源ボタン。

f:id:miyasakura:20170903110723j:plain

電源入れると光る。

f:id:miyasakura:20170903110737p:plain

アプリの接続画面。

一ヶ月のセブ島留学振り返り

現在フリーランスのエンジニアをやってますが、取引先の方たちに仕事をしたくないという思いを日頃から伝えていたら、一ヶ月ほど仕事をしない期間を設けることができました。

せっかくの休暇ですが、休むだけだともったいないということで、バカンスを楽しみつつ英語もしゃべれるようにという一石二鳥を目指してみようと思い、セブ島留学に申し込みました。

帰国後は、話す能力はともかくリスニングはできるようになった実感はあったのでTOEICを受けてみたところ過去最高得点を記録。思ったより嬉しかったので、他の人の参考になるかもというのもあり留学についてまとめてみました。

留学とTOEICスコアの概要は下記のとおりです。

  • 6/4〜7/1の4週間で平日毎日8時間授業
  • 5年くらい前まで何度か受けてたTOEICスコアは最大855で平均830くらい
  • TOEICを7/23に受けて930だった

上記の通り、スコアは留学前後で比較したわけではなく、最後のTOEICスコアは5年前とかそんな状態なのでやや盛り気味のタイトルなのですが、実感として英語力は上がったなと感じています。

セブ留学振り返り

準備と手続き

School Withというサイトを使いました。セブ留学というキーワードで一番上にAdwords広告があったとかそんな理由だったと思います。他は知らないですが、特に不満はなく使えました。

4/8に見積もりをしてから希望のところが埋まっていたり電話相談をしたりで申込みが4/14でした。海のそばでゆっくりしたいというのが大きかったので、QQEnglishのシーフロント校を選んでいます。そこは比較的豪華な部屋があるのが特徴で、オーシャンビューのエグゼクティブルームが希望だったのですが、6月という閑散期でも埋まってしまっていてデラックスルームしか取れませんでした。

渡航準備は通常の海外旅行だといつも前日にやるのですが、今回は3日前くらいから準備を開始してみましたが、普通の旅行と比べて特別なものといえば証明写真とトイレットペーパーくらいだったと思います。自分は普段使ってるリュック一つに荷物がまとめられたのでそれだけで行ったのですが、周りからはだいぶ驚かれてしまいました。数週間以上いるようなほとんどの人は一番大きいキャリーケースを持ってきてたと思います。

Tシャツなどは現地で買えば良いと思って3日分くらいしか持っていきませんでした。現地だと普通のモールで靴下4足で300円とかTシャツ1枚200円とかそんな値段でしたので5日分ほど買い足しました。

現地について

通信手段

いわゆるSIMフリースマホを持っていくと、空港でSIMカードを買ってスマホをどこでも使えるようになります。学校などWifiが通じる環境だけスマホを使っている人も多かったですが、学校のWiFiも人が多いと使いものにならなくなるのでLTEで通信した方が快適でしたし、出歩くときも地図があるのは安心です。

プランは色々ありますが、SMARTという会社の30日4000円くらいで使い放題というものにしました。

移動手段

移動は色々な手段がありますが、UBERが一番楽でした。同じタクシーの配車だとGrabというのもあるのですが、言葉が通じない人だと認識されると強制キャンセルされるのがよくあるので、基本はUBERが良いのではないかと思います。

お金

両替ですが、両替所だとレートはそれほど良くないですが、ATMのキャッシングだと200ペソの手数料がかかるので、結果どっちでもそれほど変わらないかなという印象。一ヶ月で学校の諸費用の支払いを含めて10万円分くらいペソを使った気がします。

たびレジ

外務省の旅行者登録のシステムがあるので一応登録しておきましょう。危険情報とかが流れてきます。セブ島は現在危険度1ですが意外と近くでテロが起こる可能性もある国なので、自分の身を守るのは重要になってきます。

QQEnglish シーフロント校について

ざっくりとした感想をば。見返してみたら不満のほうが多くなってしまいましたが、値段と質のバランスを考えると優秀な学校だと思っています。

  • リゾート感はなかった
    • 学校をでるとごちゃごちゃしてる町だったので海沿いを歩いてゆっくり過ごすみたいなのができなかった
  • 大きな不満は無いものの、サービスの質は高くはない
    • 食事は悪くはないが美味しくもない
    • 到着初日の飯が食べれなかったり、社長の誕生パーティの準備で授業を代替の先生にする先生が居たりという
    • 経営方針からしてここから劇的にサービスが改善していきそうな雰囲気はない
  • 先生の質は総じて高かったと思う
    • 間違ったことを教えられたり発音が特殊だったりはきっとどこも一緒
    • 新人は多かったので合わなかったらすぐに変えたほうが良さそう
  • その他
    • ネットワーク環境は良くない。夜などアクセスが多いときはWifiが繋がらなくなることがよくあった
    • 基本一人で食事をしていたら毎回先生に絡まれて面倒だった
    • 洗濯は自分でやらず校舎でやっているクリーニングを頼んでいたが、3日後に完了するプランと翌日プランがあり、翌日プランだと普通に高かった。一週間分の洗濯物で600ペソ(1,200円)くらい

遊び

一人の悠々自適感を満喫したかったのであまり人と関わらずに行こうと思っていたのですが、なんだかんだバッチメート(同じ日に来た人)と仲良くなって遊びにいったり楽しんでました。

4週間居ても土日は3回だけなのでセブを満喫したい人は最初から計画をしていったほうが良さそうです。学校内にツアーカウンターがあるので簡単に申し込めてどこでもいけますが、人数が集まらないと少し高めなので自力で行ったり現地民と交渉したりで安くしている人が多かったです。

自分の場合は最初の土日は一人でセブシティをブラブラと、次の土日はボホール島のツアーに、最後の土日はアイランドホッピングに行きました。

平日に休んで遊びに行ってる人も見かけましたが、そこは留学の目的次第かなぁと思います。

英語の勉強について

セブ留学前

今年の1月〜3月くらいは「英語耳」という本を使って発音練習をしていました。いくつか発音の本は買いましたが、唯一やる気になって続いたのが英語耳だけでした。

それ以外では留学前の1ヶ月ほどはSafari Books Onlineのビデオをたまに見たりして英語に慣れるようにしていました。

セブ留学中

最後になるほどだれてしまいましたが、おおよそ下記のように勉強していました。

  • 授業を真面目に受ける
  • 復習を1時間ほど
  • 1〜2時間は単語の勉強と技術系のビデオを見る
  • やる気が無いときはhapa英会話のYouTubeビデオを見る
  • 休日は頑張らない
  • 特に授業以外で外国人とコミュニケーションは取らなかった

1週目で耳が慣れてきて、2週目になると質問の文章を使ってフルセンテンスで受け答えができるようになるとともに、先生たちの英文法が意外と適当だなと気がつけるようになってきました。3週目くらいは"聞き取れるようになった"と"やっぱり全然だなぁ"を繰り返していました。4週目になると聞き取りが大分いい感じになってきましたが、喋るのはまだまだ全然と言った感じで帰ってきました。

良かった点、悪かった点

文法、発音がちゃんとできている状態でいったので、先生たちに褒められることも多く、吸収速度は早かったのではと思います。

ただ最後の方は復習はほぼしないようになっていたので、せっかくの授業の意味が半減してしまったかなと思います。

1ヶ月だと喋れるようになるというのはかなりの難易度のようで、3〜6ヶ月程度の期間がないと思ったことを話せるようになるのは難しそうです。

英語を話せるようになることが目標という場合は、もっと長期の留学をするか日本でも英会話の勉強を続けるのが必要です。

おわりに

ゆっくりとリゾートを楽しみたいという目的に対しては、平日毎日授業をやっていて正直普段より疲れる一ヶ月間でした。

英語も一ヶ月では期待してたほど喋れるようにはなりませんでしたが、リスニング、特にTOEICの点数という点で向上が見られたのは期待以上でした。

英語のプロっぽい点数を取ってしまい、これで英語ができないのは良くないので、気を引き締めて勉強を続けていかないとなぁという次第です。

読んだ:「スタンフォード式 最高の睡眠」

スタンフォード式 最高の睡眠

スタンフォード式 最高の睡眠

内容は薄い、というか先端研究をしててもこういう本で紹介できる程度の内容は多くないので冗長な記述で無理矢理一冊にしたという印象。

しかしもちろんスタンフォードでの研究者の方の本なので読んで損はない一冊でした。

基本的には深部体温と皮膚温度の関係で眠くなり最初の90分で睡眠の質は決まる、ということ。

コーヒーは飲んじゃだめと言われるかと思ったら普通に夜じゃなければ大丈夫そうで安心したのと、やはり睡眠の深さを測るアプリは研究者的には信頼度は低いなぁというのが印象的だった。

風呂に入る時間などすぐに実践できそうな内容はあったので実行していきたい。

AWS認定(アソシエイト)試験 合格しました

先月末にデベロッパー試験に合格したので、その勢いでソリューションアーキテクトとSysOpsアドミニストレータを受けてきました。

aws.amazon.com

2週間ほど前から試験日を予約していたので、急に入った仕事を1日断ることになってしまったこの試験。x万円の収入分と試験2つの費用が3万円で実質的にかなりの出費です。

今回もほぼ勉強せずでしたが、一応いくつかのホワイトペーパーに軽く目を通しました。

AWSのホワイトペーパーは初めて読んだのですが、かなり勉強になる内容が多いので試験関係なくちゃんと読んでおきたい資料だなと思いました。

ただ、分量が多いので一つの資料の前半くらいしか読みきれず試験に挑むことになったわけなのですが、一応試験は合格。

結果的にはどの試験もスコアが80%超えていたので自分の知識に一安心です。

SysOpsは始まったばっかりなのか合格証の番号がJP-897と若めで、ソリューションアーキテクトは JP-6614 なのでかなりの人が取ってるみたいです。

次はプロフェッショナルを目指して頑張ります。

DockerでRails+Wheneverによるcron実行

cronは cron -f で動かせるが、環境変数が引き継がれないので期待した動作をしてくれない。少しやり方に悩んだので解決方法をメモ。

Wheneverはenvを記述することでcrontab内に環境変数を定義してくれるのでそれを利用した。結果としては下記のようになった。

ENV.each{|k,v| env k.to_sym, v}

every 2.minutes do
  rake 'something:do'
end
#!/bin/bash

bundle exec whenever --update-crontab

LOG_FILE=$(dirname $0)/../log/production.log

touch ${LOG_FILE}
cron && tail -f ${LOG_FILE}

Dockerfileは通常通り作成し、cronを実行するコンテナとして動かすときだけ明示的にコマンドを指定する。

docker run -d <image> docker/cron.sh

以上でコンテナ実行時の環境変数をcronに渡すことができる。実行ログについてはDockerなので標準出力に出すようにした。Rails側で標準出力してもcronがそれを出力してくれるわけではないので、ファイルに出力したものを明示的にtail -fしている。