mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-12 11:14:20 +00:00
Curve25519 keys to 1 mod 8 for ephemerals.
This commit is contained in:
parent
fd1a18d2d0
commit
5a3daf4846
@ -22,11 +22,16 @@
|
|||||||
#include "curve25519-donna.h"
|
#include "curve25519-donna.h"
|
||||||
|
|
||||||
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_textsecure_crypto_ecc_Curve25519_generatePrivateKey
|
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_textsecure_crypto_ecc_Curve25519_generatePrivateKey
|
||||||
(JNIEnv *env, jclass clazz, jbyteArray random)
|
(JNIEnv *env, jclass clazz, jbyteArray random, jboolean ephemeral)
|
||||||
{
|
{
|
||||||
uint8_t* privateKey = (uint8_t*)(*env)->GetByteArrayElements(env, random, 0);
|
uint8_t* privateKey = (uint8_t*)(*env)->GetByteArrayElements(env, random, 0);
|
||||||
|
|
||||||
privateKey[0] &= 248;
|
privateKey[0] &= 248;
|
||||||
|
|
||||||
|
if (ephemeral) {
|
||||||
|
privateKey[0] |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
privateKey[31] &= 127;
|
privateKey[31] &= 127;
|
||||||
privateKey[31] |= 64;
|
privateKey[31] |= 64;
|
||||||
|
|
||||||
|
@ -720,9 +720,6 @@ curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 32; ++i) e[i] = secret[i];
|
for (i = 0; i < 32; ++i) e[i] = secret[i];
|
||||||
e[0] &= 248;
|
|
||||||
e[31] &= 127;
|
|
||||||
e[31] |= 64;
|
|
||||||
|
|
||||||
fexpand(bp, basepoint);
|
fexpand(bp, basepoint);
|
||||||
cmult(x, z, e, bp);
|
cmult(x, z, e, bp);
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -48,7 +48,7 @@ public class PreKeyUtil {
|
|||||||
|
|
||||||
for (int i=0;i<BATCH_SIZE;i++) {
|
for (int i=0;i<BATCH_SIZE;i++) {
|
||||||
int preKeyId = (preKeyIdOffset + i) % Medium.MAX_VALUE;
|
int preKeyId = (preKeyIdOffset + i) % Medium.MAX_VALUE;
|
||||||
ECKeyPair keyPair = Curve25519.generateKeyPair();
|
ECKeyPair keyPair = Curve25519.generateKeyPair(true);
|
||||||
PreKeyRecord record = new PreKeyRecord(context, masterSecret, preKeyId, keyPair);
|
PreKeyRecord record = new PreKeyRecord(context, masterSecret, preKeyId, keyPair);
|
||||||
|
|
||||||
record.save();
|
record.save();
|
||||||
@ -69,7 +69,7 @@ public class PreKeyUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ECKeyPair keyPair = Curve25519.generateKeyPair();
|
ECKeyPair keyPair = Curve25519.generateKeyPair(true);
|
||||||
PreKeyRecord record = new PreKeyRecord(context, masterSecret, Medium.MAX_VALUE, keyPair);
|
PreKeyRecord record = new PreKeyRecord(context, masterSecret, Medium.MAX_VALUE, keyPair);
|
||||||
|
|
||||||
record.save();
|
record.save();
|
||||||
|
@ -152,7 +152,7 @@ public class SessionCipherV2 extends SessionCipher {
|
|||||||
RootKey rootKey = sessionState.getRootKey();
|
RootKey rootKey = sessionState.getRootKey();
|
||||||
ECKeyPair ourEphemeral = sessionState.getSenderEphemeralPair();
|
ECKeyPair ourEphemeral = sessionState.getSenderEphemeralPair();
|
||||||
Pair<RootKey, ChainKey> receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral);
|
Pair<RootKey, ChainKey> receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral);
|
||||||
ECKeyPair ourNewEphemeral = Curve.generateKeyPairForType(Curve.DJB_TYPE);
|
ECKeyPair ourNewEphemeral = Curve.generateKeyPairForType(Curve.DJB_TYPE, true);
|
||||||
Pair<RootKey, ChainKey> senderChain = receiverChain.first.createChain(theirEphemeral, ourNewEphemeral);
|
Pair<RootKey, ChainKey> senderChain = receiverChain.first.createChain(theirEphemeral, ourNewEphemeral);
|
||||||
|
|
||||||
sessionState.setRootKey(senderChain.first);
|
sessionState.setRootKey(senderChain.first);
|
||||||
|
@ -25,9 +25,9 @@ public class Curve {
|
|||||||
private static final int NIST_TYPE2 = 0x03;
|
private static final int NIST_TYPE2 = 0x03;
|
||||||
public static final int DJB_TYPE = 0x05;
|
public static final int DJB_TYPE = 0x05;
|
||||||
|
|
||||||
public static ECKeyPair generateKeyPairForType(int keyType) {
|
public static ECKeyPair generateKeyPairForType(int keyType, boolean ephemeral) {
|
||||||
if (keyType == DJB_TYPE) {
|
if (keyType == DJB_TYPE) {
|
||||||
return Curve25519.generateKeyPair();
|
return Curve25519.generateKeyPair(ephemeral);
|
||||||
} else if (keyType == NIST_TYPE || keyType == NIST_TYPE2) {
|
} else if (keyType == NIST_TYPE || keyType == NIST_TYPE2) {
|
||||||
return CurveP256.generateKeyPair();
|
return CurveP256.generateKeyPair();
|
||||||
} else {
|
} else {
|
||||||
@ -35,11 +35,11 @@ public class Curve {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ECKeyPair generateKeyPairForSession(int messageVersion) {
|
public static ECKeyPair generateKeyPairForSession(int messageVersion, boolean ephemeral) {
|
||||||
if (messageVersion <= CiphertextMessage.LEGACY_VERSION) {
|
if (messageVersion <= CiphertextMessage.LEGACY_VERSION) {
|
||||||
return generateKeyPairForType(NIST_TYPE);
|
return generateKeyPairForType(NIST_TYPE, ephemeral);
|
||||||
} else {
|
} else {
|
||||||
return generateKeyPairForType(DJB_TYPE);
|
return generateKeyPairForType(DJB_TYPE, ephemeral);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,10 +37,10 @@ public class Curve25519 {
|
|||||||
|
|
||||||
private static native byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic);
|
private static native byte[] calculateAgreement(byte[] ourPrivate, byte[] theirPublic);
|
||||||
private static native byte[] generatePublicKey(byte[] privateKey);
|
private static native byte[] generatePublicKey(byte[] privateKey);
|
||||||
private static native byte[] generatePrivateKey(byte[] random);
|
private static native byte[] generatePrivateKey(byte[] random, boolean ephemeral);
|
||||||
|
|
||||||
public static ECKeyPair generateKeyPair() {
|
public static ECKeyPair generateKeyPair(boolean ephemeral) {
|
||||||
byte[] privateKey = generatePrivateKey();
|
byte[] privateKey = generatePrivateKey(ephemeral);
|
||||||
byte[] publicKey = generatePublicKey(privateKey);
|
byte[] publicKey = generatePublicKey(privateKey);
|
||||||
|
|
||||||
return new ECKeyPair(new DjbECPublicKey(publicKey), new DjbECPrivateKey(privateKey));
|
return new ECKeyPair(new DjbECPublicKey(publicKey), new DjbECPrivateKey(privateKey));
|
||||||
@ -65,11 +65,11 @@ public class Curve25519 {
|
|||||||
return new DjbECPublicKey(keyBytes);
|
return new DjbECPublicKey(keyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] generatePrivateKey() {
|
private static byte[] generatePrivateKey(boolean ephemeral) {
|
||||||
byte[] privateKey = new byte[32];
|
byte[] privateKey = new byte[32];
|
||||||
random.nextBytes(privateKey);
|
random.nextBytes(privateKey);
|
||||||
|
|
||||||
return generatePrivateKey(privateKey);
|
return generatePrivateKey(privateKey, ephemeral);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ public class RatchetingSession {
|
|||||||
sessionState.setRemoteIdentityKey(theirIdentityKey);
|
sessionState.setRemoteIdentityKey(theirIdentityKey);
|
||||||
sessionState.setLocalIdentityKey(ourIdentityKey.getPublicKey());
|
sessionState.setLocalIdentityKey(ourIdentityKey.getPublicKey());
|
||||||
|
|
||||||
ECKeyPair sendingKey = Curve.generateKeyPairForType(ourIdentityKey.getPublicKey().getPublicKey().getType());
|
ECKeyPair sendingKey = Curve.generateKeyPairForType(ourIdentityKey.getPublicKey().getPublicKey().getType(), true);
|
||||||
Pair<RootKey, ChainKey> receivingChain = calculate3DHE(true, ourBaseKey, theirBaseKey, ourIdentityKey, theirIdentityKey);
|
Pair<RootKey, ChainKey> receivingChain = calculate3DHE(true, ourBaseKey, theirBaseKey, ourIdentityKey, theirIdentityKey);
|
||||||
Pair<RootKey, ChainKey> sendingChain = receivingChain.first.createChain(theirEphemeralKey, sendingKey);
|
Pair<RootKey, ChainKey> sendingChain = receivingChain.first.createChain(theirEphemeralKey, sendingKey);
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ public class LocalKeyRecord extends Record {
|
|||||||
|
|
||||||
this.localCurrentKeyPair = this.localNextKeyPair;
|
this.localCurrentKeyPair = this.localNextKeyPair;
|
||||||
this.localNextKeyPair = new KeyPair((this.localNextKeyPair.getId()+1) % Medium.MAX_VALUE,
|
this.localNextKeyPair = new KeyPair((this.localNextKeyPair.getId()+1) % Medium.MAX_VALUE,
|
||||||
Curve.generateKeyPairForType(keyType),
|
Curve.generateKeyPairForType(keyType, true),
|
||||||
masterSecret);
|
masterSecret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ public class AsymmetricMasterCipher {
|
|||||||
theirPublic = asymmetricMasterSecret.getNistPublicKey();
|
theirPublic = asymmetricMasterSecret.getNistPublicKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
ECKeyPair ourKeyPair = Curve.generateKeyPairForType(theirPublic.getType());
|
ECKeyPair ourKeyPair = Curve.generateKeyPairForType(theirPublic.getType(), true);
|
||||||
byte[] secret = Curve.calculateAgreement(theirPublic, ourKeyPair.getPrivateKey());
|
byte[] secret = Curve.calculateAgreement(theirPublic, ourKeyPair.getPrivateKey());
|
||||||
MasterCipher masterCipher = getMasterCipherForSecret(secret);
|
MasterCipher masterCipher = getMasterCipherForSecret(secret);
|
||||||
byte[] encryptedBodyBytes = masterCipher.encryptBytes(body.getBytes());
|
byte[] encryptedBodyBytes = masterCipher.encryptBytes(body.getBytes());
|
||||||
|
@ -135,8 +135,8 @@ public class IdentityKeyUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void generateIdentityKeys(Context context, MasterSecret masterSecret) {
|
public static void generateIdentityKeys(Context context, MasterSecret masterSecret) {
|
||||||
ECKeyPair nistKeyPair = Curve.generateKeyPairForType(Curve.NIST_TYPE);
|
ECKeyPair nistKeyPair = Curve.generateKeyPairForType(Curve.NIST_TYPE, false);
|
||||||
ECKeyPair djbKeyPair = Curve.generateKeyPairForType(Curve.DJB_TYPE);
|
ECKeyPair djbKeyPair = Curve.generateKeyPairForType(Curve.DJB_TYPE, false);
|
||||||
|
|
||||||
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
||||||
IdentityKey nistIdentityKey = new IdentityKey(nistKeyPair.getPublicKey());
|
IdentityKey nistIdentityKey = new IdentityKey(nistKeyPair.getPublicKey());
|
||||||
@ -160,7 +160,7 @@ public class IdentityKeyUtil {
|
|||||||
|
|
||||||
public static void generateCurve25519IdentityKeys(Context context, MasterSecret masterSecret) {
|
public static void generateCurve25519IdentityKeys(Context context, MasterSecret masterSecret) {
|
||||||
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
||||||
ECKeyPair djbKeyPair = Curve.generateKeyPairForType(Curve.DJB_TYPE);
|
ECKeyPair djbKeyPair = Curve.generateKeyPairForType(Curve.DJB_TYPE, false);
|
||||||
IdentityKey djbIdentityKey = new IdentityKey(djbKeyPair.getPublicKey());
|
IdentityKey djbIdentityKey = new IdentityKey(djbKeyPair.getPublicKey());
|
||||||
byte[] djbPrivateKey = masterCipher.encryptKey(djbKeyPair.getPrivateKey());
|
byte[] djbPrivateKey = masterCipher.encryptKey(djbKeyPair.getPrivateKey());
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ public class KeyExchangeInitiator {
|
|||||||
private static void initiateKeyExchange(Context context, MasterSecret masterSecret, Recipient recipient) {
|
private static void initiateKeyExchange(Context context, MasterSecret masterSecret, Recipient recipient) {
|
||||||
int sequence = getRandomSequence();
|
int sequence = getRandomSequence();
|
||||||
int flags = KeyExchangeMessageV2.INITIATE_FLAG;
|
int flags = KeyExchangeMessageV2.INITIATE_FLAG;
|
||||||
ECKeyPair baseKey = Curve.generateKeyPairForSession(CiphertextMessage.CURRENT_VERSION);
|
ECKeyPair baseKey = Curve.generateKeyPairForSession(CiphertextMessage.CURRENT_VERSION, true);
|
||||||
ECKeyPair ephemeralKey = Curve.generateKeyPairForSession(CiphertextMessage.CURRENT_VERSION);
|
ECKeyPair ephemeralKey = Curve.generateKeyPairForSession(CiphertextMessage.CURRENT_VERSION, true);
|
||||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret, Curve.DJB_TYPE);
|
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret, Curve.DJB_TYPE);
|
||||||
|
|
||||||
KeyExchangeMessageV2 message = new KeyExchangeMessageV2(sequence, flags,
|
KeyExchangeMessageV2 message = new KeyExchangeMessageV2(sequence, flags,
|
||||||
|
@ -136,8 +136,8 @@ public class KeyExchangeProcessorV1 extends KeyExchangeProcessor {
|
|||||||
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
|
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
|
||||||
int initialId = secureRandom.nextInt(4094) + 1;
|
int initialId = secureRandom.nextInt(4094) + 1;
|
||||||
|
|
||||||
KeyPair currentPair = new KeyPair(initialId, Curve.generateKeyPairForSession(1), masterSecret);
|
KeyPair currentPair = new KeyPair(initialId, Curve.generateKeyPairForSession(1, true), masterSecret);
|
||||||
KeyPair nextPair = new KeyPair(initialId + 1, Curve.generateKeyPairForSession(1), masterSecret);
|
KeyPair nextPair = new KeyPair(initialId + 1, Curve.generateKeyPairForSession(1, true), masterSecret);
|
||||||
LocalKeyRecord record = new LocalKeyRecord(context, masterSecret, recipient);
|
LocalKeyRecord record = new LocalKeyRecord(context, masterSecret, recipient);
|
||||||
|
|
||||||
record.setCurrentKeyPair(currentPair);
|
record.setCurrentKeyPair(currentPair);
|
||||||
|
@ -131,8 +131,8 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
|||||||
public void processKeyExchangeMessage(PreKeyEntity message, long threadId)
|
public void processKeyExchangeMessage(PreKeyEntity message, long threadId)
|
||||||
throws InvalidKeyException
|
throws InvalidKeyException
|
||||||
{
|
{
|
||||||
ECKeyPair ourBaseKey = Curve.generateKeyPairForSession(2);
|
ECKeyPair ourBaseKey = Curve.generateKeyPairForSession(2, true);
|
||||||
ECKeyPair ourEphemeralKey = Curve.generateKeyPairForSession(2);
|
ECKeyPair ourEphemeralKey = Curve.generateKeyPairForSession(2, true);
|
||||||
ECPublicKey theirBaseKey = message.getPublicKey();
|
ECPublicKey theirBaseKey = message.getPublicKey();
|
||||||
ECPublicKey theirEphemeralKey = theirBaseKey;
|
ECPublicKey theirEphemeralKey = theirBaseKey;
|
||||||
IdentityKey theirIdentityKey = message.getIdentityKey();
|
IdentityKey theirIdentityKey = message.getIdentityKey();
|
||||||
@ -184,8 +184,8 @@ public class KeyExchangeProcessorV2 extends KeyExchangeProcessor {
|
|||||||
|
|
||||||
if (!sessionRecord.getSessionState().hasPendingKeyExchange()) {
|
if (!sessionRecord.getSessionState().hasPendingKeyExchange()) {
|
||||||
Log.w("KeyExchangeProcessorV2", "We don't have a pending initiate...");
|
Log.w("KeyExchangeProcessorV2", "We don't have a pending initiate...");
|
||||||
ourBaseKey = Curve.generateKeyPairForType(message.getBaseKey().getType());
|
ourBaseKey = Curve.generateKeyPairForType(message.getBaseKey().getType(), true);
|
||||||
ourEphemeralKey = Curve.generateKeyPairForType(message.getBaseKey().getType());
|
ourEphemeralKey = Curve.generateKeyPairForType(message.getBaseKey().getType(), true);
|
||||||
ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret, message.getBaseKey().getType());
|
ourIdentityKey = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret, message.getBaseKey().getType());
|
||||||
|
|
||||||
sessionRecord.getSessionState().setPendingKeyExchange(message.getSequence(), ourBaseKey,
|
sessionRecord.getSessionState().setPendingKeyExchange(message.getSequence(), ourBaseKey,
|
||||||
|
@ -160,7 +160,7 @@ public class MasterSecretUtil {
|
|||||||
MasterSecret masterSecret)
|
MasterSecret masterSecret)
|
||||||
{
|
{
|
||||||
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
||||||
ECKeyPair keyPair = Curve.generateKeyPairForType(Curve.DJB_TYPE);
|
ECKeyPair keyPair = Curve.generateKeyPairForType(Curve.DJB_TYPE, true);
|
||||||
|
|
||||||
save(context, ASYMMETRIC_LOCAL_PUBLIC_DJB, keyPair.getPublicKey().serialize());
|
save(context, ASYMMETRIC_LOCAL_PUBLIC_DJB, keyPair.getPublicKey().serialize());
|
||||||
save(context, ASYMMETRIC_LOCAL_PRIVATE_DJB, masterCipher.encryptKey(keyPair.getPrivateKey()));
|
save(context, ASYMMETRIC_LOCAL_PRIVATE_DJB, masterCipher.encryptKey(keyPair.getPrivateKey()));
|
||||||
|
Loading…
Reference in New Issue
Block a user