2013-02-04 08:13:07 +00:00
|
|
|
/**
|
2011-12-20 18:20:44 +00:00
|
|
|
* Copyright (C) 2011 Whisper Systems
|
2013-02-04 08:13:07 +00:00
|
|
|
*
|
2011-12-20 18:20:44 +00:00
|
|
|
* 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.
|
2013-02-04 08:13:07 +00:00
|
|
|
*
|
2011-12-20 18:20:44 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2014-11-03 23:16:04 +00:00
|
|
|
package org.thoughtcrime.securesms.crypto;
|
2011-12-20 18:20:44 +00:00
|
|
|
|
2013-02-04 08:13:07 +00:00
|
|
|
import android.os.Parcel;
|
|
|
|
import android.os.Parcelable;
|
2011-12-20 18:20:44 +00:00
|
|
|
|
2013-02-04 08:13:07 +00:00
|
|
|
import javax.crypto.spec.SecretKeySpec;
|
2013-08-18 01:37:18 +00:00
|
|
|
import java.util.Arrays;
|
2011-12-20 18:20:44 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* When a user first initializes TextSecure, a few secrets
|
|
|
|
* are generated. These are:
|
2013-02-04 08:13:07 +00:00
|
|
|
*
|
2011-12-20 18:20:44 +00:00
|
|
|
* 1) A 128bit symmetric encryption key.
|
|
|
|
* 2) A 160bit symmetric MAC key.
|
|
|
|
* 3) An ECC keypair.
|
2013-02-04 08:13:07 +00:00
|
|
|
*
|
2011-12-20 18:20:44 +00:00
|
|
|
* The first two, along with the ECC keypair's private key, are
|
|
|
|
* then encrypted on disk using PBE.
|
2013-02-04 08:13:07 +00:00
|
|
|
*
|
2011-12-20 18:20:44 +00:00
|
|
|
* This class represents 1 and 2.
|
2013-02-04 08:13:07 +00:00
|
|
|
*
|
2011-12-20 18:20:44 +00:00
|
|
|
* @author Moxie Marlinspike
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class MasterSecret implements Parcelable {
|
2013-02-04 08:13:07 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
private final SecretKeySpec encryptionKey;
|
|
|
|
private final SecretKeySpec macKey;
|
|
|
|
|
|
|
|
public static final Parcelable.Creator<MasterSecret> CREATOR = new Parcelable.Creator<MasterSecret>() {
|
2013-02-04 08:13:07 +00:00
|
|
|
@Override
|
2011-12-20 18:20:44 +00:00
|
|
|
public MasterSecret createFromParcel(Parcel in) {
|
|
|
|
return new MasterSecret(in);
|
|
|
|
}
|
|
|
|
|
2013-02-04 08:13:07 +00:00
|
|
|
@Override
|
2011-12-20 18:20:44 +00:00
|
|
|
public MasterSecret[] newArray(int size) {
|
|
|
|
return new MasterSecret[size];
|
|
|
|
}
|
|
|
|
};
|
2013-02-04 08:13:07 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public MasterSecret(SecretKeySpec encryptionKey, SecretKeySpec macKey) {
|
|
|
|
this.encryptionKey = encryptionKey;
|
|
|
|
this.macKey = macKey;
|
|
|
|
}
|
2013-02-04 08:13:07 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
private MasterSecret(Parcel in) {
|
|
|
|
byte[] encryptionKeyBytes = new byte[in.readInt()];
|
|
|
|
in.readByteArray(encryptionKeyBytes);
|
|
|
|
|
|
|
|
byte[] macKeyBytes = new byte[in.readInt()];
|
|
|
|
in.readByteArray(macKeyBytes);
|
2013-02-04 08:13:07 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
this.encryptionKey = new SecretKeySpec(encryptionKeyBytes, "AES");
|
|
|
|
this.macKey = new SecretKeySpec(macKeyBytes, "HmacSHA1");
|
2013-02-04 08:13:07 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
// SecretKeySpec does an internal copy in its constructor.
|
2013-08-18 01:37:18 +00:00
|
|
|
Arrays.fill(encryptionKeyBytes, (byte) 0x00);
|
2011-12-20 18:20:44 +00:00
|
|
|
Arrays.fill(macKeyBytes, (byte)0x00);
|
|
|
|
}
|
|
|
|
|
2013-02-04 08:13:07 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public SecretKeySpec getEncryptionKey() {
|
|
|
|
return this.encryptionKey;
|
|
|
|
}
|
2013-02-04 08:13:07 +00:00
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
public SecretKeySpec getMacKey() {
|
|
|
|
return this.macKey;
|
|
|
|
}
|
2013-02-04 08:13:07 +00:00
|
|
|
|
|
|
|
@Override
|
2011-12-20 18:20:44 +00:00
|
|
|
public void writeToParcel(Parcel out, int flags) {
|
|
|
|
out.writeInt(encryptionKey.getEncoded().length);
|
|
|
|
out.writeByteArray(encryptionKey.getEncoded());
|
|
|
|
out.writeInt(macKey.getEncoded().length);
|
|
|
|
out.writeByteArray(macKey.getEncoded());
|
|
|
|
}
|
2013-02-04 08:13:07 +00:00
|
|
|
|
|
|
|
@Override
|
2011-12-20 18:20:44 +00:00
|
|
|
public int describeContents() {
|
|
|
|
return 0;
|
|
|
|
}
|
2013-02-04 08:13:07 +00:00
|
|
|
|
|
|
|
public MasterSecret parcelClone() {
|
|
|
|
Parcel thisParcel = Parcel.obtain();
|
|
|
|
Parcel thatParcel = Parcel.obtain();
|
|
|
|
byte[] bytes = null;
|
|
|
|
|
|
|
|
thisParcel.writeValue(this);
|
|
|
|
bytes = thisParcel.marshall();
|
|
|
|
|
|
|
|
thatParcel.unmarshall(bytes, 0, bytes.length);
|
|
|
|
thatParcel.setDataPosition(0);
|
|
|
|
|
|
|
|
MasterSecret that = (MasterSecret)thatParcel.readValue(MasterSecret.class.getClassLoader());
|
|
|
|
|
|
|
|
thisParcel.recycle();
|
|
|
|
thatParcel.recycle();
|
|
|
|
|
|
|
|
return that;
|
|
|
|
}
|
|
|
|
|
2011-12-20 18:20:44 +00:00
|
|
|
}
|