Google Authenticator から secret を抽出する方法

まず、エクスポートから QRコードを表示。

Google Authenticator から secret を抽出する

テキスト化します。



otpauth-migration://offline?data=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

※ 登録数が多ければ、XXX.. は、すごく長いです。

それをさらに以下のツールでデコードします。

👉 dim13/otpauth: Google Authenticator migration decoder hatena-bookmark

go を入れるのがだるいので対応するバイナリをダウンロードします。

dim13/otpauth: Google Authenticator migration decoder
👉 Release v0.5.1 · dim13/otpauth hatena-bookmark

どれなのか、良くわからないので、インストール先を調べます。


❯ uname -a
Darwin iMac.local 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023; root:xnu-8792.81.3~2/RELEASE_X86_64 x86_64

❯ uname -m
x86_64

otpauth-v0.5.1-darwin-amd64.tgz をダウンロードして展開します。M1+なら「arm64」

先に取得したテキストを渡して実行します。


❯ ./otpauth -link "otpauth-migration://offline?data=XXXXX..."

otpauth://totp/Example%20Company:test@example.com?algorithm=SHA1&digits=6&issuer=Example+Company&period=30&secret=QUU6EA2GHORGMD22SN2YKU6VKISCKYAG
otpauth://totp/Henrik%20Schacks%20blog?algorithm=SHA1&digits=6&period=30&secret=5YGQ4IAR32CYA6PY
otpauth://totp/auth@test.com?algorithm=SHA1&digits=6&issuer=MyCompanyName.AbpZeroTemplate&period=30&secret=MFRDCZDFMQ3DAMDC
otpauth://totp/WordPress:ThinkingTeapot?algorithm=SHA1&digits=6&issuer=WordPress&period=30&secret=S55IFILZLA6DESAO
otpauth://totp/Google:example@gmail.com?algorithm=SHA1&digits=6&issuer=Google&period=30&secret=QJV3EN5JJJHGQ4PK3M6E576YMWUC5D4X
...

これの secret パラメータがそれ。base32 でエンコードされた文字列です。

👉 RFC 6238: TOTP: Time-Based One-Time Password Algorithm hatena-bookmark

他のTOTPジェネレータにも登録しておくと安心できます。

👉 「GitHub」で2要素認証の義務化、3月13日から - ケータイ Watch hatena-bookmark


AndroidStudioでMarkdownプレビューが表示されない時の対処法

プラグインは対応はしてるのに未だ表示されず。

👉 Markdown - IntelliJ IDEs Plugin | Marketplace hatena-bookmark

一時期は表示されてたことありませんでしたっけ。

 

■ プレビューを表示させる

これ。

The Java Chromium Embedded Framework (JCEF) is a simple framework for embedding Chromium-based browsers in other applications using the Java programming language.

👉 JetBrains/jcef: A simple framework for embedding Chromium-based browsers into Java-based applications. hatena-bookmark

AndroidStudio 稼働のための Java を JCEF が含まれているものに変更すればプレビューを表示できるようです。

da...@khol.me #19Jun 30, 2022 12:57PM
Based on #7

TLDR for https://intellij-support.jetbrains.com/hc/en-us/articles/206544879-Selecting-the-JDK-version-the-IDE-will-run-under:

In the Android Studio:

1. Find action (ctrl + shift + A / command + shift + A)
2. Search for Choose Boot Java Runtime for the IDE
3. Select the latest version in the "New:" dropdown - e.g. 11.0.12+7-b1504.27 JetBrains Runtime with JCEF
4. OK
5. Restart
Worked in: Android Studio Chipmunk | 2021.2.1 Patch 1 | Build #AI-212.5712.43.2112.8609683

👉 Regression in markdown support (crashes 100% of the time). Missing JCEF [159933628] - Visible to Public - Issue Tracker hatena-bookmark

リスタートすると正しく表示されました。

 

■ まとめ

lo...@gmail.com #20Jul 1, 2022 03:48AM
Why isn't it the default?

ほんとそう、なんか問題あるんでしょうか、未検証なのでしょうか?

ちなみに、Mermaid プラグインははっきり未対応のようです。

👉 Mermaid - IntelliJ IDEs Plugin | Marketplace hatena-bookmark


Kotlin で Jetpack Compose, Retrofit を使って API リクエスト、JSON パース して、グリッド表示するコードをファイル別に表示して

Kotlin で Jetpack Compose と Retrofit を使って API リクエスト、JSON パースして、グリッド表示するためには、以下のようにファイルを分けることができます。

 

1. API リクエストを行うための Retrofit インターフェースを定義するファイル


interface ApiService {

    @GET("/photos")
    suspend fun getPhotos(): List<Photo>
}

 

2. API レスポンスを表すデータクラスを定義するファイル


data class Photo(
    val id: Int,
    val title: String,
    val url: String
)

 

3. API レスポンスをパースして、表示するための画面を定義するファイル


@Composable
fun PhotoGrid() {
    val photos by remember { mutableStateOf<List<Photo>>(emptyList()) }

    LaunchedEffect(Unit) {
        val apiService = Retrofit.Builder()
            .baseUrl("https://jsonplaceholder.typicode.com")
            .addConverterFactory(Json {
                ignoreUnknownKeys = true
            }.asConverterFactory("application/json".toMediaType()))
            .build()
            .create(ApiService::class.java)

        photos = apiService.getPhotos()
    }

    LazyVerticalGrid(cells = GridCells.Adaptive(minSize = 128.dp)) {
        items(photos) { photo ->
            Card(
                modifier = Modifier.padding(4.dp),
                shape = RoundedCornerShape(8.dp),
                elevation = 4.dp
            ) {
                Column(
                    Modifier
                        .fillMaxWidth()
                        .height(128.dp)
                        .padding(8.dp)
                ) {
                    Text(
                        text = photo.title,
                        style = MaterialTheme.typography.subtitle1,
                        maxLines = 2,
                        overflow = TextOverflow.Ellipsis
                    )
                    Spacer(modifier = Modifier.weight(1f))
                    CoilImage(
                        data = photo.url,
                        contentScale = ContentScale.Crop,
                        modifier = Modifier.fillMaxSize()
                    )
                }
            }
        }
    }
}

 

4. 上記の画面を表示するための Activity もしくは Fragment を定義するファイル


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            PhotoGrid()
        }
    }
}

以上のように、ファイルを分けることで、API リクエストやパース、表示を分離し、コードを見やすく、メンテナンスしやすくすることができます。

 

■ 感想

ただ、一行問いかけただけ。

ChatGPT で、ここまで書けるとは。