openpgp-ktx: import at 95eed95fb5654e9dcfe32c3712ae97385e186396

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2020-11-25 03:27:42 +05:30
parent fa2a93769f
commit 7b25bf8783
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
17 changed files with 1762 additions and 0 deletions

14
openpgp-ktx/README.md Normal file
View file

@ -0,0 +1,14 @@
# openpgp-ktx [![Download](https://api.bintray.com/packages/android-password-store/openpgp-ktx/openpgp-ktx/images/download.svg)](https://bintray.com/android-password-store/openpgp-ktx/openpgp-ktx/_latestVersion)
Reimplementation of [OpenKeychain]'s integration library [openpgp-api]. Written entirely in Kotlin, it leverages Jetpack to be compatible with modern apps, unlike the original library.
## Using this with your projects
```gradle
dependencies {
implementation("com.github.androidpasswordstore:openpgp-ktx:<latest-version>")
}
```
[OpenKeychain]: https://github.com/open-keychain/open-keychain
[openpgp-api]: https://github.com/open-keychain/openpgp-api

View file

@ -0,0 +1,272 @@
public final class me/msfjarvis/openpgpktx/AutocryptPeerUpdate : android/os/Parcelable {
public static final field CREATOR Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate$CREATOR;
public fun <init> ()V
public synthetic fun <init> (Landroid/os/Parcel;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun createAutocryptPeerUpdate ([BLjava/util/Date;)Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate;
public fun describeContents ()I
public final fun getEffectiveDate ()Ljava/util/Date;
public final fun getKeyData ()[B
public final fun getPreferEncrypt ()Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate$PreferEncrypt;
public final fun hasKeyData ()Z
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class me/msfjarvis/openpgpktx/AutocryptPeerUpdate$CREATOR : android/os/Parcelable$Creator {
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public fun createFromParcel (Landroid/os/Parcel;)Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate;
public synthetic fun newArray (I)[Ljava/lang/Object;
public fun newArray (I)[Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate;
}
public final class me/msfjarvis/openpgpktx/AutocryptPeerUpdate$PreferEncrypt : java/lang/Enum {
public static final field MUTUAL Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate$PreferEncrypt;
public static final field NOPREFERENCE Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate$PreferEncrypt;
public static fun valueOf (Ljava/lang/String;)Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate$PreferEncrypt;
public static fun values ()[Lme/msfjarvis/openpgpktx/AutocryptPeerUpdate$PreferEncrypt;
}
public final class me/msfjarvis/openpgpktx/util/OpenPgpApi {
public static final field ACTION_BACKUP Ljava/lang/String;
public static final field ACTION_CHECK_PERMISSION Ljava/lang/String;
public static final field ACTION_CLEARTEXT_SIGN Ljava/lang/String;
public static final field ACTION_DECRYPT_METADATA Ljava/lang/String;
public static final field ACTION_DECRYPT_VERIFY Ljava/lang/String;
public static final field ACTION_DETACHED_SIGN Ljava/lang/String;
public static final field ACTION_ENCRYPT Ljava/lang/String;
public static final field ACTION_GET_KEY Ljava/lang/String;
public static final field ACTION_GET_KEY_IDS Ljava/lang/String;
public static final field ACTION_GET_SIGN_KEY_ID Ljava/lang/String;
public static final field ACTION_QUERY_AUTOCRYPT_STATUS Ljava/lang/String;
public static final field ACTION_SIGN_AND_ENCRYPT Ljava/lang/String;
public static final field ACTION_UPDATE_AUTOCRYPT_PEER Ljava/lang/String;
public static final field API_VERSION I
public static final field AUTOCRYPT_STATUS_AVAILABLE I
public static final field AUTOCRYPT_STATUS_DISCOURAGE I
public static final field AUTOCRYPT_STATUS_MUTUAL I
public static final field AUTOCRYPT_STATUS_UNAVAILABLE I
public static final field Companion Lme/msfjarvis/openpgpktx/util/OpenPgpApi$Companion;
public static final field EXTRA_API_VERSION Ljava/lang/String;
public static final field EXTRA_AUTOCRYPT_PEER_GOSSIP_UPDATES Ljava/lang/String;
public static final field EXTRA_AUTOCRYPT_PEER_ID Ljava/lang/String;
public static final field EXTRA_AUTOCRYPT_PEER_UPDATE Ljava/lang/String;
public static final field EXTRA_BACKUP_SECRET Ljava/lang/String;
public static final field EXTRA_DATA_LENGTH Ljava/lang/String;
public static final field EXTRA_DECRYPTION_RESULT Ljava/lang/String;
public static final field EXTRA_DETACHED_SIGNATURE Ljava/lang/String;
public static final field EXTRA_ENABLE_COMPRESSION Ljava/lang/String;
public static final field EXTRA_KEY_ID Ljava/lang/String;
public static final field EXTRA_KEY_IDS Ljava/lang/String;
public static final field EXTRA_KEY_IDS_SELECTED Ljava/lang/String;
public static final field EXTRA_MINIMIZE Ljava/lang/String;
public static final field EXTRA_MINIMIZE_USER_ID Ljava/lang/String;
public static final field EXTRA_OPPORTUNISTIC_ENCRYPTION Ljava/lang/String;
public static final field EXTRA_ORIGINAL_FILENAME Ljava/lang/String;
public static final field EXTRA_PASSPHRASE Ljava/lang/String;
public static final field EXTRA_PROGRESS_MESSENGER Ljava/lang/String;
public static final field EXTRA_REQUEST_ASCII_ARMOR Ljava/lang/String;
public static final field EXTRA_SENDER_ADDRESS Ljava/lang/String;
public static final field EXTRA_SIGN_KEY_ID Ljava/lang/String;
public static final field EXTRA_SUPPORT_OVERRIDE_CRYPTO_WARNING Ljava/lang/String;
public static final field EXTRA_USER_ID Ljava/lang/String;
public static final field EXTRA_USER_IDS Ljava/lang/String;
public static final field RESULT_AUTOCRYPT_STATUS Ljava/lang/String;
public static final field RESULT_CHARSET Ljava/lang/String;
public static final field RESULT_CODE Ljava/lang/String;
public static final field RESULT_CODE_ERROR I
public static final field RESULT_CODE_SUCCESS I
public static final field RESULT_CODE_USER_INTERACTION_REQUIRED I
public static final field RESULT_DECRYPTION Ljava/lang/String;
public static final field RESULT_DETACHED_SIGNATURE Ljava/lang/String;
public static final field RESULT_ERROR Ljava/lang/String;
public static final field RESULT_INSECURE_DETAIL_INTENT Ljava/lang/String;
public static final field RESULT_INTENT Ljava/lang/String;
public static final field RESULT_KEYS_CONFIRMED Ljava/lang/String;
public static final field RESULT_KEY_IDS Ljava/lang/String;
public static final field RESULT_METADATA Ljava/lang/String;
public static final field RESULT_OVERRIDE_CRYPTO_WARNING Ljava/lang/String;
public static final field RESULT_SIGNATURE Ljava/lang/String;
public static final field RESULT_SIGNATURE_MICALG Ljava/lang/String;
public static final field SERVICE_INTENT_2 Ljava/lang/String;
public fun <init> (Landroid/content/Context;Lorg/openintents/openpgp/IOpenPgpService2;)V
public final fun executeApi (Landroid/content/Intent;Ljava/io/InputStream;Ljava/io/OutputStream;)Landroid/content/Intent;
public final fun executeApiAsync (Landroid/content/Intent;Ljava/io/InputStream;Ljava/io/OutputStream;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class me/msfjarvis/openpgpktx/util/OpenPgpApi$Companion {
}
public final class me/msfjarvis/openpgpktx/util/OpenPgpServiceConnection {
public fun <init> (Landroid/content/Context;Ljava/lang/String;)V
public fun <init> (Landroid/content/Context;Ljava/lang/String;Lme/msfjarvis/openpgpktx/util/OpenPgpServiceConnection$OnBound;)V
public final fun bindToService ()V
public final fun getService ()Lorg/openintents/openpgp/IOpenPgpService2;
public final fun isBound ()Z
public final fun unbindFromService ()V
}
public abstract interface class me/msfjarvis/openpgpktx/util/OpenPgpServiceConnection$OnBound {
public abstract fun onBound (Lorg/openintents/openpgp/IOpenPgpService2;)V
public abstract fun onError (Ljava/lang/Exception;)V
}
public final class me/msfjarvis/openpgpktx/util/OpenPgpUtils {
public static final field INSTANCE Lme/msfjarvis/openpgpktx/util/OpenPgpUtils;
public static final field PARSE_RESULT_MESSAGE I
public static final field PARSE_RESULT_NO_PGP I
public static final field PARSE_RESULT_SIGNED_MESSAGE I
public final fun convertKeyIdToHex (J)Ljava/lang/String;
public final fun createUserId (Lme/msfjarvis/openpgpktx/util/OpenPgpUtils$UserId;)Ljava/lang/String;
public final fun isAvailable (Landroid/content/Context;)Z
public final fun parseMessage (Ljava/lang/String;)I
public final fun splitUserId (Ljava/lang/String;)Lme/msfjarvis/openpgpktx/util/OpenPgpUtils$UserId;
}
public final class me/msfjarvis/openpgpktx/util/OpenPgpUtils$UserId : java/io/Serializable {
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun getComment ()Ljava/lang/String;
public final fun getEmail ()Ljava/lang/String;
public final fun getName ()Ljava/lang/String;
}
public abstract interface class org/openintents/openpgp/IOpenPgpService2 : android/os/IInterface {
public abstract fun createOutputPipe (I)Landroid/os/ParcelFileDescriptor;
public abstract fun execute (Landroid/content/Intent;Landroid/os/ParcelFileDescriptor;I)Landroid/content/Intent;
}
public class org/openintents/openpgp/IOpenPgpService2$Default : org/openintents/openpgp/IOpenPgpService2 {
public fun <init> ()V
public fun asBinder ()Landroid/os/IBinder;
public fun createOutputPipe (I)Landroid/os/ParcelFileDescriptor;
public fun execute (Landroid/content/Intent;Landroid/os/ParcelFileDescriptor;I)Landroid/content/Intent;
}
public abstract class org/openintents/openpgp/IOpenPgpService2$Stub : android/os/Binder, org/openintents/openpgp/IOpenPgpService2 {
public fun <init> ()V
public fun asBinder ()Landroid/os/IBinder;
public static fun asInterface (Landroid/os/IBinder;)Lorg/openintents/openpgp/IOpenPgpService2;
public static fun getDefaultImpl ()Lorg/openintents/openpgp/IOpenPgpService2;
public fun onTransact (ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
public static fun setDefaultImpl (Lorg/openintents/openpgp/IOpenPgpService2;)Z
}
public final class org/openintents/openpgp/OpenPgpDecryptionResult : android/os/Parcelable {
public static final field CREATOR Lorg/openintents/openpgp/OpenPgpDecryptionResult$CREATOR;
public static final field RESULT_ENCRYPTED I
public static final field RESULT_INSECURE I
public static final field RESULT_NOT_ENCRYPTED I
public fun <init> ()V
public synthetic fun <init> (I[B[BLkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun describeContents ()I
public final fun getDecryptedSessionKey ()[B
public final fun getResult ()I
public final fun getSessionKey ()[B
public final fun hasDecryptedSessionKey ()Z
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class org/openintents/openpgp/OpenPgpDecryptionResult$CREATOR : android/os/Parcelable$Creator {
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public fun createFromParcel (Landroid/os/Parcel;)Lorg/openintents/openpgp/OpenPgpDecryptionResult;
public synthetic fun newArray (I)[Ljava/lang/Object;
public fun newArray (I)[Lorg/openintents/openpgp/OpenPgpDecryptionResult;
}
public final class org/openintents/openpgp/OpenPgpError : android/os/Parcelable {
public static final field CLIENT_SIDE_ERROR I
public static final field CREATOR Lorg/openintents/openpgp/OpenPgpError$CREATOR;
public static final field GENERIC_ERROR I
public static final field INCOMPATIBLE_API_VERSIONS I
public static final field NO_OR_WRONG_PASSPHRASE I
public static final field NO_USER_IDS I
public static final field OPPORTUNISTIC_MISSING_KEYS I
public fun <init> ()V
public fun describeContents ()I
public final fun getErrorId ()I
public final fun getMessage ()Ljava/lang/String;
public final fun setErrorId (I)V
public final fun setMessage (Ljava/lang/String;)V
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class org/openintents/openpgp/OpenPgpError$CREATOR : android/os/Parcelable$Creator {
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public fun createFromParcel (Landroid/os/Parcel;)Lorg/openintents/openpgp/OpenPgpError;
public synthetic fun newArray (I)[Ljava/lang/Object;
public fun newArray (I)[Lorg/openintents/openpgp/OpenPgpError;
}
public final class org/openintents/openpgp/OpenPgpMetadata : android/os/Parcelable {
public static final field CREATOR Lorg/openintents/openpgp/OpenPgpMetadata$CREATOR;
public fun <init> ()V
public fun describeContents ()I
public final fun getCharset ()Ljava/lang/String;
public final fun getFilename ()Ljava/lang/String;
public final fun getMimeType ()Ljava/lang/String;
public final fun getModificationTime ()J
public final fun getOriginalSize ()J
public final fun setCharset (Ljava/lang/String;)V
public final fun setFilename (Ljava/lang/String;)V
public final fun setMimeType (Ljava/lang/String;)V
public final fun setModificationTime (J)V
public final fun setOriginalSize (J)V
public fun toString ()Ljava/lang/String;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class org/openintents/openpgp/OpenPgpMetadata$CREATOR : android/os/Parcelable$Creator {
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public fun createFromParcel (Landroid/os/Parcel;)Lorg/openintents/openpgp/OpenPgpMetadata;
public synthetic fun newArray (I)[Ljava/lang/Object;
public fun newArray (I)[Lorg/openintents/openpgp/OpenPgpMetadata;
}
public final class org/openintents/openpgp/OpenPgpSignatureResult : android/os/Parcelable {
public static final field CREATOR Lorg/openintents/openpgp/OpenPgpSignatureResult$CREATOR;
public static final field RESULT_INVALID_KEY_EXPIRED I
public static final field RESULT_INVALID_KEY_INSECURE I
public static final field RESULT_INVALID_KEY_REVOKED I
public static final field RESULT_INVALID_SIGNATURE I
public static final field RESULT_KEY_MISSING I
public static final field RESULT_NO_SIGNATURE I
public static final field RESULT_VALID_KEY_CONFIRMED I
public static final field RESULT_VALID_KEY_UNCONFIRMED I
public synthetic fun <init> (ILjava/lang/String;JLjava/util/ArrayList;Ljava/util/ArrayList;Lorg/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult;Ljava/lang/Boolean;Ljava/util/Date;Lorg/openintents/openpgp/OpenPgpSignatureResult$AutocryptPeerResult;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Landroid/os/Parcel;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun describeContents ()I
public final fun getConfirmedUserIds ()Ljava/util/List;
public final fun getUserIds ()Ljava/util/List;
public fun toString ()Ljava/lang/String;
public final fun withAutocryptPeerResult (Lorg/openintents/openpgp/OpenPgpSignatureResult$AutocryptPeerResult;)Lorg/openintents/openpgp/OpenPgpSignatureResult;
public final fun withSignatureOnlyFlag (Z)Lorg/openintents/openpgp/OpenPgpSignatureResult;
public fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class org/openintents/openpgp/OpenPgpSignatureResult$AutocryptPeerResult : java/lang/Enum {
public static final field MISMATCH Lorg/openintents/openpgp/OpenPgpSignatureResult$AutocryptPeerResult;
public static final field NEW Lorg/openintents/openpgp/OpenPgpSignatureResult$AutocryptPeerResult;
public static final field OK Lorg/openintents/openpgp/OpenPgpSignatureResult$AutocryptPeerResult;
public static fun valueOf (Ljava/lang/String;)Lorg/openintents/openpgp/OpenPgpSignatureResult$AutocryptPeerResult;
public static fun values ()[Lorg/openintents/openpgp/OpenPgpSignatureResult$AutocryptPeerResult;
}
public final class org/openintents/openpgp/OpenPgpSignatureResult$CREATOR : android/os/Parcelable$Creator {
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public fun createFromParcel (Landroid/os/Parcel;)Lorg/openintents/openpgp/OpenPgpSignatureResult;
public final fun createWithInvalidSignature ()Lorg/openintents/openpgp/OpenPgpSignatureResult;
public final fun createWithKeyMissing (JLjava/util/Date;)Lorg/openintents/openpgp/OpenPgpSignatureResult;
public final fun createWithNoSignature ()Lorg/openintents/openpgp/OpenPgpSignatureResult;
public final fun createWithValidSignature (ILjava/lang/String;JLjava/util/ArrayList;Ljava/util/ArrayList;Lorg/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult;Ljava/util/Date;)Lorg/openintents/openpgp/OpenPgpSignatureResult;
public synthetic fun newArray (I)[Ljava/lang/Object;
public fun newArray (I)[Lorg/openintents/openpgp/OpenPgpSignatureResult;
}
public final class org/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult : java/lang/Enum {
public static final field UNKNOWN Lorg/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult;
public static final field USER_ID_CONFIRMED Lorg/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult;
public static final field USER_ID_MISSING Lorg/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult;
public static final field USER_ID_UNCONFIRMED Lorg/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult;
public static fun valueOf (Ljava/lang/String;)Lorg/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult;
public static fun values ()[Lorg/openintents/openpgp/OpenPgpSignatureResult$SenderStatusResult;
}

View file

@ -0,0 +1,28 @@
plugins {
id("com.android.library")
id("maven-publish")
kotlin("android")
`aps-plugin`
}
android {
defaultConfig {
consumerProguardFiles("consumer-rules.pro")
}
buildFeatures.aidl = true
kotlin {
explicitApi()
}
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + listOf(
"-Xexplicit-api=strict"
)
}
}
dependencies {
implementation(Dependencies.Kotlin.Coroutines.core)
}

View file

@ -0,0 +1 @@
-keep class org.openintents.openpgp.**

View file

@ -0,0 +1,17 @@
GROUP=com.github.androidpasswordstore
VERSION_NAME=2.2.0
POM_ARTIFACT_ID=openpgp-ktx
POM_ARTIFACT_DESCRIPTION=Reimplementation of OpenKeychain's integration library in Kotlin
POM_URL=https://github.com/Android-Password-Store/android-password-store
POM_SCM_URL=https://github.com/Android-Password-Store/android-password-store
POM_SCM_CONNECTION=scm:git:https://github.com/Android-Password-Store/android-password-store.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com:Android-Password-Store/android-password-store
POM_LICENSE_NAME=LGPL-3.0-only WITH LGPL-3.0-linking-exception
POM_LICENSE_URL=https://www.gnu.org/licenses/lgpl-3.0.txt
POM_LICENSE_DIST=repo
POM_DEVELOPER_ID=android-password-store
POM_DEVELOPER_NAME=The Android Password Store Authors
POM_DEVELOPER_EMAIL=aps@msfjarvis.dev

View file

@ -0,0 +1 @@
<manifest package="me.msfjarvis.openpgpktx" />

View file

@ -0,0 +1,18 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-Only
*/
package org.openintents.openpgp;
interface IOpenPgpService2 {
/**
* see org.openintents.openpgp.util.OpenPgpApi for documentation
*/
ParcelFileDescriptor createOutputPipe(in int pipeId);
/**
* see org.openintents.openpgp.util.OpenPgpApi for documentation
*/
Intent execute(in Intent data, in ParcelFileDescriptor input, int pipeId);
}

View file

@ -0,0 +1,109 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
package me.msfjarvis.openpgpktx
import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
import java.util.Date
public class AutocryptPeerUpdate() : Parcelable {
private var keyData: ByteArray? = null
private var effectiveDate: Date? = null
private lateinit var preferEncrypt: PreferEncrypt
internal constructor(
keyData: ByteArray?,
effectiveDate: Date?,
preferEncrypt: PreferEncrypt
) : this() {
this.keyData = keyData
this.effectiveDate = effectiveDate
this.preferEncrypt = preferEncrypt
}
private constructor(source: Parcel, version: Int) : this() {
keyData = source.createByteArray()
effectiveDate = if (source.readInt() != 0) Date(source.readLong()) else null
preferEncrypt = PreferEncrypt.values()[source.readInt()]
}
public fun createAutocryptPeerUpdate(
keyData: ByteArray?,
timestamp: Date?
): AutocryptPeerUpdate {
return AutocryptPeerUpdate(keyData, timestamp, PreferEncrypt.NOPREFERENCE)
}
public fun getKeyData(): ByteArray? {
return keyData
}
public fun hasKeyData(): Boolean {
return keyData != null
}
public fun getEffectiveDate(): Date? {
return effectiveDate
}
public fun getPreferEncrypt(): PreferEncrypt? {
return preferEncrypt
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
/**
* NOTE: When adding fields in the process of updating this API, make sure to bump
* [.PARCELABLE_VERSION].
*/
dest.writeInt(PARCELABLE_VERSION)
// Inject a placeholder that will store the parcel size from this point on
// (not including the size itself).
val sizePosition = dest.dataPosition()
dest.writeInt(0)
val startPosition = dest.dataPosition()
// version 1
dest.writeByteArray(keyData)
if (effectiveDate != null) {
dest.writeInt(1)
dest.writeLong(effectiveDate!!.time)
} else {
dest.writeInt(0)
}
dest.writeInt(preferEncrypt.ordinal)
// Go back and write the size
val parcelableSize = dest.dataPosition() - startPosition
dest.setDataPosition(sizePosition)
dest.writeInt(parcelableSize)
dest.setDataPosition(startPosition + parcelableSize)
}
public companion object CREATOR : Creator<AutocryptPeerUpdate> {
private const val PARCELABLE_VERSION = 1
override fun createFromParcel(source: Parcel): AutocryptPeerUpdate? {
val version = source.readInt() // parcelableVersion
val parcelableSize = source.readInt()
val startPosition = source.dataPosition()
val vr = AutocryptPeerUpdate(source, version)
// skip over all fields added in future versions of this parcel
source.setDataPosition(startPosition + parcelableSize)
return vr
}
override fun newArray(size: Int): Array<AutocryptPeerUpdate?>? {
return arrayOfNulls(size)
}
}
public enum class PreferEncrypt {
NOPREFERENCE, MUTUAL
}
}

View file

@ -0,0 +1,402 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
@file:Suppress("Unused")
package me.msfjarvis.openpgpktx.util
import android.content.Context
import android.content.Intent
import android.os.ParcelFileDescriptor
import android.util.Log
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.concurrent.atomic.AtomicInteger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.openintents.openpgp.IOpenPgpService2
import org.openintents.openpgp.OpenPgpError
public class OpenPgpApi(private val context: Context, private val service: IOpenPgpService2) {
private val pipeIdGen: AtomicInteger = AtomicInteger()
public suspend fun executeApiAsync(
data: Intent?,
inputStream: InputStream?,
outputStream: OutputStream?,
callback: (intent: Intent?) -> Unit
) {
val result = executeApi(data, inputStream, outputStream)
withContext(Dispatchers.Main) {
callback.invoke(result)
}
}
public fun executeApi(data: Intent?, inputStream: InputStream?, outputStream: OutputStream?): Intent? {
var input: ParcelFileDescriptor? = null
return try {
if (inputStream != null) {
input = ParcelFileDescriptorUtil.pipeFrom(inputStream)
}
executeApi(data, input, outputStream)
} catch (e: Exception) {
Log.e(TAG, "Exception in executeApi call", e)
val result = Intent()
result.putExtra(RESULT_CODE, RESULT_CODE_ERROR)
result.putExtra(
RESULT_ERROR,
OpenPgpError(
OpenPgpError.CLIENT_SIDE_ERROR,
e.message
)
)
result
} finally {
if (input != null) {
try {
input.close()
} catch (e: IOException) {
Log.e(TAG, "IOException when closing ParcelFileDescriptor!", e)
}
}
}
}
/**
* InputStream and OutputStreams are always closed after operating on them!
*/
private fun executeApi(
data: Intent?,
input: ParcelFileDescriptor?,
os: OutputStream?
): Intent? {
var output: ParcelFileDescriptor? = null
return try {
// always send version from client
data?.putExtra(EXTRA_API_VERSION, API_VERSION)
val result: Intent
var pumpThread: Thread? = null
var outputPipeId = 0
if (os != null) {
outputPipeId = pipeIdGen.incrementAndGet()
output = service.createOutputPipe(outputPipeId)
pumpThread = ParcelFileDescriptorUtil.pipeTo(os, output)
}
// blocks until result is ready
result = service.execute(data, input, outputPipeId)
// set class loader to current context to allow unparcelling
// of OpenPgpError and OpenPgpSignatureResult
// http://stackoverflow.com/a/3806769
result.setExtrasClassLoader(context.classLoader)
// wait for ALL data being pumped from remote side
pumpThread?.join()
result
} catch (e: Exception) {
Log.e(TAG, "Exception in executeApi call", e)
val result = Intent()
result.putExtra(RESULT_CODE, RESULT_CODE_ERROR)
result.putExtra(
RESULT_ERROR,
OpenPgpError(
OpenPgpError.CLIENT_SIDE_ERROR,
e.message
)
)
result
} finally {
// close() is required to halt the TransferThread
if (output != null) {
try {
output.close()
} catch (e: IOException) {
Log.e(TAG, "IOException when closing ParcelFileDescriptor!", e)
}
}
}
}
public companion object {
private const val TAG = "OpenPgp API"
public const val SERVICE_INTENT_2: String = "org.openintents.openpgp.IOpenPgpService2"
/**
* see CHANGELOG.md
*/
public const val API_VERSION: Int = 11
/**
* General extras
* --------------
*
* required extras:
* int EXTRA_API_VERSION (always required)
*
* returned extras:
* int RESULT_CODE (RESULT_CODE_ERROR, RESULT_CODE_SUCCESS or RESULT_CODE_USER_INTERACTION_REQUIRED)
* OpenPgpError RESULT_ERROR (if RESULT_CODE == RESULT_CODE_ERROR)
* PendingIntent RESULT_INTENT (if RESULT_CODE == RESULT_CODE_USER_INTERACTION_REQUIRED)
*/
/**
* General extras
* --------------
*
* required extras:
* int EXTRA_API_VERSION (always required)
*
* returned extras:
* int RESULT_CODE (RESULT_CODE_ERROR, RESULT_CODE_SUCCESS or RESULT_CODE_USER_INTERACTION_REQUIRED)
* OpenPgpError RESULT_ERROR (if RESULT_CODE == RESULT_CODE_ERROR)
* PendingIntent RESULT_INTENT (if RESULT_CODE == RESULT_CODE_USER_INTERACTION_REQUIRED)
*/
/**
* This action performs no operation, but can be used to check if the App has permission
* to access the API in general, returning a user interaction PendingIntent otherwise.
* This can be used to trigger the permission dialog explicitly.
*
* This action uses no extras.
*/
public const val ACTION_CHECK_PERMISSION: String = "org.openintents.openpgp.action.CHECK_PERMISSION"
/**
* Sign text resulting in a cleartext signature
* Some magic pre-processing of the text is done to convert it to a format usable for
* cleartext signatures per RFC 4880 before the text is actually signed:
* - end cleartext with newline
* - remove whitespaces on line endings
*
* required extras:
* long EXTRA_SIGN_KEY_ID (key id of signing key)
*
* optional extras:
* char[] EXTRA_PASSPHRASE (key passphrase)
*/
public const val ACTION_CLEARTEXT_SIGN: String = "org.openintents.openpgp.action.CLEARTEXT_SIGN"
/**
* Sign text or binary data resulting in a detached signature.
* No OutputStream necessary for ACTION_DETACHED_SIGN (No magic pre-processing like in ACTION_CLEARTEXT_SIGN)!
* The detached signature is returned separately in RESULT_DETACHED_SIGNATURE.
*
* required extras:
* long EXTRA_SIGN_KEY_ID (key id of signing key)
*
* optional extras:
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for detached signature)
* char[] EXTRA_PASSPHRASE (key passphrase)
*
* returned extras:
* byte[] RESULT_DETACHED_SIGNATURE
* String RESULT_SIGNATURE_MICALG (contains the name of the used signature algorithm as a string)
*/
public const val ACTION_DETACHED_SIGN: String = "org.openintents.openpgp.action.DETACHED_SIGN"
/**
* Encrypt
*
* required extras:
* String[] EXTRA_USER_IDS (=emails of recipients, if more than one key has a user_id, a PendingIntent is returned via RESULT_INTENT)
* or
* long[] EXTRA_KEY_IDS
*
* optional extras:
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
* char[] EXTRA_PASSPHRASE (key passphrase)
* String EXTRA_ORIGINAL_FILENAME (original filename to be encrypted as metadata)
* boolean EXTRA_ENABLE_COMPRESSION (enable ZLIB compression, default ist true)
*/
public const val ACTION_ENCRYPT: String = "org.openintents.openpgp.action.ENCRYPT"
/**
* Sign and encrypt
*
* required extras:
* String[] EXTRA_USER_IDS (=emails of recipients, if more than one key has a user_id, a PendingIntent is returned via RESULT_INTENT)
* or
* long[] EXTRA_KEY_IDS
*
* optional extras:
* long EXTRA_SIGN_KEY_ID (key id of signing key)
* boolean EXTRA_REQUEST_ASCII_ARMOR (request ascii armor for output)
* char[] EXTRA_PASSPHRASE (key passphrase)
* String EXTRA_ORIGINAL_FILENAME (original filename to be encrypted as metadata)
* boolean EXTRA_ENABLE_COMPRESSION (enable ZLIB compression, default ist true)
*/
public const val ACTION_SIGN_AND_ENCRYPT: String = "org.openintents.openpgp.action.SIGN_AND_ENCRYPT"
public const val ACTION_QUERY_AUTOCRYPT_STATUS: String =
"org.openintents.openpgp.action.QUERY_AUTOCRYPT_STATUS"
/**
* Decrypts and verifies given input stream. This methods handles encrypted-only, signed-and-encrypted,
* and also signed-only input.
* OutputStream is optional, e.g., for verifying detached signatures!
*
* If OpenPgpSignatureResult.getResult() == OpenPgpSignatureResult.RESULT_KEY_MISSING
* in addition a PendingIntent is returned via RESULT_INTENT to download missing keys.
* On all other status, in addition a PendingIntent is returned via RESULT_INTENT to open
* the key view in OpenKeychain.
*
* optional extras:
* byte[] EXTRA_DETACHED_SIGNATURE (detached signature)
*
* returned extras:
* OpenPgpSignatureResult RESULT_SIGNATURE
* OpenPgpDecryptionResult RESULT_DECRYPTION
* OpenPgpDecryptMetadata RESULT_METADATA
* String RESULT_CHARSET (charset which was specified in the headers of ascii armored input, if any)
*/
public const val ACTION_DECRYPT_VERIFY: String = "org.openintents.openpgp.action.DECRYPT_VERIFY"
/**
* Decrypts the header of an encrypted file to retrieve metadata such as original filename.
*
* This does not decrypt the actual content of the file.
*
* returned extras:
* OpenPgpDecryptMetadata RESULT_METADATA
* String RESULT_CHARSET (charset which was specified in the headers of ascii armored input, if any)
*/
public const val ACTION_DECRYPT_METADATA: String = "org.openintents.openpgp.action.DECRYPT_METADATA"
/**
* Select key id for signing
*
* optional extras:
* String EXTRA_USER_ID
*
* returned extras:
* long EXTRA_SIGN_KEY_ID
*/
public const val ACTION_GET_SIGN_KEY_ID: String = "org.openintents.openpgp.action.GET_SIGN_KEY_ID"
/**
* Get key ids based on given user ids (=emails)
*
* required extras:
* String[] EXTRA_USER_IDS
*
* returned extras:
* long[] RESULT_KEY_IDS
*/
public const val ACTION_GET_KEY_IDS: String = "org.openintents.openpgp.action.GET_KEY_IDS"
/**
* This action returns RESULT_CODE_SUCCESS if the OpenPGP Provider already has the key
* corresponding to the given key id in its database.
*
* It returns RESULT_CODE_USER_INTERACTION_REQUIRED if the Provider does not have the key.
* The PendingIntent from RESULT_INTENT can be used to retrieve those from a keyserver.
*
* If an Output stream has been defined the whole public key is returned.
* required extras:
* long EXTRA_KEY_ID
*
* optional extras:
* String EXTRA_REQUEST_ASCII_ARMOR (request that the returned key is encoded in ASCII Armor)
*/
public const val ACTION_GET_KEY: String = "org.openintents.openpgp.action.GET_KEY"
/**
* Backup all keys given by EXTRA_KEY_IDS and if requested their secret parts.
* The encrypted backup will be written to the OutputStream.
* The client app has no access to the backup code used to encrypt the backup!
* This operation always requires user interaction with RESULT_CODE_USER_INTERACTION_REQUIRED!
*
* required extras:
* long[] EXTRA_KEY_IDS (keys that should be included in the backup)
* boolean EXTRA_BACKUP_SECRET (also backup secret keys)
*/
public const val ACTION_BACKUP: String = "org.openintents.openpgp.action.BACKUP"
public const val ACTION_UPDATE_AUTOCRYPT_PEER: String =
"org.openintents.openpgp.action.UPDATE_AUTOCRYPT_PEER"
/* Intent extras */
public const val EXTRA_API_VERSION: String = "api_version"
// ACTION_DETACHED_SIGN, ENCRYPT, SIGN_AND_ENCRYPT, DECRYPT_VERIFY
// request ASCII Armor for output
// OpenPGP Radix-64, 33 percent overhead compared to binary, see http://tools.ietf.org/html/rfc4880#page-53)
public const val EXTRA_REQUEST_ASCII_ARMOR: String = "ascii_armor"
// ACTION_DETACHED_SIGN
public const val RESULT_DETACHED_SIGNATURE: String = "detached_signature"
public const val RESULT_SIGNATURE_MICALG: String = "signature_micalg"
// ENCRYPT, SIGN_AND_ENCRYPT, QUERY_AUTOCRYPT_STATUS
public const val EXTRA_USER_IDS: String = "user_ids"
public const val EXTRA_KEY_IDS: String = "key_ids"
public const val EXTRA_KEY_IDS_SELECTED: String = "key_ids_selected"
public const val EXTRA_SIGN_KEY_ID: String = "sign_key_id"
public const val RESULT_KEYS_CONFIRMED: String = "keys_confirmed"
public const val RESULT_AUTOCRYPT_STATUS: String = "autocrypt_status"
public const val AUTOCRYPT_STATUS_UNAVAILABLE: Int = 0
public const val AUTOCRYPT_STATUS_DISCOURAGE: Int = 1
public const val AUTOCRYPT_STATUS_AVAILABLE: Int = 2
public const val AUTOCRYPT_STATUS_MUTUAL: Int = 3
// optional extras:
public const val EXTRA_PASSPHRASE: String = "passphrase"
public const val EXTRA_ORIGINAL_FILENAME: String = "original_filename"
public const val EXTRA_ENABLE_COMPRESSION: String = "enable_compression"
public const val EXTRA_OPPORTUNISTIC_ENCRYPTION: String = "opportunistic"
// GET_SIGN_KEY_ID
public const val EXTRA_USER_ID: String = "user_id"
// GET_KEY
public const val EXTRA_KEY_ID: String = "key_id"
public const val EXTRA_MINIMIZE: String = "minimize"
public const val EXTRA_MINIMIZE_USER_ID: String = "minimize_user_id"
public const val RESULT_KEY_IDS: String = "key_ids"
// BACKUP
public const val EXTRA_BACKUP_SECRET: String = "backup_secret"
/* Service Intent returns */
public const val RESULT_CODE: String = "result_code"
// get actual error object from RESULT_ERROR
public const val RESULT_CODE_ERROR: Int = 0
// success!
public const val RESULT_CODE_SUCCESS: Int = 1
// get PendingIntent from RESULT_INTENT, start PendingIntent with startIntentSenderForResult,
// and execute service method again in onActivityResult
public const val RESULT_CODE_USER_INTERACTION_REQUIRED: Int = 2
public const val RESULT_ERROR: String = "error"
public const val RESULT_INTENT: String = "intent"
// DECRYPT_VERIFY
public const val EXTRA_DETACHED_SIGNATURE: String = "detached_signature"
public const val EXTRA_PROGRESS_MESSENGER: String = "progress_messenger"
public const val EXTRA_DATA_LENGTH: String = "data_length"
public const val EXTRA_DECRYPTION_RESULT: String = "decryption_result"
public const val EXTRA_SENDER_ADDRESS: String = "sender_address"
public const val EXTRA_SUPPORT_OVERRIDE_CRYPTO_WARNING: String = "support_override_crpto_warning"
public const val EXTRA_AUTOCRYPT_PEER_ID: String = "autocrypt_peer_id"
public const val EXTRA_AUTOCRYPT_PEER_UPDATE: String = "autocrypt_peer_update"
public const val EXTRA_AUTOCRYPT_PEER_GOSSIP_UPDATES: String = "autocrypt_peer_gossip_updates"
public const val RESULT_SIGNATURE: String = "signature"
public const val RESULT_DECRYPTION: String = "decryption"
public const val RESULT_METADATA: String = "metadata"
public const val RESULT_INSECURE_DETAIL_INTENT: String = "insecure_detail_intent"
public const val RESULT_OVERRIDE_CRYPTO_WARNING: String = "override_crypto_warning"
// This will be the charset which was specified in the headers of ascii armored input, if any
public const val RESULT_CHARSET: String = "charset"
// INTERNAL, must not be used
internal const val EXTRA_CALL_UUID1 = "call_uuid1"
internal const val EXTRA_CALL_UUID2 = "call_uuid2"
}
}

View file

@ -0,0 +1,88 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
package me.msfjarvis.openpgpktx.util
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import org.openintents.openpgp.IOpenPgpService2
public class OpenPgpServiceConnection(context: Context, providerPackageName: String?) {
// callback interface
public interface OnBound {
public fun onBound(service: IOpenPgpService2)
public fun onError(e: Exception)
}
private val mApplicationContext: Context = context.applicationContext
public var service: IOpenPgpService2? = null
private set
private val mProviderPackageName: String? = providerPackageName
private var mOnBoundListener: OnBound? = null
/**
* Create new connection with callback
*
* @param context
* @param providerPackageName specify package name of OpenPGP provider,
* e.g., "org.sufficientlysecure.keychain"
* @param onBoundListener callback, executed when connection to service has been established
*/
public constructor(
context: Context,
providerPackageName: String?,
onBoundListener: OnBound?
) : this(context, providerPackageName) {
mOnBoundListener = onBoundListener
}
public val isBound: Boolean
get() = service != null
private val mServiceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
this@OpenPgpServiceConnection.service = IOpenPgpService2.Stub.asInterface(service)
mOnBoundListener?.onBound(this@OpenPgpServiceConnection.service!!)
}
override fun onServiceDisconnected(name: ComponentName) {
service = null
}
}
/**
* If not already bound, bind to service!
*/
public fun bindToService() {
if (service == null) {
// if not already bound...
try {
val serviceIntent = Intent(OpenPgpApi.SERVICE_INTENT_2)
// NOTE: setPackage is very important to restrict the intent to this provider only!
serviceIntent.setPackage(mProviderPackageName)
val connect = mApplicationContext.bindService(
serviceIntent, mServiceConnection,
Context.BIND_AUTO_CREATE
)
if (!connect) {
throw Exception("bindService() returned false!")
}
} catch (e: Exception) {
mOnBoundListener?.onError(e)
}
} else {
// already bound, but also inform client about it with callback
mOnBoundListener?.onBound(service!!)
}
}
public fun unbindFromService() {
mApplicationContext.unbindService(mServiceConnection)
}
}

View file

@ -0,0 +1,115 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
package me.msfjarvis.openpgpktx.util
import android.content.Context
import android.content.Intent
import android.text.TextUtils
import java.io.Serializable
import java.util.Locale
import java.util.regex.Pattern
public object OpenPgpUtils {
private val PGP_MESSAGE: Pattern = Pattern.compile(
".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*",
Pattern.DOTALL
)
private val PGP_SIGNED_MESSAGE: Pattern = Pattern.compile(
".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",
Pattern.DOTALL
)
private val USER_ID_PATTERN = Pattern.compile("^(.*?)(?: \\((.*)\\))?(?: <(.*)>)?$")
private val EMAIL_PATTERN = Pattern.compile("^<?\"?([^<>\"]*@[^<>\"]*\\.[^<>\"]*)\"?>?$")
public const val PARSE_RESULT_NO_PGP: Int = -1
public const val PARSE_RESULT_MESSAGE: Int = 0
public const val PARSE_RESULT_SIGNED_MESSAGE: Int = 1
public fun parseMessage(message: String): Int {
val matcherSigned = PGP_SIGNED_MESSAGE.matcher(message)
val matcherMessage = PGP_MESSAGE.matcher(message)
return when {
matcherMessage.matches() -> PARSE_RESULT_MESSAGE
matcherSigned.matches() -> PARSE_RESULT_SIGNED_MESSAGE
else -> PARSE_RESULT_NO_PGP
}
}
public fun isAvailable(context: Context): Boolean {
val intent = Intent(OpenPgpApi.SERVICE_INTENT_2)
val resInfo =
context.packageManager.queryIntentServices(intent, 0)
return resInfo.isNotEmpty()
}
public fun convertKeyIdToHex(keyId: Long): String {
return "0x" + convertKeyIdToHex32bit(keyId shr 32) + convertKeyIdToHex32bit(
keyId
)
}
private fun convertKeyIdToHex32bit(keyId: Long): String {
var hexString =
java.lang.Long.toHexString(keyId and 0xffffffffL).toLowerCase(Locale.ENGLISH)
while (hexString.length < 8) {
hexString = "0$hexString"
}
return hexString
}
/**
* Splits userId string into naming part, email part, and comment part.
* See SplitUserIdTest for examples.
*/
public fun splitUserId(userId: String): UserId {
if (!TextUtils.isEmpty(userId)) {
val matcher = USER_ID_PATTERN.matcher(userId)
if (matcher.matches()) {
var name = if (matcher.group(1).isEmpty()) null else matcher.group(1)
val comment = matcher.group(2)
var email = matcher.group(3)
if (email != null && name != null) {
val emailMatcher = EMAIL_PATTERN.matcher(name)
if (emailMatcher.matches() && email == emailMatcher.group(1)) {
email = emailMatcher.group(1)
name = null
}
}
if (email == null && name != null) {
val emailMatcher = EMAIL_PATTERN.matcher(name)
if (emailMatcher.matches()) {
email = emailMatcher.group(1)
name = null
}
}
return UserId(name, email, comment)
}
}
return UserId(null, null, null)
}
/**
* Returns a composed user id. Returns null if name, email and comment are empty.
*/
public fun createUserId(userId: UserId): String? {
val userIdBuilder = StringBuilder()
if (!TextUtils.isEmpty(userId.name)) {
userIdBuilder.append(userId.name)
}
if (!TextUtils.isEmpty(userId.comment)) {
userIdBuilder.append(" (")
userIdBuilder.append(userId.comment)
userIdBuilder.append(")")
}
if (!TextUtils.isEmpty(userId.email)) {
userIdBuilder.append(" <")
userIdBuilder.append(userId.email)
userIdBuilder.append(">")
}
return if (userIdBuilder.isEmpty()) null else userIdBuilder.toString()
}
public class UserId(public val name: String?, public val email: String?, public val comment: String?) : Serializable
}

View file

@ -0,0 +1,63 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
package me.msfjarvis.openpgpktx.util
import android.os.ParcelFileDescriptor
import android.os.ParcelFileDescriptor.AutoCloseInputStream
import android.os.ParcelFileDescriptor.AutoCloseOutputStream
import android.util.Log
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
internal object ParcelFileDescriptorUtil {
private const val TAG = "PFDUtils"
@Throws(IOException::class)
internal fun pipeFrom(inputStream: InputStream): ParcelFileDescriptor {
val pipe = ParcelFileDescriptor.createPipe()
val readSide = pipe[0]
val writeSide = pipe[1]
TransferThread(inputStream, AutoCloseOutputStream(writeSide))
.start()
return readSide
}
@Throws(IOException::class)
internal fun pipeTo(outputStream: OutputStream, output: ParcelFileDescriptor?): TransferThread {
val t = TransferThread(AutoCloseInputStream(output), outputStream)
t.start()
return t
}
internal class TransferThread(val `in`: InputStream, private val out: OutputStream) : Thread("IPC Transfer Thread") {
override fun run() {
val buf = ByteArray(4096)
var len: Int
try {
while (`in`.read(buf).also { len = it } > 0) {
out.write(buf, 0, len)
}
} catch (e: IOException) {
Log.e(TAG, "IOException when writing to out", e)
} finally {
try {
`in`.close()
} catch (ignored: IOException) {
}
try {
out.close()
} catch (ignored: IOException) {
}
}
}
init {
isDaemon = true
}
}
}

View file

@ -0,0 +1,126 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
@file:JvmName("OpenPgpDecryptionResult")
package org.openintents.openpgp
import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
public class OpenPgpDecryptionResult() : Parcelable {
private var result = 0
private var sessionKey: ByteArray? = null
private var decryptedSessionKey: ByteArray? = null
private constructor(result: Int) : this() {
this.result = result
sessionKey = null
decryptedSessionKey = null
}
private constructor(
result: Int,
sessionKey: ByteArray?,
decryptedSessionKey: ByteArray?
) : this() {
this.result = result
if (sessionKey == null != (decryptedSessionKey == null)) {
throw AssertionError("sessionkey must be null iff decryptedSessionKey is null")
}
this.sessionKey = sessionKey
this.decryptedSessionKey = decryptedSessionKey
}
public fun getResult(): Int {
return result
}
public fun hasDecryptedSessionKey(): Boolean {
return sessionKey != null
}
public fun getSessionKey(): ByteArray? {
return if (sessionKey == null) {
null
} else sessionKey!!.copyOf(sessionKey!!.size)
}
public fun getDecryptedSessionKey(): ByteArray? {
return if (sessionKey == null || decryptedSessionKey == null) {
null
} else decryptedSessionKey!!.copyOf(decryptedSessionKey!!.size)
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
/**
* NOTE: When adding fields in the process of updating this API, make sure to bump
* [.PARCELABLE_VERSION].
*/
dest.writeInt(PARCELABLE_VERSION)
// Inject a placeholder that will store the parcel size from this point on
// (not including the size itself).
val sizePosition = dest.dataPosition()
dest.writeInt(0)
val startPosition = dest.dataPosition()
// version 1
dest.writeInt(result)
// version 2
dest.writeByteArray(sessionKey)
dest.writeByteArray(decryptedSessionKey)
// Go back and write the size
val parcelableSize = dest.dataPosition() - startPosition
dest.setDataPosition(sizePosition)
dest.writeInt(parcelableSize)
dest.setDataPosition(startPosition + parcelableSize)
}
override fun toString(): String {
return "\nresult: $result"
}
public companion object CREATOR : Creator<OpenPgpDecryptionResult> {
/**
* Since there might be a case where new versions of the client using the library getting
* old versions of the protocol (and thus old versions of this class), we need a versioning
* system for the parcels sent between the clients and the providers.
*/
private const val PARCELABLE_VERSION = 2
// content not encrypted
public const val RESULT_NOT_ENCRYPTED: Int = -1
// insecure!
public const val RESULT_INSECURE: Int = 0
// encrypted
public const val RESULT_ENCRYPTED: Int = 1
override fun createFromParcel(source: Parcel): OpenPgpDecryptionResult? {
val version = source.readInt() // parcelableVersion
val parcelableSize = source.readInt()
val startPosition = source.dataPosition()
val result = source.readInt()
val sessionKey = if (version > 1) source.createByteArray() else null
val decryptedSessionKey =
if (version > 1) source.createByteArray() else null
val vr =
OpenPgpDecryptionResult(result, sessionKey, decryptedSessionKey)
// skip over all fields added in future versions of this parcel
source.setDataPosition(startPosition + parcelableSize)
return vr
}
override fun newArray(size: Int): Array<OpenPgpDecryptionResult?> {
return arrayOfNulls(size)
}
}
}

View file

@ -0,0 +1,91 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
@file:JvmName("OpenPgpError")
package org.openintents.openpgp
import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
public class OpenPgpError() : Parcelable {
public var errorId: Int = 0
public var message: String? = null
private constructor(parcel: Parcel) : this() {
errorId = parcel.readInt()
message = parcel.readString()
}
internal constructor(errorId: Int, message: String?) : this() {
this.errorId = errorId
this.message = message
}
internal constructor(b: OpenPgpError) : this() {
errorId = b.errorId
message = b.message
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
/**
* NOTE: When adding fields in the process of updating this API, make sure to bump
* [PARCELABLE_VERSION].
*/
dest.writeInt(PARCELABLE_VERSION)
// Inject a placeholder that will store the parcel size from this point on
// (not including the size itself).
val sizePosition = dest.dataPosition()
dest.writeInt(0)
val startPosition = dest.dataPosition()
// version 1
dest.writeInt(errorId)
dest.writeString(message)
// Go back and write the size
val parcelableSize = dest.dataPosition() - startPosition
dest.setDataPosition(sizePosition)
dest.writeInt(parcelableSize)
dest.setDataPosition(startPosition + parcelableSize)
}
public companion object CREATOR : Creator<OpenPgpError> {
/**
* Since there might be a case where new versions of the client using the library getting
* old versions of the protocol (and thus old versions of this class), we need a versioning
* system for the parcels sent between the clients and the providers.
*/
private const val PARCELABLE_VERSION = 1
// possible values for errorId
public const val CLIENT_SIDE_ERROR: Int = -1
public const val GENERIC_ERROR: Int = 0
public const val INCOMPATIBLE_API_VERSIONS: Int = 1
public const val NO_OR_WRONG_PASSPHRASE: Int = 2
public const val NO_USER_IDS: Int = 3
public const val OPPORTUNISTIC_MISSING_KEYS: Int = 4
override fun createFromParcel(source: Parcel): OpenPgpError? {
source.readInt() // parcelableVersion
val parcelableSize = source.readInt()
val startPosition = source.dataPosition()
val error = OpenPgpError()
error.errorId = source.readInt()
error.message = source.readString()
// skip over all fields added in future versions of this parcel
source.setDataPosition(startPosition + parcelableSize)
return error
}
override fun newArray(size: Int): Array<OpenPgpError?> {
return arrayOfNulls(size)
}
}
}

View file

@ -0,0 +1,122 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
@file:JvmName("OpenPgpMetadata")
package org.openintents.openpgp
import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
public class OpenPgpMetadata() : Parcelable {
public var filename: String? = null
public var mimeType: String? = null
public var charset: String? = null
public var modificationTime: Long = 0
public var originalSize: Long = 0
private constructor(
filename: String?,
mimeType: String?,
modificationTime: Long,
originalSize: Long,
charset: String?
) : this() {
this.filename = filename
this.mimeType = mimeType
this.modificationTime = modificationTime
this.originalSize = originalSize
this.charset = charset
}
private constructor(
filename: String?,
mimeType: String?,
modificationTime: Long,
originalSize: Long
) : this() {
this.filename = filename
this.mimeType = mimeType
this.modificationTime = modificationTime
this.originalSize = originalSize
}
private constructor(b: OpenPgpMetadata) : this() {
filename = b.filename
mimeType = b.mimeType
modificationTime = b.modificationTime
originalSize = b.originalSize
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
/**
* NOTE: When adding fields in the process of updating this API, make sure to bump
* [PARCELABLE_VERSION].
*/
dest.writeInt(PARCELABLE_VERSION)
// Inject a placeholder that will store the parcel size from this point on
// (not including the size itself).
val sizePosition = dest.dataPosition()
dest.writeInt(0)
val startPosition = dest.dataPosition()
// version 1
dest.writeString(filename)
dest.writeString(mimeType)
dest.writeLong(modificationTime)
dest.writeLong(originalSize)
// version 2
dest.writeString(charset)
// Go back and write the size
val parcelableSize = dest.dataPosition() - startPosition
dest.setDataPosition(sizePosition)
dest.writeInt(parcelableSize)
dest.setDataPosition(startPosition + parcelableSize)
}
public companion object CREATOR : Creator<OpenPgpMetadata> {
/**
* Since there might be a case where new versions of the client using the library getting
* old versions of the protocol (and thus old versions of this class), we need a versioning
* system for the parcels sent between the clients and the providers.
*/
private const val PARCELABLE_VERSION = 2
override fun createFromParcel(source: Parcel): OpenPgpMetadata? {
val version = source.readInt() // parcelableVersion
val parcelableSize = source.readInt()
val startPosition = source.dataPosition()
val vr = OpenPgpMetadata()
vr.filename = source.readString()
vr.mimeType = source.readString()
vr.modificationTime = source.readLong()
vr.originalSize = source.readLong()
if (version >= 2) {
vr.charset = source.readString()
}
// skip over all fields added in future versions of this parcel
source.setDataPosition(startPosition + parcelableSize)
return vr
}
override fun newArray(size: Int): Array<OpenPgpMetadata?> {
return arrayOfNulls(size)
}
}
override fun toString(): String {
var out = "\nfilename: $filename"
out += "\nmimeType: $mimeType"
out += "\nmodificationTime: $modificationTime"
out += "\noriginalSize: $originalSize"
out += "\ncharset: $charset"
return out
}
}

View file

@ -0,0 +1,294 @@
/*
* Copyright © 2019 The Android Password Authors. All Rights Reserved.
* SPDX-License-Identifier: LGPL-3.0-only WITH LGPL-3.0-linking-exception
*/
@file:JvmName("OpenPgpSignatureResult")
package org.openintents.openpgp
import android.os.Parcel
import android.os.Parcelable
import android.os.Parcelable.Creator
import java.util.Date
import me.msfjarvis.openpgpktx.util.OpenPgpUtils
public class OpenPgpSignatureResult : Parcelable {
private val result: Int
private val keyId: Long
private val primaryUserId: String?
private val userIds: ArrayList<String>?
private val confirmedUserIds: ArrayList<String>?
private val senderStatusResult: SenderStatusResult?
private val signatureTimestamp: Date?
private val autocryptPeerentityResult: AutocryptPeerResult?
private constructor(
signatureStatus: Int,
signatureUserId: String?,
keyId: Long,
userIds: ArrayList<String>?,
confirmedUserIds: ArrayList<String>?,
senderStatusResult: SenderStatusResult?,
signatureOnly: Boolean?,
signatureTimestamp: Date?,
autocryptPeerentityResult: AutocryptPeerResult?
) {
result = signatureStatus
primaryUserId = signatureUserId
this.keyId = keyId
this.userIds = userIds
this.confirmedUserIds = confirmedUserIds
this.senderStatusResult = senderStatusResult
this.signatureTimestamp = signatureTimestamp
this.autocryptPeerentityResult = autocryptPeerentityResult
}
private constructor(source: Parcel, version: Int) {
result = source.readInt()
// we dropped support for signatureOnly, but need to skip the value for compatibility
source.readByte()
primaryUserId = source.readString()
keyId = source.readLong()
userIds = if (version > 1) {
source.createStringArrayList()
} else {
null
}
// backward compatibility for this exact version
if (version > 2) {
senderStatusResult = readEnumWithNullAndFallback(
source,
SenderStatusResult.values(),
SenderStatusResult.UNKNOWN
)
confirmedUserIds = source.createStringArrayList()
} else {
senderStatusResult = SenderStatusResult.UNKNOWN
confirmedUserIds = null
}
signatureTimestamp = if (version > 3) {
if (source.readInt() > 0) Date(source.readLong()) else null
} else {
null
}
autocryptPeerentityResult = if (version > 4) {
readEnumWithNullAndFallback(
source,
AutocryptPeerResult.values(),
null
)
} else {
null
}
}
public fun getUserIds(): List<String> {
return (userIds ?: arrayListOf()).toList()
}
public fun getConfirmedUserIds(): List<String> {
return (confirmedUserIds ?: arrayListOf()).toList()
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
/**
* NOTE: When adding fields in the process of updating this API, make sure to bump
* [.PARCELABLE_VERSION].
*/
dest.writeInt(PARCELABLE_VERSION)
// Inject a placeholder that will store the parcel size from this point on
// (not including the size itself).
val sizePosition = dest.dataPosition()
dest.writeInt(0)
val startPosition = dest.dataPosition()
// version 1
dest.writeInt(result)
// signatureOnly is deprecated since version 3. we pass a dummy value for compatibility
dest.writeByte(0.toByte())
dest.writeString(primaryUserId)
dest.writeLong(keyId)
// version 2
dest.writeStringList(userIds)
// version 3
writeEnumWithNull(dest, senderStatusResult)
dest.writeStringList(confirmedUserIds)
// version 4
if (signatureTimestamp != null) {
dest.writeInt(1)
dest.writeLong(signatureTimestamp.time)
} else {
dest.writeInt(0)
}
// version 5
writeEnumWithNull(dest, autocryptPeerentityResult)
// Go back and write the size
val parcelableSize = dest.dataPosition() - startPosition
dest.setDataPosition(sizePosition)
dest.writeInt(parcelableSize)
dest.setDataPosition(startPosition + parcelableSize)
}
override fun toString(): String {
var out = "\nresult: $result"
out += "\nprimaryUserId: $primaryUserId"
out += "\nuserIds: $userIds"
out += "\nkeyId: " + OpenPgpUtils.convertKeyIdToHex(keyId)
return out
}
@Deprecated("")
public fun withSignatureOnlyFlag(signatureOnly: Boolean): OpenPgpSignatureResult {
return OpenPgpSignatureResult(
result, primaryUserId, keyId, userIds, confirmedUserIds,
senderStatusResult, signatureOnly, signatureTimestamp, autocryptPeerentityResult
)
}
public fun withAutocryptPeerResult(autocryptPeerentityResult: AutocryptPeerResult?): OpenPgpSignatureResult {
return OpenPgpSignatureResult(
result, primaryUserId, keyId, userIds, confirmedUserIds,
senderStatusResult, null, signatureTimestamp, autocryptPeerentityResult
)
}
public enum class SenderStatusResult {
UNKNOWN, USER_ID_CONFIRMED, USER_ID_UNCONFIRMED, USER_ID_MISSING;
}
public enum class AutocryptPeerResult {
OK, NEW, MISMATCH;
}
public companion object CREATOR : Creator<OpenPgpSignatureResult> {
/**
* Since there might be a case where new versions of the client using the library getting
* old versions of the protocol (and thus old versions of this class), we need a versioning
* system for the parcels sent between the clients and the providers.
*/
private const val PARCELABLE_VERSION = 5
// content not signed
public const val RESULT_NO_SIGNATURE: Int = -1
// invalid signature!
public const val RESULT_INVALID_SIGNATURE: Int = 0
// successfully verified signature, with confirmed key
public const val RESULT_VALID_KEY_CONFIRMED: Int = 1
// no key was found for this signature verification
public const val RESULT_KEY_MISSING: Int = 2
// successfully verified signature, but with unconfirmed key
public const val RESULT_VALID_KEY_UNCONFIRMED: Int = 3
// key has been revoked -> invalid signature!
public const val RESULT_INVALID_KEY_REVOKED: Int = 4
// key is expired -> invalid signature!
public const val RESULT_INVALID_KEY_EXPIRED: Int = 5
// insecure cryptographic algorithms/protocol -> invalid signature!
public const val RESULT_INVALID_KEY_INSECURE: Int = 6
override fun createFromParcel(source: Parcel): OpenPgpSignatureResult? {
val version = source.readInt() // parcelableVersion
val parcelableSize = source.readInt()
val startPosition = source.dataPosition()
val vr = OpenPgpSignatureResult(source, version)
// skip over all fields added in future versions of this parcel
source.setDataPosition(startPosition + parcelableSize)
return vr
}
override fun newArray(size: Int): Array<OpenPgpSignatureResult?> {
return arrayOfNulls(size)
}
public fun createWithValidSignature(
signatureStatus: Int,
primaryUserId: String?,
keyId: Long,
userIds: ArrayList<String>?,
confirmedUserIds: ArrayList<String>?,
senderStatusResult: SenderStatusResult?,
signatureTimestamp: Date?
): OpenPgpSignatureResult {
require(!(signatureStatus == RESULT_NO_SIGNATURE || signatureStatus == RESULT_KEY_MISSING || signatureStatus == RESULT_INVALID_SIGNATURE)) { "can only use this method for valid types of signatures" }
return OpenPgpSignatureResult(
signatureStatus, primaryUserId, keyId, userIds, confirmedUserIds,
senderStatusResult, null, signatureTimestamp, null
)
}
public fun createWithNoSignature(): OpenPgpSignatureResult {
return OpenPgpSignatureResult(
RESULT_NO_SIGNATURE,
null,
0L,
null,
null,
null,
null,
null,
null
)
}
public fun createWithKeyMissing(keyId: Long, signatureTimestamp: Date?): OpenPgpSignatureResult {
return OpenPgpSignatureResult(
RESULT_KEY_MISSING,
null,
keyId,
null,
null,
null,
null,
signatureTimestamp,
null
)
}
public fun createWithInvalidSignature(): OpenPgpSignatureResult {
return OpenPgpSignatureResult(
RESULT_INVALID_SIGNATURE,
null,
0L,
null,
null,
null,
null,
null,
null
)
}
private fun <T : Enum<T>?> readEnumWithNullAndFallback(
source: Parcel,
enumValues: Array<T>,
fallback: T?
): T? {
val valueOrdinal = source.readInt()
if (valueOrdinal == -1) {
return null
}
return if (valueOrdinal >= enumValues.size) {
fallback
} else enumValues[valueOrdinal]
}
private fun writeEnumWithNull(dest: Parcel, enumValue: Enum<*>?) {
if (enumValue == null) {
dest.writeInt(-1)
return
}
dest.writeInt(enumValue.ordinal)
}
}
}

View file

@ -4,6 +4,7 @@
*/ */
include(":autofill-parser") include(":autofill-parser")
include(":app") include(":app")
include(":openpgp-ktx")
pluginManagement { pluginManagement {
repositories { repositories {