Yubikey5を手に入れたのでGPGを使ってみる(2/2)(Yubikeyに移行編)

blog.akashisn.info

前回はmasterキーとsubキー、失効証明書の作成をした。 今回は作成したキー達を暗号化したボリュームにバックアップを行いYubikeyに書き込んでいく。

暗号化ボリュームの作成

ボリュームの初期化

microSDカードを挿入して、デバイスマップを確認する。

$ sudo dmesg | tail
[ 1003.591053] mmc0: cannot verify signal voltage switch
[ 1003.717876] mmc0: new ultra high speed SDR104 SDHC card at address aaaa
[ 1003.736654] mmcblk0: mmc0:aaaa SH32G 29.7 GiB 
[ 1003.755806]  mmcblk0: p1

/dev/mmcblk0であるとわかったので、パーティションを確認しておく。

$ sudo fdisk -l /dev/mmcblk0 
Disk /dev/mmcblk0: 29.74 GiB, 31914983424 bytes, 62333952 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000

Device         Boot Start      End  Sectors  Size Id Type
/dev/mmcblk0p1       8192 62333951 62325760 29.7G  c W95 FAT32 (LBA)

暗号化するため、/dev/urandomで上書きしておく

$ sudo dd if=/dev/urandom of=/dev/mmcblk0 bs=4M status=progress 
31893487616 bytes (32 GB, 30 GiB) copied, 846 s, 37.7 MB/s 
dd: error writing '/dev/mmcblk0': No space left on device
7610+0 records in
7609+0 records out
31914983424 bytes (32 GB, 30 GiB) copied, 846.685 s, 37.7 MB/s

パーティションの作成

空のDOS領域を作成する。

o -> w と入力する。

$ sudo fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.34).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): o
Created a new DOS disklabel with disk identifier 0x1cb530ee.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

先頭から25MBの暗号化用パーティションを作成する。

n -> p -> 1 -> (enter) -> +25M -> w と入力する。

$ sudo fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.34).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-62333951, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-62333951, default 62333951): +25M

Created a new partition 1 of type 'Linux' and of size 25 MiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

パーティションの暗号化

暗号化ボリュームのパスフレーズを作成する。

$ gpg --gen-random --armor 0 24

先ほど作成したパーティションをLUKSで暗号化する。

YES と入力し、先ほど作成したパスフレーズを入力する。

$ sudo cryptsetup luksFormat /dev/mmcblk0p1 

WARNING!
========
This will overwrite data on /dev/mmcblk0p1 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase for /dev/mmcblk0p1: 
Verify passphrase: 

暗号化したパーティションのマウント

パスフレーズを入力してロックされているパーティションを解除する。

$ sudo cryptsetup luksOpen /dev/mmcblk0p1 secret
Enter passphrase for /dev/mmcblk0p1:

暗号化したパーティションをEXT2でフォーマットする。

$ sudo mkfs.ext2 /dev/mapper/secret -L gpg-$(date +%F)
mke2fs 1.45.5 (07-Jan-2020)
Creating filesystem with 2304 4k blocks and 2304 inodes

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

マウントポイントを作成してマウントする。

$ sudo mkdir /mnt/encrypted-storage
$ sudo mount /dev/mapper/secret /mnt/encrypted-storage

秘密鍵のバックアップ

$ sudo cp -avi $GNUPGHOME /mnt/encrypted-storage/
$ sudo mv /mnt/encrypted-storage/tmp.* /mnt/encrypted-storage/gpgkeys

バックアップが終わったらアンマウントしてパーティションをロックする。

$ sudo umount /mnt/encrypted-storage/
$ sudo cryptsetup luksClose secret

公開鍵のバックアップ

パーティションの作成

公開鍵をバックアップするための暗号化していないパーティションを作成する。

n -> p -> 2 -> (enter) -> +25M -> w と入力する。

$ sudo fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.34).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (53248-62333951, default 53248): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (53248-62333951, default 62333951): +25M

Created a new partition 2 of type 'Linux' and of size 25 MiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
$ sudo mkfs.vfat -F 32 /dev/mmcblk0p2

パーティションのマウント

マウントポイントを作成してマウントする。

$ sudo mkdir /mnt/public
$ sudo mount /dev/mmcblk0p2 /mnt/public/

公開鍵のエクスポート

公開鍵をエクスポートする。

$ gpg --armor --export $KEYID | sudo tee /mnt/public/gpg-$KEYID-$(date +%F).txt

バックアップが終わったらアンマウントする。

$ sudo umount /mnt/public/

Yubikey5に秘密鍵を移動

YubiKey Managerのインストール

developers.yubico.com

$ sudo apt-add-repository ppa:yubico/stable
$ sudo apt update
$ sudo apt install yubikey-manager

Yubikeyのリセット

Yubikey5をPCに接続して、リセットを行う。

$ ykman openpgp reset
WARNING! This will delete all stored OpenPGP keys and data and restore factory settings? [y/N]: y
Resetting OpenPGP data, don't remove your YubiKey...
Success! All data has been cleared and default PINs are set.
PIN:         123456
Reset code:  NOT SET
Admin PIN:   12345678

$ ykman piv reset
WARNING! This will delete all stored PIV data and restore factory settings. Proceed? [y/N]: y
Resetting PIV data...
Success! All PIV data have been cleared from your YubiKey.
Your YubiKey now has the default PIN, PUK and Management Key:
    PIN:    123456
    PUK:    12345678
    Management Key: 010203040506070801020304050607080102030405060708

PINの変更

PIV機能のPIN

Yubikey5のPIV機能には3種類のPINがある。

  • PIN : 普段使用するPINコード。6~8桁の数値
  • PUK : PINコードを紛失したときやPINを複数回間違えてロックされた時に解除するときに使う。6~8桁の英数字が使える。
  • Management Key : 24byte 3DESのkey。鍵の生成や証明書のimport時に使う。PINによって保護されたランダムのキーを用いる。
$ ykman piv change-pin
Enter your current PIN: 
Enter your new PIN: 
Repeat for confirmation: 
New PIN set.

$ ykman piv change-puk
Enter your current PUK: 
Enter your new PUK: 
Repeat for confirmation: 
New PUK set.

$ ykman piv change-management-key --protect
Enter PIN: 
Enter your current management key [blank to use default key]:

PINの変更が出来たらいったんYubikeyを抜き差しする。

さらにややこしいのが、このPIVのPINとOpenPGPのPINはレイヤーが違うので、OpenPGPでもPINを変更する必要がある。

OpenPGP機能のPIN

www.gnupg.org

PIV機能のPINと同じく、デフォルトのAdmin PINは12345678、普通のPINは123456である。

GPG側でOpenPGP機能のPINの変更を行う。

admin -> passwd -> 1 -> 123456 -> 新たなPIN(2回) -> 3 -> 12345678 -> 新たなAdmin PIN(2回) -> q と入力する。

$ gpg --card-edit 

Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: Dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: xxxxxxxx
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......: 
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> admin
Admin commands are allowed

gpg/card> passwd
gpg: OpenPGP card no. Dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
PIN changed.

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? q

Yubikey情報の変更

名前、言語、アカウント名などを指定する。

gpg/card> name
Cardholder's surname: <姓>
Cardholder's given name: <名>

gpg/card> lang
Language preferences: ja

gpg/card> login
Login data (account name): <Email等>

gpg/card> list

Reader ...........: Yubico YubiKey OTP FIDO CCID 00 00
Application ID ...: Dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: xxxxxxxx
Name of cardholder: <名><姓>
Language prefs ...: ja
Salutation .......: 
URL of public key : [not set]
Login data .......: <Email等>
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> q

秘密鍵の移動

選択しているキーにはssb*とアスタリスクがつく。

keytocardは破壊的な操作でYubikeyに移した秘密鍵はもう取り戻せないのでバックアップが確実に行われていることを確認しておく。

MasterキーのパスフレーズとAdmin PINの入力が求められる。

$ gpg --edit-key $KEYID 
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

gpg>

署名キー

key 1 -> keytocard -> 1 と入力し、MasterキーのパスフレーズとAdmin PINを入力する。

gpg> key 1

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb* nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb* nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

暗号化キー

key 1 -> key 2 -> keytocard -> 2 と入力し、MasterキーのパスフレーズとAdmin PINを入力する。

gpg> key 1

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

gpg> key 2

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb* nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

gpg> keytocard
Please select where to store the key:
   (2) Encryption key
Your selection? 2

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb* nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

認証キー

key 2 -> key 3 -> keytocard -> 3 と入力し、MasterキーのパスフレーズとAdmin PINを入力する。

gpg> key 2

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

gpg> key 3

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb* nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

gpg> keytocard
Please select where to store the key:
   (3) Authentication key
Your selection? 3

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C   
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S   
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E   
ssb* nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A   
[ultimate] (1). <名前> <メールアドレス>

変更を保存する。

gpg> save

検証

subキーの秘密鍵が移動されたかを確認する。

$ gpg -K
/tmp/tmp.nqKpgHfYNN/pubring.kbx
-------------------------------
sec   nistp521 2020-12-09 [C]
      D6FCE147DE91797391B2D70BBF8A708B020A19BB
uid           [ultimate] <名前> <メールアドレス>
ssb>  nistp521 2020-12-09 [S]
ssb>  nistp521 2020-12-09 [E]
ssb>  nistp521 2020-12-09 [A]

ssb>となってればちゃんと移動している。

クリーンアップ

$ gpg --delete-secret-key $KEYID
$ sudo srm -r $GNUPGHOME || sudo rm -rf $GNUPGHOME
$ unset GNUPGHOME

続きはこちら(執筆中)

Yubikey5を手に入れたのでGPGを使ってみる(1/2)(GPG key作成編)

Yubikeyとは

support.yubico.com

YubiKeyとはこのような見た目で、アメリカ・スウェーデンを拠点とするYubico社が開発した認証デバイス。

特徴として、海底48mに沈めて二ヶ月放置しても、洗濯乾燥機に突っ込んでも壊れない堅牢性と分解・解析に対する耐タンパ性を持っている。また、Yubikeyにデータを書き込むことは簡単にできるが、読み出すことは一切できない。そのため、秘密鍵などを保管するのに適している。

機能

購入したYubikey 5C NFCには以下の機能がある

  • FIDO2
  • OTP
  • U2F
  • OATH
  • PIV (Smart Card)
  • OpenPGP

Yubikey 5C NFCではOpenPGPにてECC(楕円曲線)に対応しているため、それを使用する。

GnuPGとは

text.baldanders.info

GnuPG (GNU Privacy Guard) は OpenPGP 実装のひとつで,現在は以下の RFC に準拠している。

  • RFC 4880 - OpenPGP Message Format
  • RFC 5581 - The Camellia Cipher in OpenPGP
  • RFC 6637 - Elliptic Curve Cryptography (ECC) in OpenPGP

OpenPGPの源流であるPGP (Pretty Good Privacy) は、Philip Zimmermannが1991年に開発した暗号ソフトウェア。 PGPにはそれが公開特許ではなく複雑な特許権問題が絡んでいるという問題があった。 そのため、当時の PGP の仕様を知財的に安全なものとして再構成したのが OpenPGPである 。

text.baldanders.info

右端列の「強度」は鍵長ではなく,セキュリティ強度なのでご注意を。

SECG/NIST 推奨パラメータ

GnuPG SECG NIST アルゴリズム 強度 bits
nistp256 secp256r1 NIST curve P-256 ECDH, ECDSA 128
nistp384 secp384r1 NIST curve P-384 ECDH, ECDSA 192
nistp521 secp521r1 NIST curve P-521 ECDH, ECDSA 256
secp256k1 secp256k1 ECDH, ECDSA 128

Yubikey 5C NFCが対応しているアルゴリズムでセキュリティ強度が一番長い secp521r1 を使う。

GPGキーの作成

Yubikey本体でキーの作成も出来るが、取り出すことが出来ないので、Yubikeyを紛失した場合終わるため、後からインポートする方法をとる。

Yubikeyのガイドは以下のリポジトリがすごく参考になる。 と言うか本記事はこのガイドを元に記述している。

github.com

Yubikeyの公式ドキュメント

developers.yubico.com

作成の流れ

作成する環境はUbuntuのLive Imageを使用する。

GPGにはmasterキーとそれのsubキーの2つの種類のキーが存在する。 masterキーは絶対秘密にしておかなければならない最重要のキーであり、普段はオフラインにて安全に保存する必要がある。 masterキーを使用するときは新たなsubキーを作成する時や、キーを失効させたりするときのみである。 またそれぞれのキーには機能(例えば証明、署名、暗号化、認証などである)があり、各機能毎にキーを分ける方が良いとされる。

  1. masterキー(証明)を作成
  2. subキー(署名、暗号化、認証のそれぞれ)を作成
  3. master, subの秘密鍵のエクスポート
  4. 失効証明書の作成
  5. 鍵のバックアップ
  6. 公開鍵をエクスポート
  7. subキーの秘密鍵をYubikeyに移動させる
  8. クリーンアップ

3,4では暗号化したボリュームにコピーをする(今回はmicro SDカードを用いた)

つまり、masterキーはオフラインで安全にバックアップをとり、普段使用するYubikeyには各種subキーを保管する

依存ソフトのインストール

/etc/apt/sources.list の各行に universe multiverseを追加してから以下を行う。

$ sudo apt update
$ sudo apt -y install wget gnupg2 gnupg-agent cryptsetup scdaemon pcscd secure-delete

一時ディレクトリを作成する

$ export GNUPGHOME=$(mktemp -d)

Masterキーの作成

masterキーのパスフレーズの作成

$ gpg --gen-random --armor 0 24
Q0ujl1x35gacX95okzlABZ93aHOBvZJl

機能が Certify だけになるようにする。 masterキーは有効期限は無期限にしてオフラインで管理する方がいいみたい。

11 -> S -> Q -> 5 -> 0 -> y -> 名前 -> メールアドレス -> コメント(あれば) と入力して先ほど作成したパスフレーズを入力する。

$ gpg --expert --full-generate-key
gpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
  (14) Existing key from card
Your selection? 11

Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Sign Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S

Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 5
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: <名前>
Email address: <メールアドレス>
Comment:
You selected this USER-ID:
    "<名前> <メールアドレス>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /tmp.nqKpgHfYNN/trustdb.gpg: trustdb created
gpg: key BF8A708B020A19BB marked as ultimately trusted
gpg: directory '/tmp/tmp.nqKpgHfYNN/openpgp-revocs.d' created
gpg: revocation certificate stored as '/tmp.nqKpgHfYNN/openpgp-revocs.d/D6FCE147DE91797391B2D70BBF8A708B020A19BB.rev'
public and secret key created and signed.

pub   nistp521 2020-12-09 [C]
      D6FCE147DE91797391B2D70BBF8A708B020A19BB
uid                      <名前> <メールアドレス>

gpg: key BF8A708B020A19BB marked as ultimately trusted

キーIDは後で使うので環境変数にセットしておく

$ export KEYID=BF8A708B020A19BB 

Subキーを作成する

今回は簡略化のためsubキーも有効期限を無期限としているが本来は有効期限を設定した方が良い。

$ gpg --expert --edit-key $KEYID
gpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C
     trust: ultimate      validity: ultimate
[ultimate] (1). <名前> <メールアドレス>

gpg>

Signing (署名)

署名のみのsubキーを作成する。

10 -> 5 -> 0 -> y -> y と入力して先ほど作成したパスフレーズを入力する。

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 10
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 5
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S
[ultimate] (1). <名前> <メールアドレス>

Encryption (暗号化)

暗号化のみのサブキーを作成する

12 -> 5 -> 0 -> y -> y と入力して先ほど作成したパスフレーズを入力する。

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 12
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 5
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E
[ultimate] (1).  <名前> <メールアドレス>

Authentication (認証)

認証のみのsubキーを作成する。 認証のみの機能は一覧にないため、自分で機能の選択をして認証のみにする。

11 -> A -> S -> Q -> 5 -> 0 -> y -> y と入力して先ほど作成したパスフレーズを入力する。

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 11

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? A

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Sign Authenticate

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S

Possible actions for a ECDSA/EdDSA key: Sign Authenticate
Current allowed actions: Authenticate

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 5
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A
[ultimate] (1). <名前> <メールアドレス>

gpg>

保存して終了する

gpg> save

検証する

-K オプションを渡すことでGPGが認識している秘密鍵をリストアップしてくれる。

$ gpg -K
/tmp/tmp.nqKpgHfYNN/pubring.kbx
------------------------------
sec   nistp521 2020-12-09 [C]
      D6FCE147DE91797391B2D70BBF8A708B020A19BB
uid           [ultimate] <名前> <メールアドレス>
ssb   nistp521 2020-12-09 [S]
ssb   nistp521 2020-12-09 [E]
ssb   nistp521 2020-12-09 [A]

ちなみに左の sec とか ssb とかはそれぞれ以下を表している。

  • sec => SECret key
  • ssb => Secret SuBkey
  • pub => PUBlic key
  • sub => public SUBkey

秘密鍵をエクスポートする

マスターキーとサブキーは、エクスポート時にパスフレーズで暗号化される。

$ gpg --armor --export-secret-keys $KEYID > $GNUPGHOME/master.key

$ gpg --armor --export-secret-subkeys $KEYID > $GNUPGHOME/sub.key

master.key は新たなsubキーを作成するときや、有効期限を更新するときにインポートして使うためにエクスポートしている。

失効証明書を作成する

マスターキーをバックアップして安全な場所に保存するが、マスターキーを紛失したり、バックアップが失敗したりする可能性をがあるため失効証明書は必要。

y -> 0 -> 追加の説明(あれば) -> y と入力して先ほど作成したパスフレーズを入力する。

$ gpg --output $GNUPGHOME/revoke.asc --gen-revoke $KEYID

sec  nistp521/BF8A708B020A19BB 2020-12-09  <名前> <メールアドレス>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 0
Enter an optional description; end it with an empty line:
>
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y
ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

この revoke.asc 証明書ファイルは、メインバックアップが失敗した場合に取得できるように、別場所に保存(または印刷)する必要がある。

続きはこちら

blog.akashisn.info

Yolov3でKITTIデータを学習してみる

前回はYolov3のAlexeyAB/Darknetをインストールしたので今回は学習してみる

blog.akashisn.info

環境

  • Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
  • 64GB RAM
  • GeForce RTX 2080 Ti 11GB
  • Ubuntu 18.04 LTS

学習データの準備

学習データとしてドイツのカールスルーエ工科大学とアメリカ・シカゴにある豊田工業大学シカゴ校のチームによる、自動車ビジョンのための画像データを使用する

www.cvlibs.net

  • Download left color images of object data set (12 GB) (data_object_image_2.zip)
  • Download training labels of object data set (5 MB) (data_object_label_2.zip)

上記からこの2つのファイルをダウンロードする。

これらを同じディレクトリで展開する

$ mkdir raw
$ cd raw
$ unzip data_object_image_2.zip
$ data_object_label_2.zip
$ ls
training testing

学習画像はtraining/image_2に、ラベルはtraining/label_2にある

ラベルデータのフォーマットは

github.com

hirotaka-hachiya.hatenablog.com

このようになっているのでYolov3のラベルフォーマット

<ラベル> <矩形の中心座標x/画像幅> <矩形の中心座標y/画像高さ> <矩形の幅/画像幅> <矩形の高さ/画像高さ>

に変換する必要がある。

convert detectnet labeling format to yolov3 labeli ...

変換するスクリプトを書いた。

Pillowを使ってるので適当にインストールしてください。

$ python detectnet2yolo.py [画像ディレクトリ]  [ラベルディレクトリ]

と実行すると、カレントディレクトリにyolo_labelディレクトリを作成してその中に変換したラベルデータとclasses.txtを出力する

$ python detectnet2yolo.py training/image_2 training/label_2

Yoloでは画像とラベルは同一のディレクトリ内にある必要があるので

$ cd ..
$ mkdir train_data
$ cp raw/training/image_2/* data/
$ cp raw/yolo_label/* data/

このようにする。

次に、学習データとテストデータを振り分ける

generate yolo training and validation(test)

$ python generate_validation.py [データディレクトリ]

と実行すると、カレントディレクトリにtrain.txttest.txtを出力する

$ python generate_validation.py data/

darknetの設定

github.com

READMEを参照しながら設定していく

https://github.com/AlexeyAB/darknet/blob/master/cfg/yolov3.cfg

これを以下のように修正してcfg/yolo-obj.cfgにコピーする

$ diff --git a/cfg/yolov3.cfg b/cfg/yolov3.cfg
index 4a0ecc3..b01d980 100644
--- a/cfg/yolov3.cfg
+++ b/cfg/yolov3.cfg
@@ -1,10 +1,10 @@
 [net]
 # Testing
-batch=1
-subdivisions=1
+# batch=1
+# subdivisions=1
 # Training
-# batch=64
-# subdivisions=16
+batch=64
+subdivisions=16
 width=416
 height=416
 channels=3
@@ -17,9 +17,9 @@ hue=.1
 
 learning_rate=0.001
 burn_in=1000
-max_batches = 500200
+max_batches = 18000
 policy=steps
-steps=400000,450000
+steps=14400,16200
 scales=.1,.1
 
 [convolutional]
@@ -600,14 +600,14 @@ activation=leaky
 size=1
 stride=1
 pad=1
-filters=255
+filters=42
 activation=linear
 
 
 [yolo]
 mask = 6,7,8
 anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
-classes=80
+classes=9
 num=9
 jitter=.3
 ignore_thresh = .7
@@ -686,14 +686,14 @@ activation=leaky
 size=1
 stride=1
 pad=1
-filters=255
+filters=42
 activation=linear
 
 
 [yolo]下
 mask = 3,4,5
 anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
-classes=80
+classes=9
 num=9
 jitter=.3
 ignore_thresh = .7
@@ -773,17 +773,18 @@ activation=leaky
 size=1
 stride=1
 pad=1
-filters=255
+filters=42
 activation=linear
 
 
 [yolo]
 mask = 0,1,2
 anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
-classes=80
+classes=9
 num=9
 jitter=.3
 ignore_thresh = .7
 truth_thresh = 1
 random=1
 
+
batch=64
subdivisions=16

これについては

stackoverflow.com

batchsubdivisionsで割り切れればいいよって情報と

github.com

subdivisionsが大きすぎると学習がうまく行かなくなったっていう情報があるのでよくわからない。

でもbatch64のままで、 GPUのメモリと相談してsubdivisions8,16.32と調整するのがいいみたい。

次にcfg/obj.dataを以下で作成する

classes = 9
train = train.txt
valid = test.txt
names = train_data/classes.txt
backup = weights/

次に事前学習データをダウンロードする

$ wget https://pjreddie.com/media/files/darknet53.conv.74

次に学習結果を保存するディレクトリを作成する

$ mkdir weights

最後にラベルをリポジトリのdata/labelsからコピーしてくる

$ mkdir data
$ cp -r (path to darknet)/data/labels data/

結果的にこのようなディレクトリ構成にする

$ tree .
.
├── cfg
│   ├── obj.data
│   └── yolo-obj.cfg
├── darknet53.conv.74
├── data
│   └── labels
│     ...
├── train_data
│   ├── 000000.png
│   ├── 000000.txt
│   ├── 000001.png
│   ├── 000001.txt
│     ...
├── raw
│   ├── training
│     ...
│   ├── testing
│     ...
│   └── yolo_label
│     ...
├── test.txt
├── train.txt
└── weights

学習する

$ darknet detector train cfg/obj.data cfg/yolo-obj.cfg darknet53.conv.74 -map

17時間後

detections_count = 11067, unique_truth_count = 5168  
class_id = 0, name = Car, ap = 94.26%        (TP = 2584, FP = 117) 
class_id = 1, name = Van, ap = 98.39%        (TP = 312, FP = 21) 
class_id = 2, name = Truck, ap = 99.73%      (TP = 103, FP = 2) 
class_id = 3, name = Pedestrian, ap = 72.65%     (TP = 313, FP = 86) 
class_id = 4, name = Person_sitting, ap = 76.04%     (TP = 21, FP = 4) 
class_id = 5, name = Cyclist, ap = 86.48%        (TP = 138, FP = 18) 
class_id = 6, name = Tram, ap = 99.09%       (TP = 65, FP = 4) 
class_id = 7, name = Misc, ap = 95.11%       (TP = 105, FP = 7) 
class_id = 8, name = DontCare, ap = 36.97%       (TP = 512, FP = 584) 

 for conf_thresh = 0.25, precision = 0.83, recall = 0.80, F1-score = 0.82 
 for conf_thresh = 0.25, TP = 4153, FP = 843, FN = 1015, average IoU = 67.70 % 

 IoU threshold = 50 %, used Area-Under-Curve for each unique Recall 
 mean average precision (mAP@0.50) = 0.843033, or 84.30 % 
Total Detection Time: 8.000000 Seconds

mAPが84.3%なのでまぁまぁいい感じに学習できた

テストしてみる

raw/testing/image_2にテスト用のデータがあるのでこれを入力してみる

$ darknet detector test cfg/obj.data cfg/yolo-obj.cfg weights/yolo-obj_best.weights raw/testing/image_2/000090.png
...
raw/testing/image_2/000090.png: Predicted in 11.234000 milli-seconds.
Car: 100%
Car: 100%
Car: 100%
Car: 39%
Car: 69%
DontCare: 30%

f:id:akashisn:20191216225430j:plain

ちゃんと学習できてる

Yolov3をUbuntuで使う

はじめに

物体認識モデルの一つであるYolov3をUbuntu 18.04にインストールする。

pjreddie.com

物体認識モデルのYolo(You only look once:一度しか見ない)のVersion3で、 Yoloネットワークを実装したものがdarknetである。

pjreddie.com

環境

  • Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
  • 64GB RAM
  • GeForce RTX 2080 Ti 11GB
  • Ubuntu 18.04 LTS

インストールの流れ

  1. NVIDIA Graphic Driverのインストール(GPUがある場合)
  2. CUDAのインストール(GPUがある場合)
  3. cuDNNのインストール(GPUがある場合)
  4. OpenCVのインストール
  5. darknetのビルド

NVIDIA関係のインストール

NVIDIA Graphic Driver

GPUを積んでいるPCならドライバは大丈夫だと思うがnvidia-smiと端末で打ってみてDriver Versionを確認しておく

$  nvidia-smi
Mon Dec 16 12:24:47 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.33.01    Driver Version: 440.33.01    CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce RTX 208...  On   | 00000000:01:00.0  On |                  N/A |
|100%   60C    P2   292W / 300W |   7496MiB / 11016MiB |     69%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0      1134      G   /usr/lib/xorg/Xorg                            39MiB |
|    0      1200      G   /usr/bin/gnome-shell                          49MiB |
|    0      2080      G   /usr/lib/xorg/Xorg                           349MiB |
|    0      2215      G   /usr/bin/gnome-shell                         194MiB |
|    0      2596      G   ...uest-channel-token=15935874221952217047   245MiB |
+-----------------------------------------------------------------------------+

ここでCUDAのバージョンが表示されているがこれはDriverをビルドしたときのCUDAランタイムのバージョンなのでインストールされているバージョンとは異なる。

ドライバが入っていなければ以下でインストールする。

# GPUを認識しているか確認
$ sudo ubuntu-drivers devices
# 認識していればインストール
$ sudo ubuntu-drivers autoinstall
$ reboot

CUDA

CUDA(Compute Unified Device Architecture:クーダ)とは、NVIDIAが開発・提供している、GPU向けの汎用並列コンピューティングプラットフォーム(並列コンピューティングアーキテクチャ)およびプログラミングモデルである。 - Wikipedia

以下のようにCUDA10.1をインストールする

CUDA Toolkit 10.2 Download | NVIDIA Developer

$ wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin
$ sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600
$ sudo apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
$ sudo add-apt-repository "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/ /"
$ sudo apt update
$ sudo apt -y install cuda-10-1
$ reboot

.bashrcなどに追加しておく

export PATH="/usr/local/cuda/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/cuda/lib64:$LD_LIBRARY_PATH"

cuDNN

NVIDIACUDA®ディープニューラルネットワークライブラリ(cuDNN)は、ディープニューラルネットワーク用のプリミティブのGPUアクセラライブラリです。 - NVIDIA cuDNN | NVIDIA Developer

https://developer.nvidia.com/rdp/cudnn-download ここから

  • cuDNN Library for Linux
  • cuDNN Runtime Library for Ubuntu18.04 (Deb)
  • cuDNN Developer Library for Ubuntu18.04 (Deb)
  • cuDNN Code Samples and User Guide for Ubuntu18.04 (Deb)

をダウンロードする(要ログイン)

ダウンロードするしたものをインストール

$ sudo apt install ./libcudnn7_7.6.5.32-1+cuda10.1_amd64.deb
$ sudo apt install ./libcudnn7-dev_7.6.5.32-1+cuda10.1_amd64.deb
$ sudo apt install ./libcudnn7-doc_7.6.5.32-1+cuda10.1_amd64.deb
$ tar xvf cudnn-10.1-linux-x64-v7.6.5.32.tgz
$ sudo cp -a cuda/include/cudnn.h /usr/local/cuda/include/
$ sudo cp -a cuda/lib64/libcudnn* /usr/local/cuda/lib64/
$ sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*
$ sudo cp -r cuda /usr/local/cudnn

テストする

$ cp -r /usr/src/cudnn_samples_v7/ ~/
$ cd ~/cudnn_samples_v7/mnistCUDNN
$ make
$ ./mnistCUDNN
...
Test passed!

OpenCVのインストール

Python関係

$ sudo apt -y install python3-dev python3-setuptools python3-pip python3-numpy

Intel MKL

intelのCPUを使っていれば最適化されるのでインストールする

公式ページ software.intel.com

$ sudo su
# cd /tmp
# wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB
# apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB
# rm GPG-PUB-KEY-INTEL-SW-PRODUCTS-2019.PUB
# echo "deb https://apt.repos.intel.com/mkl all main" > /etc/apt/sources.list.d/intelproducts.list
# exit
$ sudo apt update
$ sudo apt install -y intel-mkl-64bit-2019.5-075

Cmake

後のdarknetのビルドで最新版が必要となるので、cmakeの最新版をインストールする

$ sudo apt -y install zlib1g-dev libcurl4-openssl-dev
$ wget https://github.com/Kitware/CMake/releases/download/v3.15.5/cmake-3.16.1.tar.gz -O /tmp/cmake-3.16.1.tar.gz
$ cd /usr/local/src
$ sudo tar xvf /tmp/cmake-3.16.1.tar.gz
$ cd cmake-3.16.1
$ sudo su
# ./configure --system-curl --system-zlib
# make -j8
# make install

OpenCV

依存関係のインストール

$ sudo apt install -y build-essential bzip2 ca-certificates  curl ffmpeg \
        libavcodec-dev libavformat-dev libavresample-dev libcurl4-openssl-dev \
        libjpeg-dev libpng-dev libswscale-dev libtbb-dev libtiff-dev libv4l-dev \
        libopenalpr-dev libopenni2-dev libopenblas-dev libpcl-dev libgtkglext1-dev \
        libguava-java libgtk2.0-dev libgtk-3-dev openalpr openalpr-utils \
        openni2-utils primesense-nite-nonfree pkg-config unzip wget zlib1g-dev

ダウンロードする

$ cd /usr/local/src
$ sudo git clone https://github.com/opencv/opencv_contrib.git 
$ cd opencv_contrib
$ sudo git checkout 4.1.2 #OpenCVとバージョンを揃える
$ cd ..
$ sudo git clone https://github.com/opencv/opencv.git 
$ cd opencv
$ sudo git checkout 4.1.2

ビルドする

$ cd /usr/local/src/opencv
$ sudo su
# mkdir build
# cd build
# CUDA_PATH="/usr/local/cuda" CFLAGS="-I/usr/local/cuda/include" LDFLAGS="-L/usr/local/cuda/lib64" \
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=/usr/local/src/opencv_contrib/modules \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_TESTS=OFF \
-D BUILD_PERF_TESTS=OFF \
-D BUILD_EXAMPLES=OFF \
-D BUILD_opencv_python2=OFF \
-D BUILD_opencv_python3=ON \
-D PYTHON_DEFAULT_EXECUTABLE=python3 \
-D OpenBLAS_INCLUDE_DIR=/usr/include/x86_64-linux-gnu \
-D OpenBLAS_LIB=/usr/lib/x86_64-linux-gnu/libopenblas.so \
-D OPENCV_DNN_CUDA=ON \
-D WITH_PYTHON=ON \
-D WITH_TBB=ON \
-D WITH_CUDA=ON \
-D WITH_MKL=ON \
-D WITH_CUBLAS=ON \
-D WITH_CUDNN=ON \
-D WITH_NVCUVID=OFF \
-D WITH_FFMPEG=ON \
-D CUDA_FAST_MATH=ON \
-D CUDA_ARCH_BIN=7.5 \
-D CUDA_ARCH_PTX=7.5 \
-D ENABLE_FAST_MATH=ON \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D OPENCV_PC_FILE_NAME=opencv.pc ..
# CUDA_PATH="/usr/local/cuda" CFLAGS="-I/usr/local/cuda/include" LDFLAGS="-L/usr/local/cuda/lib64" make -j8
# make install
# /sbin/ldconfig
# exit

cmakeのオプションでGPUを積んでいないPCなら

-D OPENCV_DNN_CUDA=ON \
-D CUDA_FAST_MATH=ON \
-D WITH_PYTHON=ON \
-D WITH_MKL=ON \
-D WITH_CUDA=ON \
-D WITH_CUBLAS=ON \
-D WITH_CUDNN=ON \
-D WITH_NVCUVID=OFF \
-D BUILD_opencv_cudaimgproc=ON

ココらへんを削除する

バージョンを確認する

$ python3 -c "import cv2; print( cv2.__version__ )"
4.1.2

darknetのビルド

本家の方は開発が滞っているようで最新のOpenCVでは動作しないのでforkされたものを使用する github.com 本家

github.com fork

$ git clone https://github.com/tiagoshibata/darknet.git
# Makefileを以下のように修正する
$ diff --git a/Makefile b/Makefile
index fa6edd5..121c3d1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
-GPU=0
-CUDNN=0
-OPENCV=0
-OPENMP=0
+GPU=1
+CUDNN=1
+OPENCV=1
+OPENMP=1
 DEBUG=0
 
 ARCH= -gencode arch=compute_30,code=sm_30 \

$ make

実行してみる

$ cd result
$ wget https://pjreddie.com/media/files/yolov3.weights
$ cd ..
$ ./darknet detect cfg/yolov3.cfg results/yolov3.weights data/dog.jpg
...
Loading weights from results/yolov3.weights...Done!
data/dog.jpg: Predicted in 0.079761 seconds.
dog: 100%
truck: 92%
bicycle: 99%

CUDA Error: out of memoryと出た場合はcfg/yolov3.cfgsubdivisionsを大きな数にしてみる f:id:akashisn:20191121114409p:plain

追記 2019-11-22

darknetの更に活発なforkを見つけたのでそちらも使ってみます

github.com

コードの更新が数時間おきにあって活発

ビルドはかんたん

$ git clone https://github.com/AlexeyAB/darknet.git
$ cd darknet
$ mkdir build_release
$ cd build_release
$ cmake ..
$ make
$ make install

実行

$ mkdir models
$ wget https://pjreddie.com/media/files/yolov3.weights -O models/yolov3.weights
$ ./darknet detect cfg/yolov3.cfg models/yolov3.weights data/giraffe.jpg
...
Done! Loaded 107 layers from weights-file 
data/giraffe.jpg: Predicted in 29.941000 milli-seconds.
giraffe: 100%
giraffe: 62%
zebra: 96%

f:id:akashisn:20191122154645p:plain

blog.akashisn.info

Golangのインストール

anyenvgoenvの組み合わせがおすすめ

What's anyenv

anyenv.github.io

anyenvはPythonならpyenv、Rubyならrbenvのような**env系をひとまとめにするラッパープログラム。

現在以下の言語に対応している

  • Renv: R
  • crenv: Crystal
  • denv: D
  • erlenv: Erlang
  • exenv: Elixir
  • goenv: GO
  • hsenv: Haskell
  • jenv: Java
  • luaenv: Lua
  • nodenv: Node.js
  • phpenv: PHP
  • plenv: Perl
  • pyenv: Python
  • rbenv: Ruby
  • sbtenv: Sbt
  • scalaenv: Scala
  • swiftenv: Swift

**env ...?

**env系とはRubyのrbenvが発祥の言語を複数のバージョン使い分ける為のツール。 派生として各言語の**envができた。

グローバルの環境を汚さないので開発環境に適している。

Install anyenv

Homebrew (Mac)

  1. anyenvをインストールする
  2. $ brew install anyenv
    
  3. anyenvの設定をする
  4. $ anyenv init
    
  5. 初期設定
  6. $ anyenv install --init
    
  7. 起動時に読み込むようにする
  8. # bashの場合
    $ echo 'eval "$(anyenv init -)"' >> ~/.bashrc
    
    # zshの場合
    $ echo 'eval "$(anyenv init -)"' >> ~/.zshrc
    
  9. 端末を再起動する
  10. プラグインをインストールする
  11. $ mkdir -p $(anyenv root)/plugins
    $ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
    $ git clone https://github.com/znz/anyenv-git.git $(anyenv root)/plugins/anyenv-git
    

Manual git checkout (Linux)

  1. ~/.anyenvにクローンする
  2. $ git clone https://github.com/anyenv/anyenv ~/.anyenv
    
  3. ~/.anyenv/binを$PATHに追加し、起動時に読み込むようにする
  4. # bashの場合
    $ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bashrc
    $ echo 'eval "$(anyenv init -)"' >> ~/.bashrc
    
    # zshの場合
    $ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.zshrc
    $ echo 'eval "$(anyenv init -)"' >> ~/.zshrc
    
  5. anyenvの設定をする
  6. $ ~/.anyenv/bin/anyenv init
    
  7. 初期設定
  8. $ ~/.anyenv/bin/anyenv install --init
    
  9. 端末を再起動する
  10. プラグインをインストールする
  11. $ mkdir -p $(anyenv root)/plugins
    $ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
    $ git clone https://github.com/znz/anyenv-git.git $(anyenv root)/plugins/anyenv-git
    

Install goenv and golang

github.com

  1. goenvをインストールする
  2. $ anyenv install goenv
    
  3. GOPATHを指定
  4. # bashの場合
    $ echo 'export GOENV_DISABLE_GOPATH=1' >> ~/.bashrc
    $ echo 'export GO111MODULE=on' >> ~/.bashrc
    $ echo 'export GOPATH=$HOME/Project' >> ~/.bashrc
    $ echo 'export PATH=$PATH:$GOPATH/bin' >> .bashrc
    
    # zshの場合
    $ echo 'export GOENV_DISABLE_GOPATH=1' >> ~/.zshrc
    $ echo 'export GO111MODULE=on' >> ~/.zshrc
    $ echo 'export GOPATH=$HOME/Project' >> ~/.zshrc
    $ echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.zshrc
    
  5. 端末を再起動する
  6. Golangをインストールする
  7. $ goenv install 1.15.3
    
  8. デフォルトに設定する
  9. $ goenv global 1.15.3
    
  10. 端末を再起動する

Golangのツールをインストールする

  1. ghq (GOPATH管理の為のツール)をインストール
    • Homebrew (Mac)
    • $ brew install ghq
      
    • Linux
    • $ go get github.com/x-motemen/ghq
      
  2. ghqの設定
  3. $ git config --global ghq.root $GOPATH/src
    
  4. peco (リポジトリ間の移動を楽にするツール)をインストール
    • Homebrew (Mac)
    • $ brew install peco
      
    • Linux
    • pecoのリリースページに行って最新版をダウンロードしてパスの通ってるところに配置する
      $ wget -O /tmp/peco.tar.gz https://github.com/peco/peco/releases/download/v0.5.8/peco_linux_amd64.tar.gz
      $ tar xzvf /tmp/peco.tar.gz -C /tmp
      $ sudo mv /tmp/peco_linux_amd64/peco /usr/local/bin/peco
      
  5. pecoの設定
  6. ctrl + ]で使えるようにする
    • zshの場合
    • ~/.zshrcに以下を追記
      # Setting for peco
      function peco-src () {
        local selected_dir=$(ghq list -p | peco --query "$LBUFFER")
        if [ -n "$selected_dir" ]; then
          BUFFER="cd ${selected_dir}"
          zle accept-line
        fi
        zle clear-screen
      }
      zle -N peco-src
      bindkey '^]' peco-src
      
    • bashの場合
    • ~/.bashrcに以下を追記
      # Setting for peco
      function peco-src() {
        local selected_file=$(ghq list --full-path | peco --query "$LBUFFER")
        if [ -n "$selected_file" ]; then
          if [ -t 1 ]; then
            echo ${selected_file}
            cd ${selected_file}
            pwd
          fi
        fi
      }
      
      bind -x '"\201": peco-src'
      bind '"\C-]":"\201\C-m"'
      
  7. 端末を再起動

Clone repository

git cloneの代わりにghq getを使うと規定のディレクトリに勝手にクローンしてくれる

$ git clone git@gitlab.inoue-lab:inoue-lab/icn-hash.git

なら

$ ghq get git@gitlab.inoue-lab:inoue-lab/icn-hash.git

とすると

$GOPATH/gitlab.inoue-lab/inoue-lab/icn-hashにクローンされる

リポジトリに移動するときは ctrl + ] を押すと検索画面がでるのでそこで選択すると移動できる。

MacにTeX Live 2018の環境を整備する

概要

情報系など理工系でレポートを書くときに必須であるTeXをインストールします。 今回はLatexmkを用いて、様々なエディタからの利用を考えます。 TeX LiveをベースにしたmacOS専用のTeXディストリビューションであるMacTeXを使う。

MacTeX - TeX Wiki

blog.akashisn.info

blog.akashisn.info

brewコマンドを用いてもインストールできるのですが、公式からPKGをダウンロードしてインストールする。

構築する環境

  • macOS 10.14
  • MacTeX 2018

MacTeXのインストール

  1. ミラーサイトからMacTeX.pkgをダウンロードする。 http://mirror.ctan.org/pub/CTAN/systems/mac/mactex/MacTeX.pkg

  2. ダウンロードできたら、ダブルクリックしてインストール。

  3. パッケージを最新にアップデートする。
$ sudo tlmgr update --self --all
  1. デフォルトのページサイズをA4に設定する。
$ sudo tlmgr paper a4

これでMacTexの設定は終わり

LuaLaTeX、LuajitTeXについて

LaTeX の細かい知識に関心がなく、フォント設定の煩わしさを少しでも軽減したければ、この文書は読まずに XeLaTeX や LuaLaTeX への移行を考えましょう。

TeXとフォント - TeX Wiki

LuajitTeX は LuaTeX で使用されている Lua を LuaJIT に置き換えたものです. JIT とは Just-In-Time Compiler,つまりその場で機械語へのコンパイルを行うという意味であり,これによりインタプリタ方式の通常の Lua よりも高速な動作が期待できます.

LuajitTeX - TeX Wiki

特にこだわりがなければ、LuajitTeXに移行しましょう。

TeX処理系御伽話 - Qiita

LuajitTeXのセットアップ

LuaTeX-ja を使っているときなど、platex を使用しているときと比較して、その遅さに閉口させられることが少なくありません。当然、これは Lua を組み込んでいるからなのですが、Lua の実行時に機械語にコンパイル、実行を行う LuaJIT を使用した LuaJITTeX が、TeX Live には収録されています。

となれば、これを有効に使って LuaLaTeX を活用したいところです。Windows 版の TeX Live の場合は、luajitlatex.exe が収録されているので、従来 lualatex コマンドを使用していたところをそのまま luajitlatex に置き換えればよいだけです。 ところが、Linux 版や Mac OS 版の TeX Live には luajitlatex という名前の実行形式のファイルは収録されていません。そこで、ここでは Linux 版や Mac OS 版の TeX Live での luajitlatex の利用法について補足しておきます。 www.fugenji.org

上記を参考に設定する

パッケージの追加

CTANにあるパッケージであれば、

$ sudo tlmgr install (パッケージ名)

でインストールできる。

もしCTANになければ手動でインストールすることになる

本環境でのTeX Live 2018のインストールディレクトリは/usr/local/texlive/2018/となっている。

各パッケージは殆どの場合{Tex Liveのインストールディレクトリ}/texmf-dist/tex/latex/以下に、 *.styファイルなどを[パッケージ名]/[パッケージ本体]のように配置して、

$ sudo mktexlsr

を実行すればLaTeXが認識してくれる。

LaTeX入門/各種パッケージの利用 - TeX Wiki

Latexmkの設定をする

Latexmkとは、

Latexmkは文書を作成するのに必要な回数タイプセットしてくれるツールです。 BibTeXMakeindexなどの実行も自動で行われます。

Latexmk - TeX Wiki

以下のコマンドで公式ドキュメントを見ることができる。(英語のPDF)

$ texdoc latexmk

ホームディレクトリに以下のLatexmkの設定ファイルを.latexmkrcという名前で作成する。

#!/usr/bin/env perl
$lualatex                    = 'luajittex %O --fmt=luajitlatex.fmt -synctex=1 -interaction=nonstopmode %S';
$bibtex                      = 'pbibtex -kanji=utf8 %O %B';
$biber                       = 'biber --bblencoding=utf8 -u -U --output_safechars';
$makeindex                   = 'mendex %O -o %D %S';
$max_repeat                  = 5;
$pvc_view_file_via_temporary = 0;
$pdf_mode                    = 4;
$postscript_mode = $dvi_mode = 0;
$pdf_previewer               = "open -ga /Applications/Skim.app";

PDFビュアーをインストールする

$ brew cask install skim

これで、

$ latexmk hoge.tex

でビルドできるようになった。

実行時のオプション

  • -pv コンパイルが完了したら$pdf_previewerで指定したコマンドを使ってpdfのプレビューを表示してくれる。
  • -pvc -pvオプションと同じ。ただ、ソースファイルが更新されたら自動で再コンパイルをかけてくれる。
  • -c 変換途中に生成したファイルを削除してくれる。logファイルとか。
  • -C 出来たファイル全部消す。dviファイルとかpdfファイルとか。

latexmkを使う - Qiitaより

各エディタから使えるようにする

Latexmkを使用することで環境に依存せずにエディタの設定が行えるので以下を参照してエディタの設定を行う。

Visual Studio Code から使えるようにする

UbuntuにTeX Live 2018の環境を構築する - akashisnの日記

Sublime Text 3から使えるようにする

UbuntuにTeX Live 2018の環境を構築する - akashisnの日記