aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/dev/msfjarvis/aps/util/crypto/GpgIdentifier.kt
blob: 51b3b76b839b9bac59c5ba5e68abc1a3c706b778 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package dev.msfjarvis.aps.util.crypto

import me.msfjarvis.openpgpktx.util.OpenPgpUtils

sealed class GpgIdentifier {
    data class KeyId(val id: Long) : GpgIdentifier()
    data class UserId(val email: String) : GpgIdentifier()

    companion object {
        @OptIn(ExperimentalUnsignedTypes::class)
        fun fromString(identifier: String): GpgIdentifier? {
            if (identifier.isEmpty()) return null
            // Match long key IDs:
            // FF22334455667788 or 0xFF22334455667788
            val maybeLongKeyId = identifier.removePrefix("0x").takeIf {
                it.matches("[a-fA-F0-9]{16}".toRegex())
            }
            if (maybeLongKeyId != null) {
                val keyId = maybeLongKeyId.toULong(16)
                return KeyId(keyId.toLong())
            }

            // Match fingerprints:
            // FF223344556677889900112233445566778899 or 0xFF223344556677889900112233445566778899
            val maybeFingerprint = identifier.removePrefix("0x").takeIf {
                it.matches("[a-fA-F0-9]{40}".toRegex())
            }
            if (maybeFingerprint != null) {
                // Truncating to the long key ID is not a security issue since OpenKeychain only accepts
                // non-ambiguous key IDs.
                val keyId = maybeFingerprint.takeLast(16).toULong(16)
                return KeyId(keyId.toLong())
            }

            return OpenPgpUtils.splitUserId(identifier).email?.let { UserId(it) }
        }
    }
}