-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #98 from Arctosoft/develop
Valv v2
- Loading branch information
Showing
140 changed files
with
10,593 additions
and
3,033 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,62 @@ | ||
This is the encryption docs for file structure version 2. | ||
|
||
# File encryption | ||
Files are encrypted using the `ChaCha20/NONE/NoPadding` cipher in Android. See [Android Ciphers](https://developer.android.com/reference/javax/crypto/Cipher) for details. | ||
|
||
The key algorithm is `PBKDF2withHmacSHA512` with 20000 iterations and a 256-bit key length. | ||
The key algorithm is `PBKDF2withHmacSHA512` with 50000 iterations (default, can be changed) and a 256-bit key length. | ||
|
||
The salt is 16 bytes and the IV is 12 bytes. An additional 12 bytes is used in some files to check if the supplied password can decrypt the file, see details below. | ||
The salt is 16 bytes and the IV is 12 bytes. An additional 12 bytes is used to check if the supplied password can decrypt the file, see details below. | ||
|
||
## Encrypted file structure | ||
![Encrypted file structure image](/images/encryption.jpg) | ||
![Encrypted file structure image](/images/encryption_v2.jpg) | ||
|
||
## File types/names | ||
|
||
The following filename prefixes are used: | ||
- `.valv.i.1-` for image files | ||
- `.valv.g.1-` for GIF files | ||
- `.valv.v.1-` for video files | ||
- `.valv.n.1-` for note files | ||
- `.valv.t.1-` for thumbnail files | ||
The following filename suffixes are used: | ||
- `-i.valv` for image files | ||
- `-g.valv` for GIF files | ||
- `-v.valv` for video files | ||
- `-x.valv` for text files | ||
- `-n.valv` for note files | ||
- `-t.valv` for thumbnail files | ||
|
||
The number represents the file structure version (for future expansion/changes). | ||
|
||
Filenames are generated randomly and are `PREFIX_LENGTH + 32 chars` long. | ||
Filenames are generated randomly and are `32 chars + SUFFIX_LENGTH` long. | ||
Every media file has a corresponding thumbnail with the same name. For example, an image file named | ||
|
||
`.valv.i.1-aLFshh71iywWo7HXtEcOtZNVJe-Ot7iQ` has a thumbnail | ||
`aLFshh71iywWo7HXtEcOtZNVJe-Ot7iQ-i.valv` has a thumbnail | ||
|
||
`.valv.t.1-aLFshh71iywWo7HXtEcOtZNVJe-Ot7iQ`. | ||
`aLFshh71iywWo7HXtEcOtZNVJe-Ot7iQ-t.valv`. | ||
|
||
Similarly, a note has the same name as its media file. | ||
|
||
All text and strings are encoded as UTF-8. | ||
|
||
## Encrypting | ||
The app creates the encrypted files in the following way: | ||
1. Generate a random 16 byte salt and 12 byte IV. If the file is a thumbnail it also generates an additional 12 check bytes. | ||
1. Generate a random 16 byte salt, a 12 byte IV and 12 check bytes. | ||
2. Create an unencrypted output stream. | ||
3. Write the salt. | ||
4. Write the IV. | ||
5. If the file is a thumbnail, write the check bytes. | ||
6. Pass the output stream into a cipher (encrypted) output stream. Everything below is encrypted. | ||
7. If the file is a thumbnail, write the check bytes. | ||
8. Write a newline character followed by the original filename and another newline character (`'\n' + name + '\n'`). | ||
9. Write the file data. | ||
3. Write the encrypted file structure version (4 bytes, integer) | ||
4. Write the salt. | ||
5. Write the IV. | ||
6. Write the iteration count used for key generation (4 bytes, integer) | ||
7. Write the check bytes. | ||
8. Pass the output stream into a cipher (encrypted) output stream. Everything below is encrypted. | ||
9. Write the check bytes. | ||
10. Write a newline character followed by a JSON object as an string containing the original filename and another newline character (`'\n' + "{\"originalName\":\"file.jpg\"}" + '\n'`). | ||
11. Write the file data. | ||
|
||
## Decrypting | ||
The app reads the encrypted files in the following way: | ||
1. Create an unencrypted input stream. | ||
2. Read the 16 byte salt. | ||
3. Read the 12 byte IV. | ||
4. If the file is a thumbnail, read the 12 check bytes. | ||
5. Pass the input stream into a cipher (encrypted) input stream. Everything below is read from encrypted data. | ||
6. If the file is a thumbnail, read the check bytes. If the unencrypted check bytes does not equal the check bytes in the encrypted part, the given password is invalid. | ||
7. Read a newline character (`0x0A`) followed by the original filename and another newline character. | ||
8. Read the file data. | ||
|
||
A Python script to decrypt .valv files can be found in [this issue comment](https://github.com/Arctosoft/Valv-Android/issues/33#issuecomment-1974834924). | ||
2. Read the encrypted file structure version (4 bytes, integer) | ||
3. Read the 16 byte salt. | ||
4. Read the 12 byte IV. | ||
5. Read the iteration count used for key generation (4 bytes, integer) | ||
6. Read the 12 check bytes. | ||
7. Pass the input stream into a cipher (encrypted) input stream. Everything below is read from encrypted data. | ||
8. Read the check bytes. If the unencrypted check bytes does not equal the check bytes in the encrypted part, the given password is invalid. | ||
9. Read a newline character (`0x0A`) followed by the JSON object string and another newline character. | ||
10. Read the file data. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
This is the encryption docs for file structure version 1. | ||
|
||
# File encryption | ||
Files are encrypted using the `ChaCha20/NONE/NoPadding` cipher in Android. See [Android Ciphers](https://developer.android.com/reference/javax/crypto/Cipher) for details. | ||
|
||
The key algorithm is `PBKDF2withHmacSHA512` with 20000 iterations and a 256-bit key length. | ||
|
||
The salt is 16 bytes and the IV is 12 bytes. An additional 12 bytes is used in some files to check if the supplied password can decrypt the file, see details below. | ||
|
||
## Encrypted file structure | ||
![Encrypted file structure image](/images/encryption_v1.jpg) | ||
|
||
## File types/names | ||
|
||
The following filename prefixes are used: | ||
- `.valv.i.1-` for image files | ||
- `.valv.g.1-` for GIF files | ||
- `.valv.v.1-` for video files | ||
- `.valv.x.1-` for text files | ||
- `.valv.n.1-` for note files | ||
- `.valv.t.1-` for thumbnail files | ||
|
||
The number represents the file structure version (for future expansion/changes). | ||
|
||
Filenames are generated randomly and are `PREFIX_LENGTH + 32 chars` long. | ||
Every media file has a corresponding thumbnail with the same name. For example, an image file named | ||
|
||
`.valv.i.1-aLFshh71iywWo7HXtEcOtZNVJe-Ot7iQ` has a thumbnail | ||
|
||
`.valv.t.1-aLFshh71iywWo7HXtEcOtZNVJe-Ot7iQ`. | ||
|
||
Similarly, a note has the same name as its media file. | ||
|
||
## Encrypting | ||
The app creates the encrypted files in the following way: | ||
1. Generate a random 16 byte salt and 12 byte IV. If the file is a thumbnail it also generates an additional 12 check bytes. | ||
2. Create an unencrypted output stream. | ||
3. Write the salt. | ||
4. Write the IV. | ||
5. If the file is a thumbnail, write the check bytes. | ||
6. Pass the output stream into a cipher (encrypted) output stream. Everything below is encrypted. | ||
7. If the file is a thumbnail, write the check bytes. | ||
8. Write a newline character followed by the original filename and another newline character (`'\n' + name + '\n'`). | ||
9. Write the file data. | ||
|
||
## Decrypting | ||
The app reads the encrypted files in the following way: | ||
1. Create an unencrypted input stream. | ||
2. Read the 16 byte salt. | ||
3. Read the 12 byte IV. | ||
4. If the file is a thumbnail, read the 12 check bytes. | ||
5. Pass the input stream into a cipher (encrypted) input stream. Everything below is read from encrypted data. | ||
6. If the file is a thumbnail, read the check bytes. If the unencrypted check bytes does not equal the check bytes in the encrypted part, the given password is invalid. | ||
7. Read a newline character (`0x0A`) followed by the original filename and another newline character. | ||
8. Read the file data. | ||
|
||
A Python script to decrypt .valv files can be found in [this issue comment](https://github.com/Arctosoft/Valv-Android/issues/33#issuecomment-1974834924). |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
plugins { | ||
alias(libs.plugins.android.application) | ||
alias(libs.plugins.about.libraries) | ||
} | ||
|
||
android { | ||
namespace = "se.arctosoft.vault" | ||
compileSdk = 35 | ||
|
||
defaultConfig { | ||
applicationId = "se.arctosoft.vault" | ||
minSdk = 28 | ||
targetSdk = 35 | ||
versionCode = 31 | ||
versionName = "2.0.0" | ||
|
||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
buildTypes { | ||
release { | ||
isMinifyEnabled = true | ||
proguardFiles( | ||
getDefaultProguardFile("proguard-android-optimize.txt"), | ||
"proguard-rules.pro" | ||
) | ||
} | ||
debug { | ||
isMinifyEnabled = false | ||
proguardFiles( | ||
getDefaultProguardFile("proguard-android-optimize.txt"), | ||
"proguard-rules.pro" | ||
) | ||
applicationIdSuffix = ".dev" | ||
} | ||
applicationVariants.all { | ||
val variant = this | ||
variant.outputs.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl } | ||
.forEach { output -> | ||
val outputFileName = | ||
"Vault_${variant.versionCode}_${variant.versionName}_${variant.buildType.name}.apk" | ||
output.outputFileName = outputFileName | ||
} | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility = JavaVersion.VERSION_17 | ||
targetCompatibility = JavaVersion.VERSION_17 | ||
} | ||
buildFeatures { | ||
viewBinding = true | ||
buildConfig = true | ||
} | ||
} | ||
|
||
dependencies { | ||
androidTestImplementation(libs.ext.junit) | ||
androidTestImplementation(libs.espresso.core) | ||
testImplementation(libs.junit) | ||
|
||
implementation(libs.appcompat) | ||
implementation(libs.material) | ||
implementation(libs.constraintlayout) | ||
implementation(libs.navigation.fragment) | ||
implementation(libs.navigation.ui) | ||
implementation(libs.preference) | ||
implementation(libs.activity) | ||
|
||
implementation(libs.security.crypto) | ||
implementation(libs.media3.exoplayer) | ||
implementation(libs.media3.ui) | ||
implementation(libs.preferences) | ||
annotationProcessor(libs.glide.annotation) | ||
|
||
implementation(libs.glide) | ||
implementation(libs.about.libraries) | ||
implementation(libs.about.libraries.compose) | ||
} | ||
|
||
aboutLibraries { | ||
configPath = "config" | ||
// Remove the "generated" timestamp to allow for reproducible builds | ||
excludeFields = arrayOf("generated") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
Oops, something went wrong.