Skip to content

Commit

Permalink
Add Kyber KEM and implement PQXDH protocol
Browse files Browse the repository at this point in the history
Co-authored-by: Jordan Rose <[email protected]>
Co-authored-by: Max Moiseev <[email protected]>
  • Loading branch information
3 people committed May 9, 2023
1 parent 2b46ae1 commit ff09619
Show file tree
Hide file tree
Showing 64 changed files with 2,720 additions and 278 deletions.
51 changes: 51 additions & 0 deletions Cargo.lock

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

17 changes: 12 additions & 5 deletions java/build_jni.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,19 @@ then
# Use small BoringSSL curve tables to reduce binary size on Android.
export CFLAGS="-DOPENSSL_SMALL -flto=thin ${CFLAGS:-}"

# Use the Android NDK's prebuilt Clang+lld as Rust's linker.
# Use the Android NDK's prebuilt Clang+lld as pqcrypto's compiler and Rust's linker.
ANDROID_TOOLCHAIN_DIR=$(echo "${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt"/*/bin/)
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="${ANDROID_TOOLCHAIN_DIR}/aarch64-linux-android21-clang"
export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="${ANDROID_TOOLCHAIN_DIR}/armv7a-linux-androideabi21-clang"
export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="${ANDROID_TOOLCHAIN_DIR}/x86_64-linux-android21-clang"
export CARGO_TARGET_I686_LINUX_ANDROID_LINKER="${ANDROID_TOOLCHAIN_DIR}/i686-linux-android21-clang"
export CC_aarch64_linux_android="${ANDROID_TOOLCHAIN_DIR}/aarch64-linux-android21-clang"
export CC_armv7_linux_androideabi="${ANDROID_TOOLCHAIN_DIR}/armv7a-linux-androideabi21-clang"
export CC_x86_64_linux_android="${ANDROID_TOOLCHAIN_DIR}/x86_64-linux-android21-clang"
export CC_i686_linux_android="${ANDROID_TOOLCHAIN_DIR}/i686-linux-android21-clang"

export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="${CC_aarch64_linux_android}"
export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="${CC_armv7_linux_androideabi}"
export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="${CC_x86_64_linux_android}"
export CARGO_TARGET_I686_LINUX_ANDROID_LINKER="${CC_i686_linux_android}"

export TARGET_AR="${ANDROID_TOOLCHAIN_DIR}/llvm-ar"
export RUSTFLAGS="-C link-arg=-fuse-ld=lld ${RUSTFLAGS:-}"

echo_then_run cargo build -p libsignal-jni --release -Z unstable-options --target aarch64-linux-android --out-dir "${ANDROID_LIB_DIR}/arm64-v8a"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.signal.libsignal.protocol.groups.GroupCipher;
import org.signal.libsignal.protocol.groups.GroupSessionBuilder;
import org.signal.libsignal.protocol.kem.KEMKeyPair;
import org.signal.libsignal.protocol.kem.KEMKeyType;
import org.signal.libsignal.protocol.message.CiphertextMessage;
import org.signal.libsignal.protocol.message.DecryptionErrorMessage;
import org.signal.libsignal.protocol.message.PlaintextContent;
Expand All @@ -32,12 +34,12 @@
import org.signal.libsignal.protocol.state.PreKeyRecord;
import org.signal.libsignal.protocol.state.SessionRecord;
import org.signal.libsignal.protocol.state.SignedPreKeyRecord;
import org.signal.libsignal.protocol.state.KyberPreKeyRecord;

import org.signal.libsignal.internal.Native;
import org.signal.libsignal.internal.NativeHandleGuard;

import org.signal.libsignal.protocol.util.Hex;
import org.signal.libsignal.protocol.util.Pair;

import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -55,6 +57,14 @@ private static SignedPreKeyRecord generateSignedPreKey(IdentityKeyPair identityK
return new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), keyPair, signature);
}

private static KyberPreKeyRecord generateKyberPreKey(IdentityKeyPair identityKeyPair, int kyberPreKeyId)
throws InvalidKeyException {
KEMKeyPair keyPair = KEMKeyPair.generate(KEMKeyType.KYBER_1024);
byte[] signature = Curve.calculateSignature(identityKeyPair.getPrivateKey(), keyPair.getPublicKey().serialize());

return new KyberPreKeyRecord(kyberPreKeyId, System.currentTimeMillis(), keyPair, signature);
}

public void testEncryptDecrypt() throws UntrustedIdentityException, InvalidKeyException, InvalidCertificateException, InvalidMetadataMessageException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, InvalidMetadataVersionException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException {
TestInMemorySignalProtocolStore aliceStore = new TestInMemorySignalProtocolStore();
TestInMemorySignalProtocolStore bobStore = new TestInMemorySignalProtocolStore();
Expand Down Expand Up @@ -201,8 +211,9 @@ public void testEncryptGroupWithBadRegistrationId() throws UntrustedIdentityExce
ECKeyPair bobPreKey = Curve.generateKeyPair();
IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
SignedPreKeyRecord bobSignedPreKey = generateSignedPreKey(bobIdentityKey, 2);
KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);

PreKeyBundle bobBundle = new PreKeyBundle(0x4000, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey());
PreKeyBundle bobBundle = new PreKeyBundle(0x4000, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey(), 12, bobKyberPreKey.getKeyPair().getPublicKey(), bobKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, bobAddress);
aliceSessionBuilder.process(bobBundle);

Expand Down Expand Up @@ -239,16 +250,18 @@ public void testEncryptGroupWithManyRecipients() throws UntrustedIdentityExcepti
ECKeyPair bobPreKey = Curve.generateKeyPair();
IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
SignedPreKeyRecord bobSignedPreKey = generateSignedPreKey(bobIdentityKey, 2);
KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);

PreKeyBundle bobBundle = new PreKeyBundle(0x1234, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey());
PreKeyBundle bobBundle = new PreKeyBundle(0x1234, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey(), 12, bobKyberPreKey.getKeyPair().getPublicKey(), bobKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilderForBob = new SessionBuilder(aliceStore, bobAddress);
aliceSessionBuilderForBob.process(bobBundle);

ECKeyPair carolPreKey = Curve.generateKeyPair();
IdentityKeyPair carolIdentityKey = carolStore.getIdentityKeyPair();
SignedPreKeyRecord carolSignedPreKey = generateSignedPreKey(carolIdentityKey, 2);
KyberPreKeyRecord carolKyberPreKey = generateKyberPreKey(carolIdentityKey, 12);

PreKeyBundle carolBundle = new PreKeyBundle(0x1111, 1, 1, carolPreKey.getPublicKey(), 2, carolSignedPreKey.getKeyPair().getPublicKey(), carolSignedPreKey.getSignature(), carolIdentityKey.getPublicKey());
PreKeyBundle carolBundle = new PreKeyBundle(0x1111, 1, 1, carolPreKey.getPublicKey(), 2, carolSignedPreKey.getKeyPair().getPublicKey(), carolSignedPreKey.getSignature(), carolIdentityKey.getPublicKey(), 12, carolKyberPreKey.getKeyPair().getPublicKey(), carolKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilderForCarol = new SessionBuilder(aliceStore, carolAddress);
aliceSessionBuilderForCarol.process(carolBundle);

Expand Down Expand Up @@ -384,13 +397,14 @@ private void initializeSessions(TestInMemorySignalProtocolStore aliceStore, Test
ECKeyPair bobPreKey = Curve.generateKeyPair();
IdentityKeyPair bobIdentityKey = bobStore.getIdentityKeyPair();
SignedPreKeyRecord bobSignedPreKey = generateSignedPreKey(bobIdentityKey, 2);
KyberPreKeyRecord bobKyberPreKey = generateKyberPreKey(bobIdentityKey, 12);

PreKeyBundle bobBundle = new PreKeyBundle(1, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey());
PreKeyBundle bobBundle = new PreKeyBundle(1, 1, 1, bobPreKey.getPublicKey(), 2, bobSignedPreKey.getKeyPair().getPublicKey(), bobSignedPreKey.getSignature(), bobIdentityKey.getPublicKey(), 12, bobKyberPreKey.getKeyPair().getPublicKey(), bobKyberPreKey.getSignature());
SessionBuilder aliceSessionBuilder = new SessionBuilder(aliceStore, bobAddress);
aliceSessionBuilder.process(bobBundle);

bobStore.storeSignedPreKey(2, bobSignedPreKey);
bobStore.storeKyberPreKey(12, bobKyberPreKey);
bobStore.storePreKey(1, new PreKeyRecord(1, bobPreKey));

}
}
Loading

0 comments on commit ff09619

Please sign in to comment.