Files
Android/library/src/org/whispersystems/textsecure/crypto/protocol/PreKeyBundleMessage.java
Moxie Marlinspike c38a8aa699 Migrate to Curve25519.
1) Generate a Curve25519 identity key.

2) Use Curve25519 ephemerals and identities for v2 3DHE agreements.

3) Initiate v2 key exchange messages.

4) Accept v1 key exchange messages.

5) TOFU Curve25519 identities.
2014-01-06 14:36:22 -08:00

109 lines
4.2 KiB
Java

/**
* Copyright (C) 2013 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.crypto.protocol;
import org.whispersystems.textsecure.crypto.IdentityKey;
import org.whispersystems.textsecure.crypto.InvalidKeyException;
import org.whispersystems.textsecure.crypto.InvalidMessageException;
import org.whispersystems.textsecure.crypto.InvalidVersionException;
import org.whispersystems.textsecure.crypto.PublicKey;
import org.whispersystems.textsecure.util.Conversions;
/**
* Class responsible for parsing and constructing PreKeyBundle messages.
*
* The class takes an existing encrypted message and bundles in the necessary
* additional information for a prekeybundle, namely the addition of the local
* identity key.
*/
public class PreKeyBundleMessage {
public static final int SUPPORTED_VERSION = CiphertextMessage.SUPPORTED_VERSION;
private static final int VERSION_LENGTH = CiphertextMessage.VERSION_LENGTH;
private static final int IDENTITY_KEY_LENGTH = IdentityKey.SIZE;
private static final int VERSION_OFFSET = CiphertextMessage.VERSION_OFFSET;
private static final int IDENTITY_KEY_OFFSET = VERSION_OFFSET + VERSION_LENGTH;
private final byte[] messageBytes;
private final CiphertextMessage bundledMessage;
private final IdentityKey identityKey;
public PreKeyBundleMessage(byte[] messageBytes)
throws InvalidVersionException, InvalidKeyException
{
try {
this.messageBytes = messageBytes;
int messageVersion = Conversions.highBitsToInt(this.messageBytes[VERSION_OFFSET]);
if (messageVersion > CiphertextMessage.SUPPORTED_VERSION)
throw new InvalidVersionException("Key exchange with version: " + messageVersion);
this.identityKey = new IdentityKey(messageBytes, IDENTITY_KEY_OFFSET);
byte[] bundledMessageBytes = new byte[messageBytes.length - IDENTITY_KEY_LENGTH];
bundledMessageBytes[VERSION_OFFSET] = this.messageBytes[VERSION_OFFSET];
System.arraycopy(messageBytes, IDENTITY_KEY_OFFSET+IDENTITY_KEY_LENGTH, bundledMessageBytes,
VERSION_OFFSET+VERSION_LENGTH, bundledMessageBytes.length-VERSION_LENGTH);
this.bundledMessage = new CiphertextMessage(bundledMessageBytes);
} catch (InvalidMessageException e) {
throw new InvalidKeyException(e);
}
}
public PreKeyBundleMessage(CiphertextMessage bundledMessage, IdentityKey identityKey) {
this.bundledMessage = bundledMessage;
this.identityKey = identityKey;
this.messageBytes = new byte[IDENTITY_KEY_LENGTH + bundledMessage.serialize().length];
byte[] bundledMessageBytes = bundledMessage.serialize();
byte[] identityKeyBytes = identityKey.serialize();
messageBytes[VERSION_OFFSET] = bundledMessageBytes[VERSION_OFFSET];
System.arraycopy(identityKeyBytes, 0, messageBytes, IDENTITY_KEY_OFFSET, identityKeyBytes.length);
System.arraycopy(bundledMessageBytes, VERSION_OFFSET+VERSION_LENGTH,
messageBytes, IDENTITY_KEY_OFFSET+IDENTITY_KEY_LENGTH,
bundledMessageBytes.length-VERSION_LENGTH);
}
public byte[] serialize() {
return this.messageBytes;
}
public int getSupportedVersion() {
return bundledMessage.getSupportedVersion();
}
public IdentityKey getIdentityKey() {
return identityKey;
}
public PublicKey getPublicKey() throws InvalidKeyException {
return new PublicKey(bundledMessage.getNextKeyBytes());
}
public CiphertextMessage getBundledMessage() {
return bundledMessage;
}
public int getPreKeyId() {
return bundledMessage.getReceiverKeyId();
}
}