Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/ktlint-plugin.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

152 changes: 68 additions & 84 deletions Privacy Policy.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,68 @@
# Privacy Policy

Aditya Bhardwaj built the PassKey app as an Open Source app. This SERVICE is provided by Aditya
Bhardwaj at no cost and is intended for use as is.
This page is used to inform visitors regarding my policies with the collection, use, and disclosure
of Personal Information if anyone decided to use my Service.
If you choose to use my Service, then you agree to the collection and use of information in relation
to this policy. The Personal Information that I collect is used for providing and improving the
Service. I will not use or share your information with anyone except as described in this Privacy
Policy.
The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which
are accessible at PassKey unless otherwise defined in this Privacy Policy.

# Information Collection and Use

For a better experience, while using our Service, I may require you to provide us with certain
personally identifiable information, including but not limited to Aditya Bhardwaj. The information
that I request will be retained on your device and is not collected by me in any way.
The app does use third-party services that may collect information used to identify you.
Link to the privacy policy of third-party service providers used by the app
Google Play Services

# Log Data

I want to inform you that whenever you use my Service, in a case of an error in the app I collect
data and information (through third-party products) on your phone called Log Data. This Log Data may
include information such as your device Internet Protocol (“IP”) address, device name, operating
system version, the configuration of the app when utilizing my Service, the time and date of your
use of the Service, and other statistics.

# Cookies

Cookies are files with a small amount of data that are commonly used as anonymous unique
identifiers. These are sent to your browser from the websites that you visit and are stored on your
device's internal memory.
This Service does not use these “cookies” explicitly. However, the app may use third-party code and
libraries that use “cookies” to collect information and improve their services. You have the option
to either accept or refuse these cookies and know when a cookie is being sent to your device. If you
choose to refuse our cookies, you may not be able to use some portions of this Service.

# Service Providers

I may employ third-party companies and individuals due to the following reasons:
To facilitate our Service;
To provide the Service on our behalf;
To perform Service-related services; or
To assist us in analyzing how our Service is used.
I want to inform users of this Service that these third parties have access to their Personal
Information. The reason is to perform the tasks assigned to them on our behalf. However, they are
obligated not to disclose or use the information for any other purpose.

# Security

I value your trust in providing us your Personal Information, thus we are striving to use
commercially acceptable means of protecting it. But remember that no method of transmission over the
internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its
absolute security.

# Links to Other Sites

This Service may contain links to other sites. If you click on a third-party link, you will be
directed to that site. Note that these external sites are not operated by me. Therefore, I strongly
advise you to review the Privacy Policy of these websites. I have no control over and assume no
responsibility for the content, privacy policies, or practices of any third-party sites or services.

# Children’s Privacy

These Services do not address anyone under the age of 13. I do not knowingly collect personally
identifiable information from children under 13 years of age. In the case I discover that a child
under 13 has provided me with personal information, I immediately delete this from our servers. If
you are a parent or guardian and you are aware that your child has provided us with personal
information, please contact me so that I will be able to do the necessary actions.

# Changes to This Privacy Policy

I may update our Privacy Policy from time to time. Thus, you are advised to review this page
periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on
this page.
This policy is effective as of 2022-08-30

# Contact Us

If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me at
yrkkh.cclub@gmail.com.
# Privacy Policy — PassKey: Password Manager

_Last updated: 2026-09-16_

## Summary

Your vault stays on your device. PassKey has no account, no sync and no server of its own. The
app does, however, bundle Google Firebase and Google Play libraries that send diagnostic and
usage data to Google. This document says exactly what does and does not leave your phone.

## What we never collect

PassKey does not collect, transmit or store the passwords, usernames, notes or any other entries
you save. They exist only in an encrypted database on your device.

We cannot read your entries and we cannot recover them for you. There is no server-side copy.

## What the app does send

PassKey includes the following third-party components, all provided by Google:

| Component | What it sends |
|---|---|
| Firebase Crashlytics | Crash stack traces, device model, OS version, app version, a Crashlytics installation identifier |
| Firebase Analytics | App usage events, session and screen information, device and installation identifiers, and an advertising ID (`AD_ID`) |
| Firebase Performance Monitoring | Startup, screen rendering and trace timings |
| Google Play in-app updates | Communicates with the Play Store to check for and install updates |

Because of these components the app requests the `INTERNET` permission, along with
`ACCESS_NETWORK_STATE`, `WAKE_LOCK`, `AD_ID` and the Play AdServices attribution permissions.
None of these components has access to your vault contents.

Data handled by these services is processed by Google under
[Google's privacy policy](https://policies.google.com/privacy).

## Backups

When you export a backup, the file is encrypted with AES-256-GCM using a key derived from a
password you choose, and written to the location you pick through the system file picker.

That file is then yours to manage. Anyone who obtains **both** the file and its password can read
it. We keep no copy and cannot recover the password for you.

## Device backup

PassKey sets `android:allowBackup="false"` and excludes its data from both Android cloud backup
and device-to-device transfer, so your vault is not uploaded to your Google account.

## Permissions

| Permission | Why |
|---|---|
| `USE_BIOMETRIC` | Unlocking the vault |
| `INTERNET`, `ACCESS_NETWORK_STATE`, `WAKE_LOCK` | Required by the Firebase and Google Play libraries above |
| `AD_ID`, AdServices permissions | Merged in by Firebase Analytics |

## Children

PassKey is not directed at children and does not knowingly collect information from them.

## Changes

This policy may be updated. Material changes will be noted in the app's release notes and in this
file's history.

## Contact

yrkkh.cclub@gmail.com
53 changes: 37 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,43 @@ design -> https://www.figma.com/community/file/1116675775484733517

## 🤩 Features:

- Kotlin & Jetpack Compose.
- Clean Architecture.
- Kotlin Flows.
- Dark Mode Support.
- Biometric Authentication.
- Dagger-Hilt (Dependency Injection).
- DataStore Preferences.
- Encrypted Database.
- Screenshot Blocked.
- Open Source.
- Drag & Drop to reorder list.
- Swipe to Delete Feature.
- Separation of content.
- Import / Export data to and from storage.
- SQL Cipher (For Room DB Encryption and Decryption).
- Fully Offline : No internet permission required.
- Kotlin & Jetpack Compose, Material 3.
- Clean architecture with Kotlin Flows and Dagger-Hilt.
- Encrypted database (Room + SQLCipher).
- Biometric / device-credential unlock, with automatic re-lock on background and idle.
- Screenshot blocking, including dialogs and bottom sheets.
- Clipboard entries marked sensitive and cleared automatically.
- Password generator backed by SecureRandom.
- Vault analysis for weak and reused passwords.
- Password-protected encrypted backup and restore, written wherever you choose.
- Excluded from Android cloud backup and device-to-device transfer.
- Drag & drop reordering, swipe to delete, category separation.
- Dark mode and 17 languages.
- Open source.

## 🔐 Security model:

- The vault is a Room database encrypted with SQLCipher, stored only on the device.
- It is unlocked with device biometrics or the screen lock, and re-locks automatically after a
configurable idle period.
- Backups are encrypted with AES-256-GCM under a key derived from a password you choose
(PBKDF2-HMAC-SHA512), written through the system file picker.
- The app performs no network requests of its own and has no server or account.

> **Known limitation, being addressed in 5.7.0:** the database key is currently a single
> build-time constant shared by every install, so the database is encrypted against someone who
> obtains the file alone, and not against someone who also has the APK. 5.7.0 replaces it with a
> per-install random key wrapped by an Android Keystore key and unlocked via a biometric
> `CryptoObject`, with a password-based recovery slot.

## 🌐 Network and privacy:

The app itself makes no network calls, but it bundles Google Firebase (Crashlytics, Analytics,
Performance Monitoring) and Google Play in-app updates. These require the `INTERNET` permission
and send crash diagnostics, usage events, performance traces and device/installation identifiers
— including an advertising ID — to Google. They never have access to vault contents. See
[Privacy Policy.md](Privacy%20Policy.md).


## 🌎 Released Android Application:

Expand Down
63 changes: 49 additions & 14 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import java.util.Properties

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose.compiler)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.ksp)
alias(libs.plugins.hilt.android)
alias(libs.plugins.room)
Expand All @@ -14,20 +14,32 @@ plugins {

android {
namespace = "com.bhardwaj.passkey"
compileSdk = 36
compileSdk = 37

defaultConfig {
applicationId = "com.bhardwaj.passkey"
minSdk = 28
targetSdk = 36
versionCode = 43
versionName = "5.5.1"
versionCode = 46
versionName = "5.7.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

val properties = Properties()
properties.load(project.rootProject.file("local.properties").inputStream())
buildConfigField("String", "PASS_PHRASE", "\"${properties.getProperty("PASS_PHRASE")}\"")
// local.properties is gitignored, so a fresh clone or CI checkout will not have it.
// Loading it unconditionally threw FileNotFoundException and broke configuration.
val localProperties = Properties().apply {
val file = project.rootProject.file("local.properties")
if (file.exists()) file.inputStream().use { load(it) }
}
// Renamed from PASS_PHRASE: this value only exists to open pre-5.7 databases that were
// encrypted with the old build-time constant, so they can be re-keyed. Never use it for
// new vaults. Note that when the key is absent the historical builds embedded the literal
// string "null", which the migration also has to treat as a candidate.
buildConfigField(
"String",
"LEGACY_PASS_PHRASE",
"\"${localProperties.getProperty("PASS_PHRASE")}\""
)

vectorDrawables {
useSupportLibrary = true
Expand Down Expand Up @@ -58,18 +70,31 @@ android {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_22
targetCompatibility = JavaVersion.VERSION_22
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
kotlin {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_22)
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
}
}
buildFeatures {
compose = true
buildConfig = true
}
lint {
// The onboarding strings shipped in English to all 16 locales for several releases
// because they were marked translatable="false", which also suppressed this check.
// Failing the build is what stops that recurring.
error += setOf(
"MissingTranslation",
"ExtraTranslation",
"ImpliedQuantity",
"StringFormatInvalid",
"StringFormatMatches"
)
abortOnError = true
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
Expand Down Expand Up @@ -102,6 +127,8 @@ dependencies {
implementation(libs.androidx.appcompat)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.lifecycle.viewmodel.compose)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.lifecycle.process)
implementation(libs.androidx.navigation.compose)

// Coroutines
Expand All @@ -114,9 +141,6 @@ dependencies {
ksp(libs.hilt.compiler)
implementation(libs.hilt.navigation.compose)

// Splash Screen
implementation(libs.androidx.core.splashscreen)

// DataStore Preferences
implementation(libs.datastore.preferences)

Expand All @@ -133,9 +157,15 @@ dependencies {
implementation(libs.sqlcipher.android)
implementation(libs.sqlcipher.sqlite)

// Open CSV - Import/ Export Data
// Open CSV - used by the read-only legacy .passkey CSV importer
implementation(libs.opencsv)

// Backup payload serialization
implementation(libs.kotlinx.serialization.json)

// Argon2id for the recovery-password key slot
implementation(libs.argon2kt)

// Reordering Lazy Columns
implementation(libs.reorderable)

Expand All @@ -144,13 +174,18 @@ dependencies {
implementation(libs.firebase.crashlytics)
implementation(libs.firebase.analytics)
implementation(libs.firebase.perf)
implementation(libs.firebase.config)

// In App Updates
implementation(libs.app.update)
implementation(libs.app.update.ktx)

// Testing & Debugging
testImplementation(libs.junit)
testImplementation(libs.google.truth)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.mockk)
testImplementation(libs.turbine)
androidTestImplementation(libs.test.ext.junit)
androidTestImplementation(libs.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
Expand Down
Loading