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
39 changes: 38 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,38 @@
/build
*.iml
.gradle
/local.properties
/.idea/*
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
double_ratchet/build/*
double_ratchet/build/
double_ratchet/build
/captures
.externalNativeBuild
.cxx
*.aab
*.apk
local.properties
keystore.properties
*.jks
ks.passwd
venv/*
/release.properties
*.sw*
gradle.properties
*.tmp.sh
*.logs
/double_ratchet/.idea/.gitignore
/double_ratchet/.ideadouble_ratchetInsightsSettings.xml
/double_ratchet/.idea/caches/deviceStreaming.xml
/double_ratchet/.idea/gradle.xml
/double_ratchet/.idea/migrations.xml
/double_ratchet/.idea/misc.xml
/double_ratchet/.idea/runConfigurations.xml
/double_ratchet/.idea/vcs.xml
99 changes: 23 additions & 76 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,84 +1,31 @@
plugins {
id 'com.android.library'
// id 'maven-publish'
id 'signing'
id 'org.jetbrains.kotlin.android'
id "com.vanniktech.maven.publish" version "0.34.0"
id 'org.jetbrains.kotlin.plugin.serialization' version '2.2.10'
}

android {
namespace 'com.afkanerd.smswithoutborders.libsignal_doubleratchet'
compileSdk 36

defaultConfig {
minSdk 24
targetSdk 36

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aarMetadata {
minCompileSdk = 24
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
// kotlin_version = '1.8.20-RC'
// kotlin_version = '1.9.23'
kotlin_version = '2.3.10'
agp_version = '8.5.0'
agp_version1 = '8.12.2'
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
nightly {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:$agp_version1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

testFixtures {
enable = true
}

kotlinOptions {
jvmTarget = '17'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

import com.vanniktech.maven.publish.AndroidSingleVariantLibrary
mavenPublishing {
// the first parameter represennts which variant is published
// the second whether to publish a sources jar
// the third whether to publish a javadoc jar
configure(new AndroidSingleVariantLibrary("release", true, true))
plugins {
// Existing plugins
// alias(libs.plugins.compose.compiler) apply false
// alias(libs.plugins.org.jetbrains.kotlin.android) apply false
}



dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', "*.aar"])
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.guava:guava:33.4.8-jre'
implementation 'com.madgag.spongycastle:prov:1.58.0.0'
implementation 'org.conscrypt:conscrypt-android:2.5.3'
implementation 'androidx.core:core-ktx:1.13.1'

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'

implementation 'com.github.netricecake:x25519:2.0'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'at.favre.lib:hkdf:2.0.0'

implementation "androidx.datastore:datastore-preferences:1.1.7"

// optional - RxJava2 support
implementation "androidx.datastore:datastore-preferences-rxjava2:1.1.7"

// optional - RxJava3 support
implementation "androidx.datastore:datastore-preferences-rxjava3:1.1.7"

implementation "androidx.datastore:datastore-preferences-core:1.1.7"

implementation 'com.google.code.gson:gson:2.11.0'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0"
}
tasks.register('clean', Delete) {
delete rootProject.buildDir
}
73 changes: 73 additions & 0 deletions double_ratchet/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
plugins {
id 'com.android.library'
// id 'maven-publish'
id 'signing'
id 'org.jetbrains.kotlin.android'
id "com.vanniktech.maven.publish" version "0.34.0"
id 'org.jetbrains.kotlin.plugin.serialization' version '2.2.10'
}

android {
namespace 'com.afkanerd.smswithoutborders.libsignal_doubleratchet'
compileSdk 36

defaultConfig {
minSdk 24
targetSdk 36

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aarMetadata {
minCompileSdk = 24
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
nightly {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}

testFixtures {
enable = true
}

kotlinOptions {
jvmTarget = '17'
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', "*.aar"])
implementation 'androidx.appcompat:appcompat:1.7.1'
implementation 'com.google.guava:guava:33.5.0-jre'
implementation 'org.conscrypt:conscrypt-android:2.5.3'
implementation 'androidx.core:core-ktx:1.18.0'

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'

implementation 'com.google.code.gson:gson:2.13.2'
implementation 'at.favre.lib:hkdf:2.0.0'

implementation "androidx.datastore:datastore-preferences:1.2.1"

// optional - RxJava2 support
implementation "androidx.datastore:datastore-preferences-rxjava2:1.2.1"

// optional - RxJava3 support
implementation "androidx.datastore:datastore-preferences-rxjava3:1.2.1"

implementation "androidx.datastore:datastore-preferences-core:1.2.1"

implementation 'com.google.code.gson:gson:2.13.2'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.11.0"
implementation("org.bouncycastle:bcprov-jdk18on:1.83")
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package com.afkanerd.smswithoutborders.libsignal_doubleratchet

import android.content.Context
import androidx.test.espresso.internal.inject.InstrumentationContext
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.afkanerd.smswithoutborders.libsignal_doubleratchet.extensions.generateRandomBytes
import org.junit.Assert.assertArrayEquals
import org.junit.Test
import javax.crypto.SecretKey

@SmallTest
class SecurityAESTest {

var context: Context = InstrumentationRegistry.getInstrumentation().targetContext
@Test
fun aesTest() {
val secretKey = SecurityAES.generateSecretKey(256)

val input = CryptoHelpers.generateRandomBytes(277)
val input = context.generateRandomBytes(277)
val cipher = SecurityAES.encryptAES256CBC(input, secretKey.encoded, null)
val output = SecurityAES.decryptAES256CBC(cipher, secretKey.encoded, null)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ public void testCanStoreAndEncrypt() throws NoSuchAlgorithmException, NoSuchProv
// .build());
//
// KeyPair keyPair = kpg.generateKeyPair();
PublicKey publicKey = SecurityRSA.generateKeyPair(keystoreAlias, 2048);
KeyPair keyPair = KeystoreHelpers.getKeyPairFromKeystore(keystoreAlias);

SecretKey secretKey = SecurityAES.generateSecretKey(256);
byte[] cipherText = SecurityRSA.encrypt(keyPair.getPublic(), secretKey.getEncoded());
byte[] plainText = SecurityRSA.decrypt(keyPair.getPrivate(), cipherText);
assertArrayEquals(secretKey.getEncoded(), plainText);
// PublicKey publicKey = SecurityRSA.generateKeyPair(keystoreAlias, 2048);
// KeyPair keyPair = KeystoreHelpers.getKeyPairFromKeystore(keystoreAlias);
//
// SecretKey secretKey = SecurityAES.generateSecretKey(256);
// byte[] cipherText = SecurityRSA.encrypt(keyPair.getPublic(), secretKey.getEncoded());
// byte[] plainText = SecurityRSA.decrypt(keyPair.getPrivate(), cipherText);
// assertArrayEquals(secretKey.getEncoded(), plainText);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.afkanerd.smswithoutborders.libsignal_doubleratchet

import android.content.Context
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import com.afkanerd.smswithoutborders.libsignal_doubleratchet.libsignal.Protocols
import org.junit.Assert.assertArrayEquals
import org.junit.Test
import java.security.KeyPairGenerator
import java.security.KeyStore
import java.security.Signature

@SmallTest
class SecurityX25519Test {

var context: Context = InstrumentationRegistry.getInstrumentation().targetContext

@Test
fun keystoreEd25519() {
val keystoreAlias = "keystoreAlias"
val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_EC,
"AndroidKeyStore"
)
val parameterSpec: KeyGenParameterSpec = KeyGenParameterSpec.Builder(
keystoreAlias,
KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
).run {
setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
build()
}

kpg.initialize(parameterSpec)
val kp = kpg.generateKeyPair()

val ks: KeyStore = KeyStore.getInstance("AndroidKeyStore").apply {
load(null)
}
val entry: KeyStore.Entry = ks.getEntry(keystoreAlias, null)
if (entry !is KeyStore.PrivateKeyEntry) {
throw Exception("No instance of keystore")
}

val data = "Hello world".encodeToByteArray()
val signature: ByteArray = Signature.getInstance("SHA256withECDSA").run {
initSign(entry.privateKey)
update(data)
sign()
}

}

@Test
fun sharedSecret() {
val protocols = Protocols(context)
val alice = protocols.generateDH()
val bob = protocols.generateDH()

val aliceSharedSecret = protocols.dh(alice, bob.public)
val bobSharedSecret = protocols.dh(bob, alice.public)

assertArrayEquals(aliceSharedSecret, bobSharedSecret)
}
}
Loading