Passphrase & hint can now be set.

- Built-in password list
This commit is contained in:
2020-07-12 00:30:57 +02:00
parent 8865e9a394
commit 1bb1b55452
7 changed files with 183220 additions and 40 deletions

View File

@@ -1,10 +1,7 @@
package com.github.mondei1.offpass
import android.annotation.SuppressLint
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.*
import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.graphics.Color
@@ -15,11 +12,14 @@ import android.print.PrintJob
import android.print.PrintManager
import android.util.Base64
import android.util.Log
import android.view.ContextThemeWrapper
import android.view.View
import android.view.WindowManager
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.google.zxing.BarcodeFormat
import com.google.zxing.integration.android.IntentIntegrator
@@ -27,6 +27,8 @@ import com.google.zxing.integration.android.IntentResult
import com.journeyapps.barcodescanner.BarcodeEncoder
import dev.turingcomplete.kotlinonetimepassword.GoogleAuthenticator
import kotlinx.android.synthetic.main.activity_create.*
import kotlinx.android.synthetic.main.dialogpassphrase.*
import kotlinx.android.synthetic.main.dialogpassphrase.view.*
import kotlinx.coroutines.*
import java.io.ByteArrayOutputStream
import java.util.*
@@ -39,7 +41,31 @@ class CreateActivity : AppCompatActivity() {
private var mWebView: WebView? = null
private var printJob: PrintJob? = null
fun doPrint() {
private var fa_uri: Uri? = null
/**
* Gets triggered when the user clicks on printing button (top left) and renders the paper to
* print.
*/
fun doPrint(passphrase: String, hint: String) {
// Set up printing
this.schema = QRSchema(this)
this.schema!!.title = title_input.text.toString()
this.schema!!.username = username_input.text.toString()
this.schema!!.password = password_input.text.toString()
this.schema!!.email = email_input.text.toString()
this.schema!!.website_url = url_input.text.toString()
if (fa_uri != null) {
this.schema!!.custom.put("2fa", fa_uri.toString())
}
this.schema!!.build(arrayOf(), passphrase)
val barcodeEncoder: BarcodeEncoder = BarcodeEncoder()
this.qrCodeBitmap = barcodeEncoder.encodeBitmap(this.schema!!.raw, BarcodeFormat.QR_CODE, 400, 400)
val webView = WebView(this)
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, requesst: WebResourceRequest) = false
@@ -59,7 +85,7 @@ class CreateActivity : AppCompatActivity() {
var byteArrayOutputStream = ByteArrayOutputStream()
this.qrCodeBitmap?.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)
htmlDocument = htmlDocument.replace("\$DATE", Date().time.toString())
.replace("\$HINT", "Not configurable yet!")
.replace("\$HINT", hint)
.replace("\$QRCODE", Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.NO_WRAP))
Log.i("Create Activity", htmlDocument)
@@ -68,6 +94,9 @@ class CreateActivity : AppCompatActivity() {
mWebView = webView
}
/**
* Invoked after doPrint() and takes the rendered web view and creates a new print job.
*/
fun createWebPrintJob(webView: WebView) {
(this.getSystemService(Context.PRINT_SERVICE) as? PrintManager)?.let { printManager ->
val jobName = "Offpass Document"
@@ -83,15 +112,49 @@ class CreateActivity : AppCompatActivity() {
}
}
/**
* Invoked when user gave empty passphrase.
*/
fun showError(title: String, body: String) {
val builder = AlertDialog.Builder(ContextThemeWrapper(this, R.style.ErrorDialog))
with(builder) {
setTitle(title)
setMessage(body)
setPositiveButton("Got it", DialogInterface.OnClickListener { dialogInterface, i ->
dialogInterface.dismiss()
})
show()
}
}
fun passwordKnown(password: String): Boolean {
val known_passwords = String(this.resources.openRawResource(
this.resources.getIdentifier("passwordlist", "raw", this.packageName)
).readBytes())
val known_passwords_array = runBlocking {
known_passwords.split("\n")
}
Log.i("Create Activity", "Size of passwords: ${known_passwords_array.size}")
return known_passwords_array.contains(password)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Prevent other apps from making screenshots or to record Offpass.
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
this.schema = QRSchema(this)
this.schema!!.decrypted_raw = "%JtuB4O9M42%Gitea|Nicolas|542superGoOD_pW&|klier.nicolas@protonmail.com|\$ul|(\$vb)\$O4|()What's your favorite series%Rick and morty|(2fa)otpauth://totp/OffPass%20Test?secret=d34gfkki5dkd5knifysrpgndd5xb2c7eddwki7ya4pvoisfa5c3ko5pv&issuer=Nicolas%20Klier"
/*this.schema!!.decrypted_raw = "%JtuB4O9M42%Gitea|Nicolas|542superGoOD_pW&|klier.nicolas@protonmail.com|\$ul|(\$vb)\$O4|()What's your favorite series%Rick and morty|(2fa)otpauth://totp/OffPass%20Test?secret=d34gfkki5dkd5knifysrpgndd5xb2c7eddwki7ya4pvoisfa5c3ko5pv&issuer=Nicolas%20Klier"
this.schema!!.parse(this)
this.schema!!.build(arrayOf("website_url", "2fa", "What's your favorite series"), "123")
this.schema!!.decrypt(this.schema!!.raw, "123")
this.schema!!.decrypt(this.schema!!.raw, "123")*/
setSupportActionBar(findViewById(R.id.toolbar))
@@ -101,18 +164,48 @@ class CreateActivity : AppCompatActivity() {
finish()
}
print_button.setOnClickListener {
// Set up printing
this.schema = QRSchema(this)
this.schema!!.title = title_input.text.toString()
this.schema!!.username = username_input.text.toString()
this.schema!!.password = password_input.text.toString()
this.schema!!.email = email_input.text.toString()
this.schema!!.website_url = url_input.text.toString()
this.schema!!.build(arrayOf(), "123")
// Ask user for passhprase and hint
val builder = AlertDialog.Builder(ContextThemeWrapper(this, R.style.PassphraseDialog))
with(builder) {
val editTextLayout = layoutInflater.inflate(R.layout.dialogpassphrase, null)
setView(editTextLayout)
setTitle("Set Passphrase")
setMessage("Final step is it to set your passphrase. Minimum are 8 characters.")
setPositiveButton("Print", DialogInterface.OnClickListener { dialogInterface, i ->
val passphrase = editTextLayout.passphrase_input.text.toString();
if (passphrase == "") {
// Make a new alert, telling the user that passphrase must not be null.
dialogInterface.cancel()
showError("Empty passphrase", "Passphrase must not be null.")
return@OnClickListener
}
if (passphrase.length < 8) {
// Make a new alert, telling the user that his passphrase doesn't meet the minimum.
dialogInterface.cancel()
showError("Weak passphrase", "Passphrase has to be at least 8 characters long.")
return@OnClickListener
}
// Check if password is found in our offline password list
if(passwordKnown(passphrase)) {
// Make a new alert, telling the user that his passphrase was found in our local wordlist.
dialogInterface.cancel()
showError("Passphrase is compromised!", "Passphrase got found in a wordlist of bad passwords. " +
"If you already used it somewhere, change it immediately!")
return@OnClickListener
}
doPrint(editTextLayout.passphrase_input.text.toString(),
editTextLayout.hint_input.text.toString())
})
setNegativeButton("Go back", DialogInterface.OnClickListener { dialogInterface, i ->
dialogInterface.dismiss()
})
show()
}
val barcodeEncoder: BarcodeEncoder = BarcodeEncoder()
this.qrCodeBitmap = barcodeEncoder.encodeBitmap(this.schema!!.raw, BarcodeFormat.QR_CODE, 400, 400)
doPrint()
}
fa_input.isFocusable = false
@@ -148,8 +241,9 @@ class CreateActivity : AppCompatActivity() {
// We scanned a 2FA code
if (result.contents.startsWith("otpauth://totp/")) {
fa_progress.visibility = View.VISIBLE
val fa_uri = Uri.parse(result.contents)
val fa_generator = GoogleAuthenticator(base32secret = fa_uri.getQueryParameter("secret").toString())
fa_uri = Uri.parse(result.contents)
val fa_generator = GoogleAuthenticator(base32secret = fa_uri?.getQueryParameter("secret").toString())
this.schema!!.custom.put("2fa", fa_uri?.getQueryParameter("secret").toString())
/*val objAnim: ObjectAnimator = ObjectAnimator.ofInt(fa_progress, "progress")
objAnim.duration = 300
@@ -180,7 +274,7 @@ class CreateActivity : AppCompatActivity() {
}
}
fa_label.text = "${fa_uri.path?.replace("/", "")} (${fa_uri.getQueryParameter("issuer")})"
fa_label.text = "${fa_uri?.path?.replace("/", "")} (${fa_uri?.getQueryParameter("issuer")})"
}
}
}