aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt
diff options
context:
space:
mode:
authorHarsh Shandilya <msfjarvis@gmail.com>2019-02-03 16:54:15 +0530
committerMohamed Zenadi <zeapo@users.noreply.github.com>2019-02-03 12:24:15 +0100
commit86696c668c08c8e283e840b6c54e40fa043c542a (patch)
treef36139bed1a6ae1589570b7fcf8aff2ad4d3d4a9 /app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt
parenta819343c747b2ce022c5a5c7810979a62a213dc5 (diff)
downloadHardenedPass-86696c668c08c8e283e840b6c54e40fa043c542a.tar.gz
HardenedPass-86696c668c08c8e283e840b6c54e40fa043c542a.zip
Convert PasswordEntry to Kotlin (#477)
Signed-off-by: Harsh Shandilya <msfjarvis@gmail.com>
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt')
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt114
1 files changed, 114 insertions, 0 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt
new file mode 100644
index 00000000..757681c5
--- /dev/null
+++ b/app/src/main/java/com/zeapo/pwdstore/PasswordEntry.kt
@@ -0,0 +1,114 @@
+package com.zeapo.pwdstore
+
+import android.net.Uri
+
+import java.io.ByteArrayOutputStream
+import java.io.UnsupportedEncodingException
+
+/**
+ * A single entry in password store.
+ */
+class PasswordEntry(private val content: String) {
+ val password: String
+ val username: String?
+ val totpSecret: String?
+ val hotpSecret: String?
+ val hotpCounter: Long?
+ var extraContent: String? = null
+ private set
+ private var isIncremented = false
+
+ @Throws(UnsupportedEncodingException::class)
+ constructor(os: ByteArrayOutputStream) : this(os.toString("UTF-8"))
+
+ init {
+ val passContent = content.split("\n".toRegex(), 2).toTypedArray()
+ password = passContent[0]
+ totpSecret = findTotpSecret(content)
+ hotpSecret = findHotpSecret(content)
+ hotpCounter = findHotpCounter(content)
+ extraContent = findExtraContent(passContent)
+ username = findUsername()
+ }
+
+ fun hasExtraContent(): Boolean {
+ return !extraContent.isNullOrEmpty()
+ }
+
+ fun hasUsername(): Boolean {
+ return username != null
+ }
+
+ fun hasTotp(): Boolean {
+ return totpSecret != null
+ }
+
+ fun hasHotp(): Boolean {
+ return hotpSecret != null && hotpCounter != null
+ }
+
+ fun hotpIsIncremented(): Boolean {
+ return isIncremented
+ }
+
+ fun incrementHotp() {
+ content.split("\n".toRegex()).forEach { line ->
+ if (line.startsWith("otpauth://hotp/")) {
+ extraContent = extraContent?.replaceFirst("counter=[0-9]+".toRegex(), "counter=${hotpCounter!! + 1}")
+ isIncremented = true
+ }
+ }
+ }
+
+ private fun findUsername(): String? {
+ val extraLines = extraContent!!.split("\n".toRegex())
+ for (line in extraLines) {
+ for (field in USERNAME_FIELDS) {
+ if (line.toLowerCase().startsWith("$field:")) {
+ return line.split(": *".toRegex(), 2).toTypedArray()[1]
+ }
+ }
+ }
+ return null
+ }
+
+ private fun findTotpSecret(decryptedContent: String): String? {
+ decryptedContent.split("\n".toRegex()).forEach { line ->
+ if (line.startsWith("otpauth://totp/")) {
+ return Uri.parse(line).getQueryParameter("secret")
+ }
+ }
+ return null
+ }
+
+ private fun findHotpSecret(decryptedContent: String): String? {
+ decryptedContent.split("\n".toRegex()).forEach { line ->
+ if (line.startsWith("otpauth://hotp/")) {
+ return Uri.parse(line).getQueryParameter("secret")
+ }
+ }
+ return null
+ }
+
+ private fun findHotpCounter(decryptedContent: String): Long? {
+ decryptedContent.split("\n".toRegex()).forEach { line ->
+ if (line.startsWith("otpauth://hotp/")) {
+ return java.lang.Long.parseLong(Uri.parse(line).getQueryParameter("counter")!!)
+ }
+ }
+ return null
+ }
+
+ private fun findExtraContent(passContent: Array<String>): String {
+ val extraContent = if (passContent.size > 1) passContent[1] else ""
+ // if there is a HOTP URI, we must return the extra content with the counter incremented
+ return if (hasHotp()) {
+ extraContent.replaceFirst("counter=[0-9]+".toRegex(), "counter=" + java.lang.Long.toString(hotpCounter!!))
+ } else extraContent
+ }
+
+ companion object {
+
+ private val USERNAME_FIELDS = arrayOf("login", "username")
+ }
+}