package peergos.server.tests; import org.junit.*; import peergos.server.corenode.SQLiteCoreNode; import peergos.shared.corenode.CoreNode; import peergos.shared.corenode.UserPublicKeyLink; import peergos.shared.crypto.*; import peergos.shared.crypto.asymmetric.*; import peergos.shared.crypto.asymmetric.curve25519.*; import peergos.shared.crypto.random.*; import java.sql.SQLException; import java.time.LocalDate; import java.util.*; import java.util.concurrent.*; public class UserPublicKeyLinkTests { @BeforeClass public static void init() throws Exception { PublicSigningKey.addProvider(PublicSigningKey.Type.Ed25519, new Ed25519.Java()); // use insecure random otherwise tests take ages UserTests.setFinalStatic(TweetNaCl.class.getDeclaredField("prng"), new Random(1)); } @Test public void createInitial() { SigningKeyPair user = SigningKeyPair.random(new SafeRandom.Java(), new Ed25519.Java()); UserPublicKeyLink.UsernameClaim node = UserPublicKeyLink.UsernameClaim.create("someuser", user, LocalDate.now().plusYears(2)); UserPublicKeyLink upl = new UserPublicKeyLink(user.publicSigningKey, node); testSerialization(upl); } public void testSerialization(UserPublicKeyLink link) { byte[] serialized1 = link.toByteArray(); UserPublicKeyLink upl2 = UserPublicKeyLink.fromByteArray(link.owner, serialized1); byte[] serialized2 = upl2.toByteArray(); if (!Arrays.equals(serialized1, serialized2)) throw new IllegalStateException("toByteArray not inverse of fromByteArray!"); } @Test public void createChain() { SigningKeyPair oldUser = SigningKeyPair.random(new SafeRandom.Java(), new Ed25519.Java()); SigningKeyPair newUser = SigningKeyPair.random(new SafeRandom.Java(), new Ed25519.Java()); List<UserPublicKeyLink> links = UserPublicKeyLink.createChain(oldUser, newUser, "someuser", LocalDate.now().plusYears(2)); links.forEach(link -> testSerialization(link)); } @Test public void coreNode() throws Exception { CoreNode core = getDefaultCoreNode(); SigningKeyPair user = SigningKeyPair.insecureRandom(); String username = "someuser"; // register the username UserPublicKeyLink.UsernameClaim node = UserPublicKeyLink.UsernameClaim.create(username, user, LocalDate.now().plusYears(2)); UserPublicKeyLink upl = new UserPublicKeyLink(user.publicSigningKey, node); boolean success = core.updateChain(username, Arrays.asList(upl)).get(); List<UserPublicKeyLink> chain = core.getChain(username).get(); if (chain.size() != 1 || !chain.get(0).equals(upl)) throw new IllegalStateException("Retrieved chain element different "+chain +" != "+Arrays.asList(upl)); // now change the expiry UserPublicKeyLink.UsernameClaim node2 = UserPublicKeyLink.UsernameClaim.create(username, user, LocalDate.now().plusYears(3)); UserPublicKeyLink upl2 = new UserPublicKeyLink(user.publicSigningKey, node2); boolean success2 = core.updateChain(username, Arrays.asList(upl2)).get(); List<UserPublicKeyLink> chain2 = core.getChain(username).get(); if (chain2.size() != 1 || !chain2.get(0).equals(upl2)) throw new IllegalStateException("Retrieved chain element different "+chain2 +" != "+Arrays.asList(upl2)); // now change the keys SigningKeyPair user2 = SigningKeyPair.insecureRandom(); List<UserPublicKeyLink> chain3 = UserPublicKeyLink.createChain(user, user2, username, LocalDate.now().plusWeeks(1)); boolean success3 = core.updateChain(username, chain3).get(); List<UserPublicKeyLink> chain3Retrieved = core.getChain(username).get(); if (!chain3.equals(chain3Retrieved)) throw new IllegalStateException("Retrieved chain element different"); // update the expiry at the end of the chain UserPublicKeyLink.UsernameClaim node4 = UserPublicKeyLink.UsernameClaim.create(username, user2, LocalDate.now().plusWeeks(2)); UserPublicKeyLink upl4 = new UserPublicKeyLink(user2.publicSigningKey, node4); List<UserPublicKeyLink> chain4 = Arrays.asList(upl4); boolean success4 = core.updateChain(username, chain4).get(); List<UserPublicKeyLink> chain4Retrieved = core.getChain(username).get(); if (!chain4.equals(Arrays.asList(chain4Retrieved.get(chain4Retrieved.size()-1)))) throw new IllegalStateException("Retrieved chain element different after expiry update"); // check username lookup String uname = core.getUsername(user2.publicSigningKey).get(); if (!uname.equals(username)) throw new IllegalStateException("Returned username is different! "+uname + " != "+username); // try to claim the same username with a different key SigningKeyPair user3 = SigningKeyPair.insecureRandom(); UserPublicKeyLink.UsernameClaim node3 = UserPublicKeyLink.UsernameClaim.create(username, user3, LocalDate.now().plusYears(2)); UserPublicKeyLink upl3 = new UserPublicKeyLink(user3.publicSigningKey, node3); try { boolean shouldFail = core.updateChain(username, Arrays.asList(upl3)).get(); throw new RuntimeException("Should have failed before here!"); } catch (ExecutionException e) {} } static CoreNode getDefaultCoreNode() { try { return SQLiteCoreNode.build(":memory:"); } catch (SQLException s) { throw new IllegalStateException(s); } } }