diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd9fe3848..7dc51477d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
As this project is pre 1.0, breaking changes may happen for minor version bumps. A breaking change will get clearly notified in this log.
## 0.21.2
+- Update challenge transaction helpers for SEP-0010 v3.0.0. ([#308](https://github.com/stellar/java-stellar-sdk/pull/308))
- Fix the decoding of `balanceId` in `org.stellar.sdk.ClaimClaimableBalanceOperation`. ([#310](https://github.com/stellar/java-stellar-sdk/pull/310))
## 0.21.1
diff --git a/src/main/java/org/stellar/sdk/Sep10Challenge.java b/src/main/java/org/stellar/sdk/Sep10Challenge.java
index 11f182f27..1836b4ae7 100644
--- a/src/main/java/org/stellar/sdk/Sep10Challenge.java
+++ b/src/main/java/org/stellar/sdk/Sep10Challenge.java
@@ -19,7 +19,7 @@ public class Sep10Challenge {
* @param signer The server's signing account.
* @param network The Stellar network used by the server.
* @param clientAccountId The stellar account belonging to the client.
- * @param domainName The fully qualified domain name of the service requiring authentication (The domainName field is reserved for future use and not used).
+ * @param domainName The fully qualified domain name of the service requiring authentication.
* @param timebounds The lifetime of the challenge token.
*/
public static Transaction newChallenge(
@@ -64,17 +64,23 @@ public static Transaction newChallenge(
* that any signatures other than the servers on the transaction are valid. Use
* one of the following functions to completely verify the transaction:
* {@link Sep10Challenge#verifyChallengeTransactionSigners(String, String, Network, String, Set)} or
- * {@link Sep10Challenge#verifyChallengeTransactionThreshold(String, String, Network, String, int, Set)}
+ * {@link Sep10Challenge#verifyChallengeTransactionThreshold(String, String, Network, String, int, Set)} or
+ * {@link Sep10Challenge#verifyChallengeTransactionSigners(String, String, Network, String[], Set)} or
+ * {@link Sep10Challenge#verifyChallengeTransactionThreshold(String, String, Network, String[], int, Set)} or
*
* @param challengeXdr SEP-0010 transaction challenge transaction in base64.
* @param serverAccountId Account ID for server's account.
* @param network The network to connect to for verifying and retrieving.
- * @param domainName The fully qualified domain name of the service requiring authentication (The domainName field is reserved for future use and not used).
+ * @param domainNames An array of home domains, one of which is expected to be included in the first Manage Data operation's string key.
* @return {@link ChallengeTransaction}, the decoded transaction envelope and client account ID contained within.
* @throws InvalidSep10ChallengeException If the SEP-0010 validation fails, the exception will be thrown.
* @throws IOException If read XDR string fails, the exception will be thrown.
*/
- public static ChallengeTransaction readChallengeTransaction(String challengeXdr, String serverAccountId, Network network, String domainName) throws InvalidSep10ChallengeException, IOException {
+ public static ChallengeTransaction readChallengeTransaction(String challengeXdr, String serverAccountId, Network network, String[] domainNames) throws InvalidSep10ChallengeException, IOException {
+ if (domainNames == null || domainNames.length == 0) {
+ throw new IllegalArgumentException("At least one domain name must be included in domainNames.");
+ }
+
// decode the received input as a base64-urlencoded XDR representation of Stellar transaction envelope
AbstractTransaction parsed = Transaction.fromEnvelopeXdr(challengeXdr, network);
if (!(parsed instanceof Transaction)) {
@@ -130,10 +136,25 @@ public static ChallengeTransaction readChallengeTransaction(String challengeXdr,
throw new InvalidSep10ChallengeException("Operation should have a source account.");
}
+ String matchedDomainName = null;
+ for (String homeDomain : domainNames) {
+ if ((homeDomain + " " + MANAGER_DATA_NAME_FLAG).equals(manageDataOperation.getName())) {
+ matchedDomainName = homeDomain;
+ break;
+ }
+ }
+
+ if (matchedDomainName == null) {
+ throw new InvalidSep10ChallengeException("The transaction's operation key name does not include one of the expected home domains.");
+ }
+
if (StrKey.decodeVersionByte(clientAccountId) != StrKey.VersionByte.ACCOUNT_ID) {
throw new InvalidSep10ChallengeException("clientAccountId: "+clientAccountId+" is not a valid account id");
}
+ if (manageDataOperation.getValue() == null) {
+ throw new InvalidSep10ChallengeException("The transaction's operation value should not be null.");
+ }
// verify manage data value
if (manageDataOperation.getValue().length != 64) {
throw new InvalidSep10ChallengeException("Random nonce encoded as base64 should be 64 bytes long.");
@@ -170,7 +191,32 @@ public static ChallengeTransaction readChallengeTransaction(String challengeXdr,
throw new InvalidSep10ChallengeException(String.format("Transaction not signed by server: %s.", serverAccountId));
}
- return new ChallengeTransaction(transaction, clientAccountId);
+ return new ChallengeTransaction(transaction, clientAccountId, matchedDomainName);
+ }
+
+ /**
+ * Reads a SEP 10 challenge transaction and returns the decoded transaction envelope and client account ID contained within.
+ *
+ * It also verifies that transaction is signed by the server.
+ *
+ * It does not verify that the transaction has been signed by the client or
+ * that any signatures other than the servers on the transaction are valid. Use
+ * one of the following functions to completely verify the transaction:
+ * {@link Sep10Challenge#verifyChallengeTransactionSigners(String, String, Network, String, Set)} or
+ * {@link Sep10Challenge#verifyChallengeTransactionThreshold(String, String, Network, String, int, Set)} or
+ * {@link Sep10Challenge#verifyChallengeTransactionSigners(String, String, Network, String[], Set)} or
+ * {@link Sep10Challenge#verifyChallengeTransactionThreshold(String, String, Network, String[], int, Set)} or
+ *
+ * @param challengeXdr SEP-0010 transaction challenge transaction in base64.
+ * @param serverAccountId Account ID for server's account.
+ * @param network The network to connect to for verifying and retrieving.
+ * @param domainName The home domain that is expected to be included in the first Manage Data operation's string key.
+ * @return {@link ChallengeTransaction}, the decoded transaction envelope and client account ID contained within.
+ * @throws InvalidSep10ChallengeException If the SEP-0010 validation fails, the exception will be thrown.
+ * @throws IOException If read XDR string fails, the exception will be thrown.
+ */
+ public static ChallengeTransaction readChallengeTransaction(String challengeXdr, String serverAccountId, Network network, String domainName) throws InvalidSep10ChallengeException, IOException {
+ return readChallengeTransaction(challengeXdr, serverAccountId, network, new String[]{domainName});
}
/**
@@ -185,19 +231,41 @@ public static ChallengeTransaction readChallengeTransaction(String challengeXdr,
* @param challengeXdr SEP-0010 transaction challenge transaction in base64.
* @param serverAccountId Account ID for server's account.
* @param network The network to connect to for verifying and retrieving.
- * @param domainName The fully qualified domain name of the service requiring authentication (The domainName field is reserved for future use and not used).
+ * @param domainName The home domain that is expected to be included in the first Manage Data operation's string key.
* @param signers The signers of client account.
* @return a list of signers that were found is returned, excluding the server account ID.
* @throws InvalidSep10ChallengeException If the SEP-0010 validation fails, the exception will be thrown.
* @throws IOException If read XDR string fails, the exception will be thrown.
*/
public static Set verifyChallengeTransactionSigners(String challengeXdr, String serverAccountId, Network network, String domainName, Set signers) throws InvalidSep10ChallengeException, IOException {
+ return verifyChallengeTransactionSigners(challengeXdr, serverAccountId, network, new String[]{domainName}, signers);
+ }
+
+ /**
+ * Verifies that for a SEP 10 challenge transaction
+ * all signatures on the transaction are accounted for. A transaction is
+ * verified if it is signed by the server account, and all other signatures
+ * match a signer that has been provided as an argument. Additional signers can
+ * be provided that do not have a signature, but all signatures must be matched
+ * to a signer for verification to succeed. If verification succeeds a list of
+ * signers that were found is returned, excluding the server account ID.
+ *
+ * @param challengeXdr SEP-0010 transaction challenge transaction in base64.
+ * @param serverAccountId Account ID for server's account.
+ * @param network The network to connect to for verifying and retrieving.
+ * @param domainNames An array of home domains, one of which is expected to be included in the first Manage Data operation's string key.
+ * @param signers The signers of client account.
+ * @return a list of signers that were found is returned, excluding the server account ID.
+ * @throws InvalidSep10ChallengeException If the SEP-0010 validation fails, the exception will be thrown.
+ * @throws IOException If read XDR string fails, the exception will be thrown.
+ */
+ public static Set verifyChallengeTransactionSigners(String challengeXdr, String serverAccountId, Network network, String[] domainNames, Set signers) throws InvalidSep10ChallengeException, IOException {
if (signers == null || signers.isEmpty()) {
throw new InvalidSep10ChallengeException("No verifiable signers provided, at least one G... address must be provided.");
}
// Read the transaction which validates its structure.
- ChallengeTransaction parsedChallengeTransaction = readChallengeTransaction(challengeXdr, serverAccountId, network, domainName);
+ ChallengeTransaction parsedChallengeTransaction = readChallengeTransaction(challengeXdr, serverAccountId, network, domainNames);
Transaction transaction = parsedChallengeTransaction.getTransaction();
// Ensure the server account ID is an address and not a seed.
@@ -275,14 +343,14 @@ public static Set verifyChallengeTransactionSigners(String challengeXdr,
* @param challengeXdr SEP-0010 transaction challenge transaction in base64.
* @param serverAccountId Account ID for server's account.
* @param network The network to connect to for verifying and retrieving.
- * @param domainName The fully qualified domain name of the service requiring authentication (The domainName field is reserved for future use and not used).
+ * @param domainNames An array of home domains, one of which is expected to be included in the first Manage Data operation's string key.
* @param threshold The threshold on the client account.
* @param signers The signers of client account.
* @return a list of signers that were found is returned, excluding the server account ID.
* @throws InvalidSep10ChallengeException If the SEP-0010 validation fails, the exception will be thrown.
* @throws IOException If read XDR string fails, the exception will be thrown.
*/
- public static Set verifyChallengeTransactionThreshold(String challengeXdr, String serverAccountId, Network network, String domainName, int threshold, Set signers) throws InvalidSep10ChallengeException, IOException {
+ public static Set verifyChallengeTransactionThreshold(String challengeXdr, String serverAccountId, Network network, String[] domainNames, int threshold, Set signers) throws InvalidSep10ChallengeException, IOException {
if (signers == null || signers.isEmpty()) {
throw new InvalidSep10ChallengeException("No verifiable signers provided, at least one G... address must be provided.");
}
@@ -292,7 +360,7 @@ public static Set verifyChallengeTransactionThreshold(String challengeXd
weightsForSigner.put(signer.getKey(), signer.getWeight());
}
- Set signersFound = verifyChallengeTransactionSigners(challengeXdr, serverAccountId, network, domainName, weightsForSigner.keySet());
+ Set signersFound = verifyChallengeTransactionSigners(challengeXdr, serverAccountId, network, domainNames, weightsForSigner.keySet());
int sum = 0;
for (String signer : signersFound) {
@@ -309,6 +377,28 @@ public static Set verifyChallengeTransactionThreshold(String challengeXd
return signersFound;
}
+ /**
+ * Verifies that for a SEP-0010 challenge transaction
+ * all signatures on the transaction are accounted for and that the signatures
+ * meet a threshold on an account. A transaction is verified if it is signed by
+ * the server account, and all other signatures match a signer that has been
+ * provided as an argument, and those signatures meet a threshold on the
+ * account.
+ *
+ * @param challengeXdr SEP-0010 transaction challenge transaction in base64.
+ * @param serverAccountId Account ID for server's account.
+ * @param network The network to connect to for verifying and retrieving.
+ * @param domainName The home domain that is expected to be included in the first Manage Data operation's string key.
+ * @param threshold The threshold on the client account.
+ * @param signers The signers of client account.
+ * @return a list of signers that were found is returned, excluding the server account ID.
+ * @throws InvalidSep10ChallengeException If the SEP-0010 validation fails, the exception will be thrown.
+ * @throws IOException If read XDR string fails, the exception will be thrown.
+ */
+ public static Set verifyChallengeTransactionThreshold(String challengeXdr, String serverAccountId, Network network, String domainName, int threshold, Set signers) throws InvalidSep10ChallengeException, IOException {
+ return verifyChallengeTransactionThreshold(challengeXdr, serverAccountId, network, new String[]{domainName}, threshold, signers);
+ }
+
private static Set verifyTransactionSignatures(Transaction transaction, Set signers) throws InvalidSep10ChallengeException {
if (transaction.getSignatures().isEmpty()) {
throw new InvalidSep10ChallengeException("Transaction has no signatures.");
@@ -346,15 +436,17 @@ private static boolean verifyTransactionSignature(Transaction transaction, Strin
}
/**
- * Used to store the results produced by {@link Sep10Challenge#readChallengeTransaction(String, String, Network, String)}.
+ * Used to store the results produced by {@link Sep10Challenge#readChallengeTransaction(String, String, Network, String[])}.
*/
public static class ChallengeTransaction {
private final Transaction transaction;
private final String clientAccountId;
+ private final String matchedHomeDomain;
- public ChallengeTransaction(Transaction transaction, String clientAccountId) {
+ public ChallengeTransaction(Transaction transaction, String clientAccountId, String matchedHomeDomain) {
this.transaction = transaction;
this.clientAccountId = clientAccountId;
+ this.matchedHomeDomain = matchedHomeDomain;
}
public Transaction getTransaction() {
@@ -365,6 +457,10 @@ public String getClientAccountId() {
return clientAccountId;
}
+ public String getMatchedHomeDomain() {
+ return matchedHomeDomain;
+ }
+
@Override
public int hashCode() {
return Objects.hashCode(this.transaction.hashHex(), this.clientAccountId);
@@ -382,7 +478,8 @@ public boolean equals(Object object) {
ChallengeTransaction other = (ChallengeTransaction) object;
return Objects.equal(this.transaction.hashHex(), other.transaction.hashHex()) &&
- Objects.equal(this.clientAccountId, other.clientAccountId);
+ Objects.equal(this.clientAccountId, other.clientAccountId) &&
+ Objects.equal(this.matchedHomeDomain, other.matchedHomeDomain);
}
}
diff --git a/src/test/java/org/stellar/sdk/Sep10ChallengeTest.java b/src/test/java/org/stellar/sdk/Sep10ChallengeTest.java
index 15420bea8..b324944d2 100644
--- a/src/test/java/org/stellar/sdk/Sep10ChallengeTest.java
+++ b/src/test/java/org/stellar/sdk/Sep10ChallengeTest.java
@@ -3,7 +3,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.io.BaseEncoding;
import org.junit.Test;
-import org.stellar.sdk.xdr.BumpSequenceOp;
import org.stellar.sdk.xdr.EnvelopeType;
import org.stellar.sdk.xdr.TransactionEnvelope;
@@ -102,7 +101,7 @@ public void testReadChallengeTransactionValidSignedByServer() throws InvalidSep1
);
Sep10Challenge.ChallengeTransaction challengeTransaction = Sep10Challenge.readChallengeTransaction(transaction.toEnvelopeXdrBase64(), server.getAccountId(), Network.TESTNET, domainName);
- assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId()), challengeTransaction);
+ assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId(), domainName), challengeTransaction);
}
@Test
@@ -154,7 +153,7 @@ public void testReadChallengeTransactionAcceptsBothV0AndV1() throws InvalidSep10
server.getAccountId(),
Network.TESTNET, domainName
);
- assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId()), challengeTransaction);
+ assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId(), domainName), challengeTransaction);
}
}
@@ -256,7 +255,7 @@ public void testReadChallengeTransactionValidSignedByServerAndClient() throws In
transaction.sign(client);
Sep10Challenge.ChallengeTransaction challengeTransaction = Sep10Challenge.readChallengeTransaction(transaction.toEnvelopeXdrBase64(), server.getAccountId(), Network.TESTNET, domainName);
- assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId()), challengeTransaction);
+ assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId(), domainName), challengeTransaction);
}
@Test
@@ -745,49 +744,41 @@ public void testReadChallengeTransactionInvalidDataValueWrongByteLength() throws
}
@Test
- public void testReadChallengeTransactionValidDoesNotVerifyHomeDomainWithHomeDomainSetToNull() throws IOException, InvalidSep10ChallengeException {
+ public void testReadChallengeTransactionInvalidDataValueIsNull() throws IOException {
KeyPair server = KeyPair.random();
KeyPair client = KeyPair.random();
- Network network = Network.TESTNET;
String domainName = "example.com";
- long now = System.currentTimeMillis() / 1000L;
- long end = now + 300;
- TimeBounds timeBounds = new TimeBounds(now, end);
-
- Transaction transaction = Sep10Challenge.newChallenge(
- server,
- network,
- client.getAccountId(),
- domainName,
- timeBounds
- );
-
- Sep10Challenge.ChallengeTransaction challengeTransaction = Sep10Challenge.readChallengeTransaction(transaction.toEnvelopeXdrBase64(), server.getAccountId(), Network.TESTNET, null);
- assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId()), challengeTransaction);
- }
-
- @Test
- public void testReadChallengeTransactionValidDoesNotVerifyHomeDomainWithHomeDomainSetToInvalidValue() throws IOException, InvalidSep10ChallengeException {
- KeyPair server = KeyPair.random();
- KeyPair client = KeyPair.random();
Network network = Network.TESTNET;
- String domainName = "example.com";
long now = System.currentTimeMillis() / 1000L;
long end = now + 300;
TimeBounds timeBounds = new TimeBounds(now, end);
- Transaction transaction = Sep10Challenge.newChallenge(
- server,
- network,
- client.getAccountId(),
- domainName,
- timeBounds
+ Account sourceAccount = new Account(server.getAccountId(), -1L);
+ ManageDataOperation manageDataOperation1 = new ManageDataOperation.Builder(domainName + " auth", null)
+ .setSourceAccount(client.getAccountId())
+ .build();
+
+ Operation[] operations = new Operation[]{manageDataOperation1};
+ Transaction transaction = new Transaction(
+ sourceAccount.getAccountId(),
+ 100 * operations.length,
+ sourceAccount.getIncrementedSequenceNumber(),
+ operations,
+ Memo.none(),
+ timeBounds,
+ network
);
+ transaction.sign(server);
+ String challenge = transaction.toEnvelopeXdrBase64();
- Sep10Challenge.ChallengeTransaction challengeTransaction = Sep10Challenge.readChallengeTransaction(transaction.toEnvelopeXdrBase64(), server.getAccountId(), Network.TESTNET, "invalid.domain");
- assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId()), challengeTransaction);
+ try {
+ Sep10Challenge.readChallengeTransaction(challenge, server.getAccountId(), Network.TESTNET, domainName);
+ fail();
+ } catch (InvalidSep10ChallengeException e) {
+ assertEquals("The transaction's operation value should not be null.", e.getMessage());
+ }
}
@Test
@@ -829,7 +820,7 @@ public void testReadChallengeTransactionValidAdditionalManageDataOpsWithSourceAc
String challenge = transaction.toEnvelopeXdrBase64();
Sep10Challenge.ChallengeTransaction challengeTransaction = Sep10Challenge.readChallengeTransaction(challenge, server.getAccountId(), Network.TESTNET, domainName);
- assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId()), challengeTransaction);
+ assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId(), domainName), challengeTransaction);
}
@Test
@@ -968,6 +959,132 @@ public void testReadChallengeTransactionInvalidAdditionalOpsOfOtherTypes() throw
}
}
+ @Test
+ public void testReadChallengeTransactionValidMultipleDomainNames() throws IOException, InvalidSep10ChallengeException {
+ KeyPair server = KeyPair.random();
+ KeyPair client = KeyPair.random();
+ Network network = Network.TESTNET;
+ String domainName = "example.com";
+
+ long now = System.currentTimeMillis() / 1000L;
+ long end = now + 300;
+ TimeBounds timeBounds = new TimeBounds(now, end);
+
+ Transaction transaction = null;
+ try {
+ transaction = Sep10Challenge.newChallenge(
+ server,
+ network,
+ client.getAccountId(),
+ domainName,
+ timeBounds
+ );
+ } catch (InvalidSep10ChallengeException e) {
+ fail("Should not have thrown any exception.");
+ }
+
+ Sep10Challenge.ChallengeTransaction challengeTransaction = Sep10Challenge.readChallengeTransaction(transaction.toEnvelopeXdrBase64(), server.getAccountId(), Network.TESTNET, new String[]{"example3.com", "example2.com", "example.com"});
+ assertEquals(new Sep10Challenge.ChallengeTransaction(transaction, client.getAccountId(), domainName), challengeTransaction);
+ }
+
+ @Test
+ public void testReadChallengeTransactionInvalidDomainNamesMismatch() throws IOException {
+ KeyPair server = KeyPair.random();
+ KeyPair client = KeyPair.random();
+ Network network = Network.TESTNET;
+ String domainName = "example.com";
+
+ long now = System.currentTimeMillis() / 1000L;
+ long end = now + 300;
+ TimeBounds timeBounds = new TimeBounds(now, end);
+
+ Transaction transaction = null;
+ try {
+ transaction = Sep10Challenge.newChallenge(
+ server,
+ network,
+ client.getAccountId(),
+ domainName,
+ timeBounds
+ );
+ } catch (InvalidSep10ChallengeException e) {
+ fail("Should not have thrown any exception.");
+ }
+
+ try {
+ Sep10Challenge.readChallengeTransaction(transaction.toEnvelopeXdrBase64(), server.getAccountId(), Network.TESTNET, new String[]{"example2.com", "example1.com"});
+ fail();
+ } catch (InvalidSep10ChallengeException e) {
+ assertEquals("The transaction's operation key name does not include one of the expected home domains.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testReadChallengeTransactionInvalidDomainNamesEmpty() throws IOException, InvalidSep10ChallengeException {
+ KeyPair server = KeyPair.random();
+ KeyPair client = KeyPair.random();
+ Network network = Network.TESTNET;
+ String domainName = "example.com";
+
+ long now = System.currentTimeMillis() / 1000L;
+ long end = now + 300;
+ TimeBounds timeBounds = new TimeBounds(now, end);
+
+ Transaction transaction = null;
+ try {
+ transaction = Sep10Challenge.newChallenge(
+ server,
+ network,
+ client.getAccountId(),
+ domainName,
+ timeBounds
+ );
+ } catch (InvalidSep10ChallengeException e) {
+ fail("Should not have thrown any exception.");
+ }
+
+ try {
+ String[] domainNames = new String[]{};
+ Sep10Challenge.readChallengeTransaction(transaction.toEnvelopeXdrBase64(), server.getAccountId(), Network.TESTNET, domainNames);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertEquals("At least one domain name must be included in domainNames.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testReadChallengeTransactionInvalidDomainNamesNull() throws IOException, InvalidSep10ChallengeException {
+ KeyPair server = KeyPair.random();
+ KeyPair client = KeyPair.random();
+ Network network = Network.TESTNET;
+ String domainName = "example.com";
+
+ long now = System.currentTimeMillis() / 1000L;
+ long end = now + 300;
+ TimeBounds timeBounds = new TimeBounds(now, end);
+
+ Transaction transaction = null;
+ try {
+ transaction = Sep10Challenge.newChallenge(
+ server,
+ network,
+ client.getAccountId(),
+ domainName,
+ timeBounds
+ );
+ } catch (InvalidSep10ChallengeException e) {
+ fail("Should not have thrown any exception.");
+ }
+
+ try {
+ String[] domainNames = null;
+ Sep10Challenge.readChallengeTransaction(transaction.toEnvelopeXdrBase64(), server.getAccountId(), Network.TESTNET, domainNames);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertEquals("At least one domain name must be included in domainNames.", e.getMessage());
+ }
+ }
+
@Test
public void testVerifyChallengeTransactionThresholdInvalidNotSignedByServer() throws IOException {
Network network = Network.TESTNET;
@@ -1018,7 +1135,6 @@ public void testVerifyChallengeTransactionThresholdInvalidNotSignedByServer() th
} catch (InvalidSep10ChallengeException e) {
assertEquals(String.format("Transaction not signed by server: %s.", server.getAccountId()), e.getMessage());
}
-
}
@Test
@@ -1051,6 +1167,36 @@ public void testVerifyChallengeTransactionThresholdValidServerAndClientKeyMeetin
assertEquals(new HashSet(Collections.singletonList(masterClient.getAccountId())), signersFound);
}
+ @Test
+ public void testVerifyChallengeTransactionThresholdValidMultipleDomainNames() throws IOException, InvalidSep10ChallengeException {
+ Network network = Network.TESTNET;
+ KeyPair server = KeyPair.random();
+ KeyPair masterClient = KeyPair.random();
+
+ long now = System.currentTimeMillis() / 1000L;
+ long end = now + 300;
+ TimeBounds timeBounds = new TimeBounds(now, end);
+ String domainName = "example.com";
+
+ Transaction transaction = Sep10Challenge.newChallenge(
+ server,
+ network,
+ masterClient.getAccountId(),
+ domainName,
+ timeBounds
+ );
+
+ transaction.sign(masterClient);
+
+ Set signers = new HashSet(Collections.singletonList(
+ new Sep10Challenge.Signer(masterClient.getAccountId(), 255)
+ ));
+
+ int threshold = 255;
+ Set signersFound = Sep10Challenge.verifyChallengeTransactionThreshold(transaction.toEnvelopeXdrBase64(), server.getAccountId(), network, new String[]{"example3.com", "example2.com", "example.com"}, threshold, signers);
+ assertEquals(new HashSet(Collections.singletonList(masterClient.getAccountId())), signersFound);
+ }
+
@Test
public void testVerifyChallengeTransactionThresholdValidServerAndMultipleClientKeyMeetingThreshold() throws IOException, InvalidSep10ChallengeException {
Network network = Network.TESTNET;
@@ -1427,6 +1573,32 @@ public void testVerifyChallengeTransactionSignersValidServerAndClientMasterKey()
assertEquals(signers, signersFound);
}
+ @Test
+ public void testVerifyChallengeTransactionSignersValidMultipleDomainNames() throws InvalidSep10ChallengeException, IOException {
+ KeyPair server = KeyPair.random();
+ KeyPair masterClient = KeyPair.random();
+ Network network = Network.TESTNET;
+
+ long now = System.currentTimeMillis() / 1000L;
+ long end = now + 300;
+ TimeBounds timeBounds = new TimeBounds(now, end);
+ String domainName = "example.com";
+
+ Transaction transaction = Sep10Challenge.newChallenge(
+ server,
+ network,
+ masterClient.getAccountId(),
+ domainName,
+ timeBounds
+ );
+
+ transaction.sign(masterClient);
+
+ Set signers = new HashSet(Collections.singletonList(masterClient.getAccountId()));
+ Set signersFound = Sep10Challenge.verifyChallengeTransactionSigners(transaction.toEnvelopeXdrBase64(), server.getAccountId(), network, new String[]{"example3.com", "example2.com", "example.com"}, signers);
+ assertEquals(signers, signersFound);
+ }
+
@Test
public void testVerifyChallengeTransactionSignersInvalidServerAndNoClient() throws InvalidSep10ChallengeException, IOException {
KeyPair server = KeyPair.random();
@@ -1790,56 +1962,6 @@ public void testVerifyChallengeTransactionSignersInvalidNoSignersEmptySet() thro
}
}
- @Test
- public void testVerifyChallengeTransactionValidDoesNotVerifyHomeDomainHomeDomainSetToNull() throws IOException, InvalidSep10ChallengeException {
- KeyPair server = KeyPair.random();
- KeyPair masterClient = KeyPair.random();
- Network network = Network.TESTNET;
- String domainName = "example.com";
-
- long now = System.currentTimeMillis() / 1000L;
- long end = now + 300;
- TimeBounds timeBounds = new TimeBounds(now, end);
-
- Transaction transaction = Sep10Challenge.newChallenge(
- server,
- network,
- masterClient.getAccountId(),
- domainName,
- timeBounds
- );
- transaction.sign(masterClient);
-
- Set signers = new HashSet(Collections.singletonList(masterClient.getAccountId()));
- Set signersFound = Sep10Challenge.verifyChallengeTransactionSigners(transaction.toEnvelopeXdrBase64(), server.getAccountId(), network, null, signers);
- assertEquals(signers, signersFound);
- }
-
- @Test
- public void testVerifyChallengeTransactionValidDoesNotVerifyHomeDomainWithHomeDomainSetToInvalidValue() throws IOException, InvalidSep10ChallengeException {
- KeyPair server = KeyPair.random();
- KeyPair masterClient = KeyPair.random();
- Network network = Network.TESTNET;
- String domainName = "example.com";
-
- long now = System.currentTimeMillis() / 1000L;
- long end = now + 300;
- TimeBounds timeBounds = new TimeBounds(now, end);
-
- Transaction transaction = Sep10Challenge.newChallenge(
- server,
- network,
- masterClient.getAccountId(),
- domainName,
- timeBounds
- );
- transaction.sign(masterClient);
-
- Set signers = new HashSet(Collections.singletonList(masterClient.getAccountId()));
- Set signersFound = Sep10Challenge.verifyChallengeTransactionSigners(transaction.toEnvelopeXdrBase64(), server.getAccountId(), network, "invalid.domain", signers);
- assertEquals(signers, signersFound);
- }
-
@Test
public void testVerifyChallengeTransactionValidAdditionalManageDataOpsWithSourceAccountSetToServerAccount() throws IOException, InvalidSep10ChallengeException {
KeyPair server = KeyPair.random();