12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- package com.chameth.yaotp.accounts
-
- import com.chameth.yaotp.algos.HotpParams
- import com.chameth.yaotp.algos.TotpParams
- import com.chameth.yaotp.algos.getHmacFunc
- import com.chameth.yaotp.util.base32Decode
- import java.net.URI
-
- fun parseUri(uri: String) : Account? {
- return try {
- toAccount(URI.create(uri))
- } catch (_ : Exception) {
- null
- }
- }
-
- @Throws(IllegalArgumentException::class)
- internal fun toAccount(uri: URI): Account? {
- require(uri.scheme == "otpauth") { "Scheme must be 'otpauth', got '${uri.scheme}'" }
- require(uri.path.length > 1) { "No label specified" }
- requireNotNull(uri.query) { "No query string supplied" }
-
- val label = uri.path.substring(1)
- val params = uri.queryParameters()
- require("secret" in params) { "No 'secret' parameter specified, got ${params.keys}"}
-
- return when(uri.host) {
- "hotp" -> getHotpAccount(label, params)
- "totp" -> getTotpAccount(label, params)
- else -> throw IllegalArgumentException("Unrecognised type: ${uri.host}")
- }
- }
-
- internal fun getHotpAccount(label: String, uriParams: Map<String, String>): HotpAccount {
- val counter = uriParams["counter"]?.toLongOrNull()
- requireNotNull(counter) { "No 'counter' parameter specified for HOTP" }
- return HotpAccount(label, uriParams["issuer"], counter!!, getHotpParameters(uriParams))
- }
-
- fun getTotpAccount(label: String, uriParams: Map<String, String>): TotpAccount {
- val step = uriParams["step"]?.toIntOrNull() ?: 30
- return TotpAccount(label, uriParams["issuer"], TotpParams(getHotpParameters(uriParams), step = step))
- }
-
- internal fun getHotpParameters(uriParams : Map<String, String>) : HotpParams {
- return HotpParams(
- base32Decode(uriParams["secret"] ?: ""),
- uriParams["digits"]?.toIntOrNull() ?: 6,
- getHmacFunc(uriParams["algorithm"])
- )
- }
-
- internal fun URI.queryParameters(): Map<String, String> {
- return query.split('&').map { with(it.split('=', limit = 2)) { this[0] to this[1] } }.toMap()
- }
|