OpenID Connect のメモ
Amazon Cognito の署名検証のコードを書いたので一旦メモとして残す。
import java.math.BigInteger import java.net.URI import java.security.interfaces.RSAPublicKey import java.security.spec.RSAPublicKeySpec import java.security.{KeyFactory, PublicKey} import java.util.Base64 import com.auth0.jwt.JWT import com.auth0.jwt.algorithms.Algorithm import spray.json._ private case class Key(alg: String, e: String, kid: String, kty: String, n: String, use: String) private case class JwksJson(keys: Array[Key]) private object JwksJsonProtocol extends DefaultJsonProtocol { implicit val keyJsonFormat = jsonFormat6(Key) implicit val inputJsonFormat = jsonFormat(JwksJson, "keys") } trait OpenIDConnectGetKey { val openIdConnectUrl: String private lazy val jwksJsonUrl = new URI(openIdConnectUrl.concat("/.well-known/jwks.json")) private var keys: Map[String, PublicKey] = Map.empty def openIDConnectGetKeys: Map[String, PublicKey] = { import JwksJsonProtocol._ val input = jwksJsonUrl.toURL.openStream() try { val bytes = Stream.continually(input.read).takeWhile(_ != -1).map(_.toByte).toArray val jwksJson = JsonParser(bytes).convertTo[JwksJson] keys ++= jwksJson.keys.map { key => val kty = key.kty val modulus = new BigInteger(1, Base64.getUrlDecoder.decode(key.n)) val publicExponent = new BigInteger(1, Base64.getUrlDecoder.decode(key.e)) val keySpec = new RSAPublicKeySpec(modulus, publicExponent) key.kid -> KeyFactory.getInstance(kty).generatePublic(keySpec) }.toMap keys } finally { input.close() } } def verify(idToken: String): JsValue = { val jwt = JWT.decode(idToken) val maybePublicKey = keys.get(jwt.getKeyId) match { case None => openIDConnectGetKeys.get(jwt.getKeyId) case s => s } maybePublicKey map { publicKey => val algorithm = Algorithm.RSA256(publicKey.asInstanceOf[RSAPublicKey], null) val verification = JWT.require(algorithm) verification.build().verify(jwt) } getOrElse(throw new RuntimeException(s"Not exists ${jwt.getKeyId}")) JsonParser(Base64.getUrlDecoder().decode(jwt.getPayload)) } }
Java で書いてみた
import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.Verification; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.net.URI; import java.net.URISyntaxException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.RSAPublicKeySpec; import java.util.Base64; import java.util.HashMap; import java.util.Map; public interface OpenIDConnectGetKeys { Map<String, KeyItem> getKeys(); void saveKeys(Map<String, KeyItem> keys); String getOpenIdConnectUrl(); default URI getJwksJsonUrl() throws URISyntaxException { return new URI(getOpenIdConnectUrl().concat("/.well-known/jwks.json")); } default BigInteger decodeBase64UrlUInt(String value) { byte[] uintBinary = Base64.getUrlDecoder().decode(value); return new BigInteger(1, uintBinary); } default Map<String, KeyItem> openIDConnectGetKeys() throws URISyntaxException, IOException { try (InputStream input = getJwksJsonUrl().toURL().openStream()) { Map<String, KeyItem> map = new HashMap(); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); while (true) { int ch = input.read(); if (ch == -1) { break; } buffer.write(ch); } ObjectMapper mapper = new ObjectMapper(); Keys keys = mapper.readValue(buffer.toByteArray(), Keys.class); for (KeyItem key: keys.keys) { map.put(key.kid, key); } return map; } } default HashMap<String, Object> verify(String idToken) throws TokenVerifyException { try { DecodedJWT jwt = JWT.decode(idToken); Map<String, KeyItem> keys = getKeys(); if (!keys.containsKey(jwt.getKeyId())) { keys = openIDConnectGetKeys(); saveKeys(keys); } KeyItem key = keys.get(jwt.getKeyId()); if (key != null) { BigInteger modulus = decodeBase64UrlUInt(key.n); BigInteger publicExponent = decodeBase64UrlUInt(key.e); KeySpec spec = new RSAPublicKeySpec(modulus, publicExponent); RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(spec); Algorithm algorithm = Algorithm.RSA256(publicKey, null); Verification verification = JWT.require(algorithm); verification.build().verify(jwt); ObjectMapper mapper = new ObjectMapper(); TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {}; return mapper.readValue(Base64.getUrlDecoder().decode(jwt.getPayload()), typeRef); } else { throw new TokenVerifyException(String.format("Not exists %s", jwt.getKeyId())); } } catch (IOException e) { throw new TokenVerifyException(e); } catch (NoSuchAlgorithmException e) { throw new TokenVerifyException(e); } catch (URISyntaxException e) { throw new TokenVerifyException(e); } catch (InvalidKeySpecException e) { throw new TokenVerifyException(e); } } }
古くなったMacBook ProからバッテリーとHDDを取り出した
気づくと、バッテリーがパンパンに膨らんでいて、とりあえず、バッテリーとHDDを取り出そうと MacBook Pro の分解をはじめました
以前、バッテリーをはずすYドライバーは購入していたのですが、バッテリーの膨らみにより簡単には外せませんでした。もっと早く外しておけばよかったと後悔。
目的のハードディスクは、ホームセンターで購入した精密ドライバーセット(EPS-650)を使って外しました。
参考にした記事

E-Value 精密ドライバーセット EPS-650(1セット)【E-VaLue】
- ジャンル: 電動ドライバー・電動ドリル用部品・アクセサリ
- ショップ: 楽天24
- 価格: 1,360円
HeadlessなDebianをmacOSのVirtualBox上に構築したメモ
ホストオンリーアダプターを追加
/etc/network/interfaces にホストオンリーアダプターを追記
allow-hotplug enp0s8 iface enp0s8 inet dhcp
ホストオンリーアダプターに設定された IP Address の確認
$ ip addr show
Installing the Linux Guest Additions
# mount /dev/cdrom /media/cdrom # apt-get install -y dkms build-essential linux-headers-$(uname -r) # ./VBoxLinuxAdditions.run
ヘッドレス起動
VBoxHeadless, the Remote Desktop Server
$ VBoxManage startvm "VM name" --type headless
FireタブレットにMacからUSBでファイル転送
Google で配布されているAndroid File Transferで転送できる。
Fire用のVLC for Fire、Chromecastで再生できる。
Ubuntu 18.04 に pyenv と Python 3.7.2 をインストールしたメモ
$ sudo apt-get install git $ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
export PYENV_ROOT=$HOME/.pyenv export PATH=${PYENV_ROOT}/bin:$PATH eval "$(pyenv init -)"
$ sudo apt-get install gcc make $ sudo apt-get install libssl-dev \ libbz2-dev \ libreadline-dev \ libsqlite3-dev $ sudo apt-get install zlib1g-dev $ sudo apt-get install libffi-dev
$ pyenv install -v 3.7.2
VirtualBox に Ubuntu 18.04 と Docker をインストールしたメモ
- VirtualBox
- Ubuntu 18.04
VirtualBox 上の Ubuntu に ssh でログインするために、openssh-server をインストール
$ sudo apt-get install openssh-server
Docker CE をインストール
$ sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - $ sudo add-apt-repository \ "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable" $ sudo apt-get update $ sudo apt-get install docker-ce docker-ce-cli containerd.io $ sudo gpasswd -a your-user docker
確認
$ docker run hello-world
MacBook に pyenv をインストールしたときのメモ
- macOS Mojave 10.14.4
Homebrew
$ brew install pyenv
.bash_profileの編集
$HOME/.bash_profile
export PYENV_ROOT=$HOME/.pyenv export PATH=$(pyenv root)/shims:$PATH
Pythonのインストール
$ sudo installer \ -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg \ -target / $ pyenv install 3.7.2 $ pyenv global 3.7.2