package im.actor.core.modules.encryption.entity;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import im.actor.core.util.RandomUtils;
import im.actor.runtime.bser.BserObject;
import im.actor.runtime.bser.BserValues;
import im.actor.runtime.bser.BserWriter;
public class PrivateKeyStorage extends BserObject {
private int keyGroupId;
private PrivateKey identityKey = null;
private PrivateKey[] keys;
private PrivateKey[] preKeys;
private boolean wasRegenerated = false;
public PrivateKeyStorage(int keyGroupId, PrivateKey identityKey, PrivateKey[] keys, PrivateKey[] preKeys) {
this.keyGroupId = keyGroupId;
this.identityKey = identityKey;
this.keys = keys;
this.preKeys = preKeys;
}
public PrivateKeyStorage(byte[] data) throws IOException {
load(data);
}
public int getKeyGroupId() {
return keyGroupId;
}
public PrivateKey getIdentityKey() {
return identityKey;
}
public PrivateKey[] getKeys() {
return keys;
}
public PrivateKeyStorage setGroupId(int groupId) {
return new PrivateKeyStorage(groupId, identityKey, keys, preKeys);
}
public PrivateKeyStorage appendPreKeys(PrivateKey[] addedPreKeys) {
PrivateKey[] nKeys = new PrivateKey[
addedPreKeys.length + preKeys.length];
System.arraycopy(preKeys, 0, nKeys, 0, preKeys.length);
System.arraycopy(addedPreKeys, 0, nKeys, preKeys.length, addedPreKeys.length);
return new PrivateKeyStorage(keyGroupId, identityKey, keys, nKeys);
}
public PrivateKeyStorage markAsUploaded(PrivateKey[] uploadedPreKeys) {
PrivateKey[] nKeys = new PrivateKey[preKeys.length];
for (int i = 0; i < preKeys.length; i++) {
boolean found = false;
for (int j = 0; j < uploadedPreKeys.length; j++) {
if (uploadedPreKeys[j].getKeyId() == preKeys[i].getKeyId()) {
found = true;
break;
}
}
if (found) {
nKeys[i] = preKeys[i].markAsUploaded();
} else {
nKeys[i] = preKeys[i];
}
}
return new PrivateKeyStorage(keyGroupId, identityKey, keys, nKeys);
}
public PrivateKey[] getPreKeys() {
return preKeys;
}
public PrivateKey pickRandomPreKey() {
ArrayList<PrivateKey> uploadedKeys = new ArrayList<PrivateKey>();
for (PrivateKey u : preKeys) {
if (u.isUploaded()) {
uploadedKeys.add(u);
}
}
return uploadedKeys.get(RandomUtils.randomId(uploadedKeys.size()));
}
public boolean isWasRegenerated() {
return wasRegenerated;
}
@Override
public void parse(BserValues values) throws IOException {
keyGroupId = values.getInt(1);
identityKey = new PrivateKey(values.getBytes(2));
wasRegenerated |= identityKey.isWasRegenerated();
List<byte[]> r = values.getRepeatedBytes(3);
keys = new PrivateKey[r.size()];
for (int i = 0; i < keys.length; i++) {
keys[i] = new PrivateKey(r.get(i));
wasRegenerated |= keys[i].isWasRegenerated();
}
r = values.getRepeatedBytes(4);
preKeys = new PrivateKey[r.size()];
for (int i = 0; i < preKeys.length; i++) {
preKeys[i] = new PrivateKey(r.get(i));
wasRegenerated |= preKeys[i].isWasRegenerated();
}
}
@Override
public void serialize(BserWriter writer) throws IOException {
writer.writeInt(1, keyGroupId);
writer.writeBytes(2, identityKey.toByteArray());
for (PrivateKey k : keys) {
writer.writeBytes(3, k.toByteArray());
}
for (PrivateKey k : preKeys) {
writer.writeBytes(4, k.toByteArray());
}
}
}