### Question:
PasetoPublic { static String sign(byte[] privateKey, String payload, String footer) { Preconditions.checkNotNull(privateKey); Preconditions.checkNotNull(payload); Preconditions.checkArgument(privateKey.length == 64, "Private signing key should be 64 bytes"); byte[] m2 = BaseEncoding.base16().lowerCase().decode(Util.pae(PUBLIC, payload, footer)); byte[] signature = new byte[64]; CryptoCavaWrapper.cryptoSignDetached(signature, m2, privateKey); String signedToken = PUBLIC + getUrlEncoder().withoutPadding().encodeToString(Bytes.concat(payload.getBytes(UTF_8), signature)); if (!Strings.isNullOrEmpty(footer)) { signedToken = signedToken + "." + getUrlEncoder().withoutPadding().encodeToString(footer.getBytes(UTF_8)); } return signedToken; } private  PasetoPublic();   }### Answer:
@Test public void signTokenWithSeed() { byte[] seed = Util.hexToBytes("b4cbfb43df4ce210727d953e4a713307fa19bb7d9f85041438d9e11b942a3774"); byte[] privateKey = new byte[64]; byte[] publicKey = new byte[64]; CryptoCavaWrapper.cryptoSignEd25519SeedKeypair(seed, publicKey, privateKey); String token = PasetoPublic.sign( privateKey, "{\"data\":\"this is a signed message\",\"expires\":\"2019-01-01T00:00:00+00:00\"}", "Paragon Initiative Enterprises"); assertEquals("v2.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIiwiZXhwaXJlcyI6IjIwMTktMDEtMDFUMDA6MDA6MDArMDA6MDAifcMYjoUaEYXAtzTDwlcOlxdcZWIZp8qZga3jFS8JwdEjEvurZhs6AmTU3bRW5pB9fOQwm43rzmibZXcAkQ4AzQs.UGFyYWdvbiBJbml0aWF0aXZlIEVudGVycHJpc2Vz", token); }