package mobisocial.musubi.encoding;
import android.database.sqlite.SQLiteOpenHelper;
import mobisocial.crypto.IBEncryptionScheme;
import mobisocial.crypto.IBHashedIdentity.Authority;
import mobisocial.crypto.IBIdentity;
import mobisocial.crypto.IBSignatureScheme;
import mobisocial.musubi.identity.UnverifiedIdentityProvider;
import mobisocial.musubi.model.MEncodedMessage;
import mobisocial.musubi.model.MEncryptionUserKey;
import mobisocial.musubi.model.MIdentity;
import mobisocial.musubi.model.MSignatureUserKey;
import mobisocial.musubi.model.helpers.DatabaseFile;
import mobisocial.musubi.model.helpers.EncodedMessageManager;
import mobisocial.musubi.model.helpers.IdentitiesManager;
import mobisocial.musubi.model.helpers.MessageTransportManager;
import mobisocial.musubi.model.helpers.UserKeyManager;
import mobisocial.musubi.util.Util;
import mobisocial.test.TestBase;
public class PersistentEncodingTest extends TestBase {
IBEncryptionScheme encryptionScheme_ = new IBEncryptionScheme();
IBSignatureScheme signatureScheme_ = new IBSignatureScheme();
UnverifiedIdentityProvider idp_ = new UnverifiedIdentityProvider();
SQLiteOpenHelper dbh, dbh0, dbh1;
public void setUp() {
dbh = new DatabaseFile(getContext(), null);
dbh0 = new DatabaseFile(getContext(), null);
dbh1 = new DatabaseFile(getContext(), null);
}
public void tearDown() {
dbh.close();
dbh0.close();
dbh1.close();
}
public void testMissingSigningKeyMissingEncryptionKeyAndDuplicateMessage() throws Exception {
final IBIdentity me = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0);
long myDeviceName = r.nextLong();
IdentitiesManager idm = new IdentitiesManager(dbh);
MessageTransportManager mtm = new MessageTransportManager(dbh, idp_.getEncryptionScheme(),
idp_.getSignatureScheme(), myDeviceName);
MIdentity myid = mtm.addClaimedIdentity(me);
myid.owned_ = true;
myid.principal_ = me.principal_;
idm.updateIdentity(myid);
//encode a message
MessageEncoder encoder = new MessageEncoder(mtm);
OutgoingMessage om = new OutgoingMessage();
om.fromIdentity_ = myid;
om.recipients_ = new MIdentity[] { mtm.addClaimedIdentity(me) };
om.data_ = new byte[16];
r.nextBytes(om.data_);
om.app_ = new byte[32];
r.nextBytes(om.app_);
om.hash_ = Util.sha256(om.data_);
MEncodedMessage encodedOutgoing;
try {
encodedOutgoing = encoder.processMessage(om);
fail("should have required signing key");
} catch(NeedsKey.Signature e) {
// GOOD
UserKeyManager sm = new UserKeyManager(idp_.getEncryptionScheme(), idp_.getSignatureScheme(), dbh);
MSignatureUserKey sigKey = new MSignatureUserKey();
sigKey.identityId_ = myid.id_;
IBIdentity required_key = idm.getIBIdentityForIBHashedIdentity(e.identity_);
sigKey.userKey_ = idp_.syncGetSignatureKey(required_key).key_;
sigKey.when_ = required_key.temporalFrame_;
sm.insertSignatureUserKey(sigKey);
} catch (Exception e) {
throw e;
}
//second time it will try with the new key inserted which should work
try {
encodedOutgoing = encoder.processMessage(om);
} catch (Exception e) {
throw e;
}
EncodedMessageManager emm = new EncodedMessageManager(dbh);
long id0 = encodedOutgoing.id_;
//add a new dup
encodedOutgoing.fromDevice_ = null;
encodedOutgoing.fromIdentityId_ = null;
encodedOutgoing.hash_ = null;
encodedOutgoing.outbound_ = false;
encodedOutgoing.processed_ = false;
emm.insertEncoded(encodedOutgoing);
MessageDecoder decoder = new MessageDecoder(mtm);
//decode it
try {
decoder.processMessage(encodedOutgoing);
fail("this should have been detected as a duplicate");
} catch (DiscardMessage.Duplicate e) {
//GOOD!
} catch (Exception e) {
throw e;
}
emm.delete(id0);
emm.delete(encodedOutgoing.id_);
encodedOutgoing.fromDevice_ = null;
encodedOutgoing.fromIdentityId_ = null;
encodedOutgoing.hash_ = null;
encodedOutgoing.outbound_ = false;
encodedOutgoing.processed_ = false;
emm.updateEncodedMetadata(encodedOutgoing);
//decode it
try {
decoder.processMessage(encodedOutgoing);
fail("this should have required an encryption key");
} catch (NeedsKey.Encryption e) {
//GOOD!
UserKeyManager sm = new UserKeyManager(idp_.getEncryptionScheme(), idp_.getSignatureScheme(), dbh);
MEncryptionUserKey encKey = new MEncryptionUserKey();
encKey.identityId_ = myid.id_;
IBIdentity required_key = idm.getIBIdentityForIBHashedIdentity(e.identity_);
encKey.userKey_ = idp_.syncGetEncryptionKey(required_key).key_;
encKey.when_ = required_key.temporalFrame_;
sm.insertEncryptionUserKey(encKey);
} catch (Exception e) {
throw e;
}
encodedOutgoing.fromDevice_ = null;
encodedOutgoing.fromIdentityId_ = null;
encodedOutgoing.hash_ = null;
encodedOutgoing.outbound_ = false;
encodedOutgoing.processed_ = false;
emm.insertEncoded(encodedOutgoing);
//decode it again
try {
decoder.processMessage(encodedOutgoing);
} catch (DiscardMessage.Duplicate e) {
throw e;
} catch (Exception e) {
throw e;
}
}
public void testSendToDifferentDevice() throws Exception {
final IBIdentity me = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0);
long myDeviceName0 = r.nextLong();
IdentitiesManager idm0 = new IdentitiesManager(dbh0);
MessageTransportManager mtm0 = new MessageTransportManager(dbh0, idp_.getEncryptionScheme(),
idp_.getSignatureScheme(), myDeviceName0);
MIdentity myid0 = mtm0.addClaimedIdentity(me);
myid0.owned_ = true;
myid0.principal_ = me.principal_;
idm0.updateIdentity(myid0);
long myDeviceName1 = r.nextLong();
IdentitiesManager idm1 = new IdentitiesManager(dbh1);
MessageTransportManager mtm1 = new MessageTransportManager(dbh1, idp_.getEncryptionScheme(),
idp_.getSignatureScheme(), myDeviceName1);
MIdentity myid1 = mtm1.addClaimedIdentity(me);
myid1.owned_ = true;
myid1.principal_ = me.principal_;
idm1.updateIdentity(myid1);
//encode a message
MessageEncoder encoder = new MessageEncoder(mtm0);
OutgoingMessage om = new OutgoingMessage();
om.fromIdentity_ = myid0;
om.recipients_ = new MIdentity[] { mtm0.addClaimedIdentity(me) };
om.data_ = new byte[16];
r.nextBytes(om.data_);
om.app_ = new byte[32];
r.nextBytes(om.app_);
om.hash_ = Util.sha256(om.data_);
UserKeyManager sm0 = new UserKeyManager(idp_.getEncryptionScheme(), idp_.getSignatureScheme(), dbh0);
MSignatureUserKey sigKey = new MSignatureUserKey();
sigKey.identityId_ = myid0.id_;
IBIdentity required_key = me.at(mtm0.getSignatureTime(myid0));
sigKey.userKey_ = idp_.syncGetSignatureKey(required_key).key_;
sigKey.when_ = required_key.temporalFrame_;
sm0.insertSignatureUserKey(sigKey);
UserKeyManager sm1 = new UserKeyManager(idp_.getEncryptionScheme(), idp_.getSignatureScheme(), dbh1);
MEncryptionUserKey encKey = new MEncryptionUserKey();
encKey.identityId_ = myid1.id_;
required_key = me.at(mtm1.getEncryptionTime(myid1));
encKey.userKey_ = idp_.syncGetEncryptionKey(required_key).key_;
encKey.when_ = required_key.temporalFrame_;
sm1.insertEncryptionUserKey(encKey);
MEncodedMessage encodedOutgoing;
try {
encodedOutgoing = encoder.processMessage(om);
} catch (Exception e) {
throw e;
}
EncodedMessageManager emm1 = new EncodedMessageManager(dbh1);
MEncodedMessage encodedIncoming = new MEncodedMessage();
encodedIncoming.encoded_ = encodedOutgoing.encoded_;
emm1.insertEncoded(encodedIncoming);
//decode it
MessageDecoder decoder = new MessageDecoder(mtm1);
IncomingMessage im;
try {
im = decoder.processMessage(encodedIncoming);
} catch (Exception e) {
throw e;
}
assertMessagesEqual(om, im);
}
public void testSendToAFriend() throws Exception {
final IBIdentity me = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0);
long myDeviceName0 = r.nextLong();
IdentitiesManager idm0 = new IdentitiesManager(dbh0);
MessageTransportManager mtm0 = new MessageTransportManager(dbh0, idp_.getEncryptionScheme(),
idp_.getSignatureScheme(), myDeviceName0);
MIdentity myid0 = mtm0.addClaimedIdentity(me);
myid0.owned_ = true;
myid0.principal_ = me.principal_;
idm0.updateIdentity(myid0);
final IBIdentity you = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0);
long myDeviceName1 = r.nextLong();
IdentitiesManager idm1 = new IdentitiesManager(dbh1);
MessageTransportManager mtm1 = new MessageTransportManager(dbh1, idp_.getEncryptionScheme(),
idp_.getSignatureScheme(), myDeviceName1);
MIdentity myid1 = mtm1.addClaimedIdentity(you);
myid1.owned_ = true;
myid1.principal_ = you.principal_;
idm1.updateIdentity(myid1);
//encode a message
MessageEncoder encoder = new MessageEncoder(mtm0);
OutgoingMessage om = new OutgoingMessage();
om.fromIdentity_ = myid0;
om.recipients_ = new MIdentity[] { mtm0.addClaimedIdentity(you) };
om.data_ = new byte[16];
r.nextBytes(om.data_);
om.app_ = new byte[32];
r.nextBytes(om.app_);
om.hash_ = Util.sha256(om.data_);
UserKeyManager sm0 = new UserKeyManager(idp_.getEncryptionScheme(), idp_.getSignatureScheme(), dbh0);
MSignatureUserKey sigKey = new MSignatureUserKey();
sigKey.identityId_ = myid0.id_;
IBIdentity required_key = me.at(mtm0.getSignatureTime(myid0));
sigKey.userKey_ = idp_.syncGetSignatureKey(required_key).key_;
sigKey.when_ = required_key.temporalFrame_;
sm0.insertSignatureUserKey(sigKey);
UserKeyManager sm1 = new UserKeyManager(idp_.getEncryptionScheme(), idp_.getSignatureScheme(), dbh1);
MEncryptionUserKey encKey = new MEncryptionUserKey();
encKey.identityId_ = myid1.id_;
required_key = you.at(mtm1.getEncryptionTime(myid1));
encKey.userKey_ = idp_.syncGetEncryptionKey(required_key).key_;
encKey.when_ = required_key.temporalFrame_;
sm1.insertEncryptionUserKey(encKey);
MEncodedMessage encodedOutgoing;
try {
encodedOutgoing = encoder.processMessage(om);
} catch (Exception e) {
throw e;
}
EncodedMessageManager emm1 = new EncodedMessageManager(dbh1);
MEncodedMessage encodedIncoming = new MEncodedMessage();
encodedIncoming.encoded_ = encodedOutgoing.encoded_;
emm1.insertEncoded(encodedIncoming);
//decode it
MessageDecoder decoder = new MessageDecoder(mtm1);
IncomingMessage im;
try {
im = decoder.processMessage(encodedIncoming);
} catch (Exception e) {
throw e;
}
assertMessagesEqual(om, im);
}
}