stepnを初めてみた。強制ウォーキングツール
テレワークで2年間家から出ていない。 そして2年間歩くことすらしていない。 日々腰が悪くなっていくのを実感する。 健康診断は経過観察から要注意になった。
ということで、強制的に運動(ウォーキング)するハメになる最恐アプリ、STEPNをインストールしてみた。 STEPNは仮想通貨界隈で俄に人気のWeb3.0のランニングアプリだ。
初期投資は17万程度だった。 STEPNを始めるには仮想通貨、Solana(ソラナ)が必要になるのだが、 休日に急にやりたくなったので、Binanceでクレカ決済でBitcoinを購入し、 Bitcoin建でSolana取引(Solanaが直接クレカで買えることを知らなかった)をするというわけがわからないことをしてしまった。 しかもSolana取引で最小取引ロットに届かないとかっていうエラーが出て、無駄にBitcoinを買ってしまうというアホっぷり。 そのおかげで当時9万程度のスニーカーを買うのに17万支払い、4SOL残るという状態からスタートした。
今日初めてちゃんとフルエネルギーの状態でウォーキングできて、大体20分くらいで2700円程度のコイン獲得。 毎日歩かなければ投資分が無駄になってしまうので、今後も強制的に歩くことになる。
初期投資 170,000 / 1回の大体の利益 2,500 = 68回か。
とりあえずはあと67日、がんばろう。
Javaでopenssl準拠のaes128cbc暗号化
AES128の暗号化って何かと使う機会あるんだけど、InitialVectorの扱いとかどうしようとかいろいろ悩んでいたんだけど、opensslのアルゴリズムパクればいいんじゃね!?と閃いた。
どうせ暗号化するなら、互換性もあったほうが気分的にいいしね。
package sample; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.CipherOutputStream; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; /** * AES128,CBCモードで暗号化/復号するためのUtil<br> * opensslの実装に準拠している * <pre> * 【暗号化】 * $ openssl aes-128-cbc -e -in rawtext.txt -out encrypted.txt * 【復号】 * $ openssl aes-128-cbc -d -in encrypted.txt -out decrypted.txt * </pre> * * @author test * @version 1.0 * */ public class AESCryptUtil { /** saltのバイト長 */ public static final int SALT_BYTE_LENGTH = 8; /** 暗号化Keyのバイト長 */ public static final int KEY_BYTE_LENGTH = 16; /** IVのバイト長 */ public static final int IV_BYTE_LENGTH = 16; /** キャッシュのバイト長 */ public static final int BUFFER_BYTE_LENGTH = 1024; /** 暗号化ファイルの先頭に付与するbyte値 */ protected static final byte[] HEADER_BYTES = "Salted__".getBytes(StandardCharsets.UTF_8); /** 不可視のコンストラクタ */ private AESCryptUtil() { // インスタンス化禁止 } public static void main(String... args) { String pass = "password"; File in = new File(args[0]); File encrypt_out = new File(args[1]); File decrypt_out = new File(args[2]); // 暗号化 encrypt(in, encrypt_out, pass); // 復号 decrypt(encrypt_out, decrypt_out, pass); } /** * 復号処理 * * @param srcIs * 復号対象ファイルストリーム * @param password * 暗号化パスワード * @return 復号ファイルストリーム */ public static InputStream decrypt(FileInputStream srcIs, String password) { try { // バイナリからヘッダー文字列(Salted__)を取得し、検証する byte[] header = new byte[HEADER_BYTES.length]; srcIs.read(header); if (!Arrays.equals(HEADER_BYTES, header)) { throw new IllegalArgumentException("復号対象データの形式が不正です"); } // バイナリからsaltを取得する byte[] salt = new byte[SALT_BYTE_LENGTH]; srcIs.read(salt); // パスワードとsaltをもとに、暗号化keyとivを生成する byte[] key = generateKey(password, salt); byte[] iv = generateIV(password, salt, key); // 復号処理 Cipher cipher = getAESCipher(Cipher.DECRYPT_MODE, key, iv); return new CipherInputStream(srcIs, cipher); } catch (IOException e) { throw new IllegalArgumentException("復号処理に失敗しました", e); } } /** * 復号処理 * * @param src * 復号対象ファイル * @param dest * 復号後のファイル * @param password * 暗号化パスワード */ public static void decrypt(File src, File dest, String password) { validate(src, dest); try (InputStream is = decrypt(new FileInputStream(src), password); FileOutputStream fos = new FileOutputStream(dest);) { byte[] buf = new byte[BUFFER_BYTE_LENGTH]; int read; while ((read = is.read(buf)) != -1) { fos.write(buf, 0, read); } } catch (IOException e) { throw new IllegalArgumentException("復号処理に失敗しました", e); } } /** * 暗号化処理 * * @param src * 暗号化対象ファイル * @param dest * 暗号化後のファイル * @param password * 暗号化パスワード */ public static void encrypt(File src, File dest, String password) { validate(src, dest); // salt、暗号化Key、IVを生成する byte[] salt = generateSalt(); byte[] key = generateKey(password, salt); byte[] iv = generateIV(password, salt, key); // 暗号化処理 Cipher cipher = getAESCipher(Cipher.ENCRYPT_MODE, key, iv); try (FileInputStream fis = new FileInputStream(src); FileOutputStream fos = new FileOutputStream(dest); CipherOutputStream cos = new CipherOutputStream(fos, cipher);) { // ヘッダー文字列「Salted__」(8バイト) + Salt値(8バイト)をまず書き込む fos.write(concatBytes(HEADER_BYTES, salt)); // 暗号化されたコンテンツを書き込む byte[] buf = new byte[BUFFER_BYTE_LENGTH]; int read; while ((read = fis.read(buf)) != -1) { cos.write(buf, 0, read); } } catch (IOException e) { throw new IllegalArgumentException("暗号化処理に失敗しました", e); } } /** * バリデート * * @param src * 入力ファイル * @param dest * 出力ファイル */ private static void validate(File src, File dest) { if (!src.exists()) { throw new IllegalArgumentException("入力ファイルが存在しません。:" + src); } if (src.equals(dest)) { throw new IllegalArgumentException("入力ファイルと出力ファイルが同一です。:" + src); } if (dest.exists()) { throw new IllegalArgumentException("出力ファイルがすでに存在します。:" + dest); } } /** * 暗号器を取得する * * @param mode * 暗号化モード/復号モード * @param key * 暗号化キー * @param iv * IV * @return 暗号機 */ private static Cipher getAESCipher(int mode, byte[] key, byte[] iv) { SecretKey secretKey = new SecretKeySpec(key, "AES"); try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(mode, secretKey, new IvParameterSpec(iv)); return cipher; } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { throw new IllegalStateException("暗号処理の初期化に失敗しました", e); } catch (NoSuchPaddingException | InvalidKeyException e) { throw new IllegalArgumentException("暗号化キーが不正です", e); } } /** * saltを生成する<br> * saltは実行毎に違う値となる。 * * @return 生成されたsalt */ private static byte[] generateSalt() { byte[] salt = new byte[SALT_BYTE_LENGTH]; new SecureRandom().nextBytes(salt); return salt; } /** * パスワードとsaltをもとに、暗号化キーを取得する<br> * 暗号化キー = パスワード + Salt のMD5 * * @param passwdStr * パスワード * @param salt * Salt * @return 生成された暗号化キー */ private static byte[] generateKey(String passwdStr, byte[] salt) { byte[] passwd = passwdStr.getBytes(StandardCharsets.UTF_8); return getMd5(concatBytes(passwd, salt)); } /** * 暗号化キーとパスワードとsaltをもとに、IVを取得する<br> * IV = 暗号化キー + パスワード + Salt のMD5 * * @param passwdStr * パスワード * @param salt * Salt * @param key * 暗号化キー * @return 生成された暗号化iv */ private static byte[] generateIV(String passwdStr, byte[] salt, byte[] key) { byte[] passwd = passwdStr.getBytes(StandardCharsets.UTF_8); return getMd5(concatBytes(key, passwd, salt)); } /** * byte配列の連結 * * @param byteArrays * byte配列 * @return 連結後byte配列 */ private static byte[] concatBytes(byte[]... byteArrays) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try { for (byte[] array : byteArrays) { outputStream.write(array); } } catch (IOException e) { throw new IllegalStateException("バイト配列の連結処理で予期しないエラーが発生しました。", e); } return outputStream.toByteArray(); } /** * MD5ハッシュの生成 * * @param src * ハッシュ生成対象 * @return MD5ハッシュ */ private static byte[] getMd5(byte[] src) { try { MessageDigest md = MessageDigest.getInstance("MD5"); return md.digest(src); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("MD5ハッシュの生成処理で予期しないエラーが発生しました。", e); } } }
いじょーう。
日経 xTECH EXPO AWARD 2018に参加してきました
はじめに
日経 xTECH EXPO なるものに参加してきたのでそのメモ。 全体の割合は、すごくざっくりではあるけど、機械学習関連2割、IoT1割、セキュリティ1割、RPA3割、その他4割くらい。
いろんな企業のブースが、製品とか技術の紹介をしているんだけど、端っこにはセミナースペースもあって、事前申し込みしている人は無料でセミナーを聞くことができるようだった。
RPA関連ブースについてのめも
UIPATH、WINACTOR、BIZROBOの導入や、他のOCR製品と組み合わせたシステムを導入しますよーっといったブースが多かった。
デモを見た感じだと、有名どころのRPA製品については、ほとんどできることは似通っているのかなという印象。ユーザ部が作成することを前提に、GUIで条件分岐や繰り返しができたり、
作業対象のソフトを問わず実行できるように、画像による識別、操作ができる。ユーザの操作を記録してスクリプトを作成するなんてこともできる。
デモでは、エクセルに記載の内容を他のネイティブアプリケーションに転記したり、交通費が記載されていたエクセルの内容を読み取って、えきねっとを起動し、区間をもとに入力された値の検証をする。といったようなこともしていた。普通の企業には山ほどそういった業務があるんだろうなぁ。
ただ、そういう業務があることは担当レベルじゃないとなかなかわからないわけで、Sierがフラーっと見に行っても、発見できないんだろうなぁと思った。業務をやっている側の警戒心もあるだろうし。というところで、「D-Analyzer」というRPA導入のサポートをするような製品を紹介している面白そうなブースを発見した。
「D-Analyzer」は、業務ユーザのPCにインストールし、操作のログを分析するソフトウェア。
ログは、それぞれ担当チームが、どういうソフトウェアにどれだけの時間をかけて作業をしているかというものが一目でわかるようになっている。
膨大な量の業務から、どこに主に時間がかかっているのか、どのソフトウェアを利用してるのかがわかるようになっており、RPA導入の最初の一歩として、どの業務にフォーカスをあてるのが効率がいいのか、その分析に非常に有用なものと感じた。
また、このブースはマニュアル自動生成のためのソフトも展示しており、それも興味深かった。
ユーザの一連の行動を記録し、それぞれスクリーンショットをもとに、どの部分にどういった内容を入力して、どこをクリックしてください。といった吹き出しが追加されたワードやエクセルが出力される。
そのままでは使えないだろうけど、手順書のひな型としてはこちらも非常に有用かと思う。
RPAの技術をそのまま流用させているのだろうけど、展開がうまいね。
OCRとの連携
人が紙でやっていた作業をRPAにするにあたって、OCRは避けては通れないわけで、RPAとOCRとを連携するようなデモも見ることができた。入力用紙を読み取るデモだったが、用紙の入力欄の範囲を指定し、その範囲に対してそれぞれどんな値が入力されるか?をユーザが指定すること、クラウド上の機械学習プラットフォームで解析される。
当然枠外に記載されるとアウト。デモを見た感じ、汚い字でも読み込みはされていた。
ただ自由入力欄の入力は多少識字率が落ちるとのこと。
後は記入データがクラウド上に送信されることをお客さんが許すかどうかという問題もありそう。
IoT
あんまりプラットフォームのところは話が聞けなかった。。暇そうなIoT関連ブースではハード寄りなお話を聞かせてもらいました。
機械学習
画像認識系のブースを2つほど回った。カメラの前でしゃべると、リアルタイムで唇の動きを読み込むというものと、撮った写真のタグ付けをしてくれるというもの。
唇の動きについては、騒音のひどい現場などで使用できるということ。でもデモの感じだと多少精度に問題が出そうだったのと(当然学習を続けることで精度はあがるのでしょうが。)高精度のカメラが必須になるってことで、インカムでいいんちゃうの?という問題をクリアする必要があるのかなーといった印象。
写真のタグ付けに関しては、あらかじめ登録しておいた正解の写真データをもとに、新しく撮った一枚がどのタグに所属するかを推測していた。こちらも5つしか種類がないのにも関わらず、デモ中に失敗していて精度の問題はあるのだろうなぁといった印象。なお、正解データの数は1タグにつき最低5枚あればいいとのこと。
また、やっていることは他社の画像認識用クラウドサービスにデータを送り付けて、それをもとにタグを表示しているだけだった(ように見えた)のが残念。導入している企業もないとのことで、まだまだ研究中で、いろんな用途を探している段階っぽい。
その他
超高速開発WEBサイト開発ツール
GUIで、データ項目定義をすると、そのCRUD操作を行うための画面を自動生成してくれるとかそういったツールの紹介。
見た目はデフォルトだとチープになるため、どちらかというと企業内WEBサイト向けの内容。
CSSはカスタマイズできるものの、JavaScriptとかで見え方こだわるんならスクラッチでやったほうが影響でなくていいと思う。
ビジネスロジックを入れ込むこともできるらしく、俺が聞いた製品は、Javaで実装できるとのこと。
まあ、Salesforceでいいんじゃないでしょうかという印象はぬぐえなかった。。
テスト自動化
テスト自動化製品については2ブースほど。WEBアプリだけで考えるとどちらもSeleniumIDEのとっつきにくさをラップしているだけという印象。
現場で課題となっている、待ち時間管理の問題だったり、サイトのDOM構成変更による保守コストが高いという問題は棚上げになっているのが残念。
テレワーク
2,3ブースあったかもしれないが、、家で使う端末にインストールして、会社からのデータとのやり取りをフォローしたり、家の端末からUSBなどによるデータ呼び出しを防止したり。まあ対策は大事やろなと思いましたまる。
キャンペーンガールの誘導のうまさ。
かわいいお姉さんがブース前にいる→目が合うとにっこり笑顔→パンフレットどうですか?
→アンケートもお願いしてま~す→あちらの机で書いてくださ~い→アンケート書きながらおじさんによる製品紹介。の流れがスムーズすぎる。
まんまと最後までやられてしまった。別にいいんだけど、流石プロだなーって思いました。
怪しげな資格紹介ブース(違う)
キャンペーンガールの呼び込みに引っかかった自分に反省しながら歩いていると、 誰もいないブースの前で、おじいさんがITの資格~資格で~す!と呼びかけている。。 興味を惹かれて入ってみると、おばあさん二人による資格の説明が始まって。。
いやお前全然ITのこと知らんやん!っていう突っ込みが何度も入りそうになりながらプレゼンを聞いていたが、資格の有用性さえ疑わしくなり、途中で耐えきれなくなって出てしまった。
あとで資格の名前を調べてみると、経済産業省推進とか書いているしちゃんとした資格なんだろうなとは思うけど、もうちょっと紹介の仕方は考えたほうがいいんじゃないかと思いました。。
戦利品
今回の戦利品はこんな感じ。
左のボトルはsky株式会社さんのアンケートに書いたらいただいた。そのほかにもプレゼンを聞いた人には抽選で米沢牛があたるという太っ腹ぶり。俺の番号と一つ違いの番号が当選してがっかりです。
総括
なんだか悪いところばっかり協調して書いちゃっているけど、全体として非常に楽しかったし勉強になった。 どの会社さんも無知な俺にすごく丁寧にいろいろ教えてくれて、ありがとうございました。 いろいろいただいたものは大事に使わせていただきます。
ITのトレンドの移り変わりとか、どこにどれだけの熱量があるのかとかを肌で感じるいい機会だと思うので、興味のある方は参加すると損はしないと思う。俺は来年も参加したい。
AWS 認定ソリューションアーキテクト – アソシエイトに合格しました
まあ一週間ほど前のことなのですが、AWS 認定ソリューションアーキテクトの資格に合格しましたのでその記事でも。
自分のスペック
- アプリケーションプログラマ(6年目)
- ミドルウェア(Webサーバ、DB)もそれなりに見る
- インフラの知識はほぼなし。LBは知ってるけど触ったことはない。サブネットとか基本情報で見たなーってくらい。
- AWS経験はほぼなし。少しだけ自己学習用にEC2インスタンスを触ったことはある。
勉強内容(3週間程度)
AWSの基本的な考え方がわかる資料を読む
https://aws.amazon.com/jp/aws-jp-introduction/上の資料で概要を理解したうえで、実際に触ってみた。
→VPC、EC2、ELBを活用して、オートスケールできるサンプルWEBアプリ
※ここまでを2週間くらいかけてダラダラとやったうえで、以下を4日くらい。
参考問題集を解く。
→これについては後述。AWS公式の模擬を解く。
→2000円とかだった気がする。大体模擬試験と本番とは感覚一緒だったんで、模試で7割くらいとれたら受かるんじゃないかと。
試験結果
- 880/1000くらい
まあ全体的に試験勉強という感じではなかった。
ちゃんとAWSの考え方を理解していれば、試験対策はそこまで不要な印象。
AWSの考え方っていうのは、クラウド上でシステムを構築するうえで、
可用性が高くて、コストが低く抑えられるような、AWSの推奨するアーキテクトのポイントをちゃんと抑えるというところ。
上で書いたような、AutoScaling、ELB、EC2の組み合わせとか、WebサーバをS3で代替してCloudFrontと組み合わせるとか、RDSでマルチAZ構成にすると便利だよーとかですね。
抑えるべきポイントとして。最低限以下のサービスについては、AWS クラウドサービス活用資料集をちゃんと読んで、考え方を理解する必要があると思う。
ちゃんと理解しといたほうがいいサービス
- VPC
→パブリックサブネット、プライベートサブネットとか、NATゲートウェイとか。 - EC2
→可用性を上げる構成、セキュリティ(セキュリティグループ、IAMロール)コストプラン(スポットインスタンス、リザーブドインスタンス)とか - S3
→バケットポリシーとかパフォーマンス向上の方法とか、結果整合性の考え方とか。 - RDS
→マルチAZ構成とか、リードレプリカ、ElastiCacheとの組み合わせ、ストレージタイプとか。 - EBS
→ストレージタイプとバックアップとか。ランダムアクセスとシーケンシャルはどんな違いがあってどんな用途に適しているの?とか。 - Lambda
→サーバレスアーキテクチャしってますか?とか - SQS
→AWSに限ったことではなく、キューを使うことのメリットとか。 - CloudWatch
→AWS上のシステムのログ管理一括で請け負ってるよとか、メトリクスどんなんあるのとか。
問題集について
日本語のまともな試験対策本・アプリがない。
結果的には合格したけど、これについては深く絶望した。
自分はがんがん問題を解いて覚える派だったので。
なんでもういっそアプリとか作っちゃおうかな。Vue.jsの勉強もかねてmonacaとかで。
まとめ
俺の会社は古くて、ほぼオンプレとか、今時自社クラウドとかやっているんだけど、
そしてこの試験を会社から受けろと言われてしぶしぶ勉強した口なんだけど、
AWS・・しゅ、しゅごい。。ってなった。よく考えられてる。
今後はこの知識を生かして、AWS上で構築するようなシステム作りたいなー。
ザ・小並感★
Happy Hacking Keyboardを買いました
いやほんとそれだけの記事。 ただ文字が打ちたいだけで3年ぶりに記事を投稿しちゃいまして。
こちら、買っちゃいまして。
もう今ね、文字が打ちたくてしょうがない。 今更HHKかよみたいなところはあるんだろうけどね。 ずっと前から欲しかったんだけど値段的になかなか手が出なくて、 ヨドバシで試し打ちをひたすらしていた日々にさよならだ。
やっぱり買ってよかった。ものを書く皆さんに改めておすすめしたい。 指に吸い付くとか、そこまでの感覚が得られているわけではないけど、 気持ちがいい。スコスコスコ!って音がとにかく気持ちがいい。
HHKってなにって人はこちらね。
いっつも使っていたキーボードは、ThinkPadのやつ。通称赤乳首。 これはこれで最強のビジネスキーボードと呼べると思う。 マウスが必要なくて、指先をホームポジションからほぼ動かさなくて済む。
ただ、うっかりゲームやってたらWキー(前進)するときのキーがもうペカペカになってしまいまして。 その代わりに買ったというわけです。
マウスまで手を持っていく労力は確かに増えたが、HHKを買って後悔は一切していない。 むしろ、HHKを生かした上でどうマウスを触れなくてよくするかというところを改善していきたい。 いっそマウスをやめてトラックボールにも挑戦しようかなと思っています。
さて、文字が打ちたいだけの理由で明日もブログ書く気がする。 ネタはない。