From 939eb76ea77f8c8d69f658574d2e73acdf78a211 Mon Sep 17 00:00:00 2001 From: Adolfo Builes Date: Tue, 6 Aug 2019 15:33:02 -0500 Subject: [PATCH 1/2] Fix manage data value in SEP0010 challenge builder. >The value must be a 64 byte long base64 encoded >cryptographic-quality random string We were generating a 64 bytes nonce which wasn't necessarily encoded in base64. Closes #395 --- src/utils.ts | 21 ++++++++++++++++++++- test/unit/utils_test.js | 31 ++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index fd63745ac..50b908d66 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -42,6 +42,13 @@ export namespace Utils { const account = new Account(serverKeypair.publicKey(), "-1"); const now = Math.floor(Date.now() / 1000); + // A Base64 digit represents 6 bits, to generate a random 64 bytes + // base64 string, we need 48 random bytes = (64 * 6)/8 + // + // Each Base64 digit is in ASCII and each ASCII characters when + // turned into binary represents 8 bits = 1 bytes. + const value = randomBytes(48).toString("base64"); + const transaction = new TransactionBuilder(account, { fee: BASE_FEE, timebounds: { @@ -52,7 +59,7 @@ export namespace Utils { .addOperation( Operation.manageData({ name: `${anchorName} auth`, - value: randomBytes(64), + value, source: clientAccountID, }), ) @@ -132,6 +139,18 @@ export namespace Utils { ); } + if (Buffer.from(operation.value.toString(), "base64").length !== 48) { + throw new InvalidSep10ChallengeError( + "The transaction's operation value should be a 64 bytes base64 random string", + ); + } + + if (operation.type !== "manageData") { + throw new InvalidSep10ChallengeError( + "The transaction's operation should be manageData", + ); + } + if (!verifyTxSignedBy(transaction, serverAccountId)) { throw new InvalidSep10ChallengeError( "The transaction is not signed by the server", diff --git a/test/unit/utils_test.js b/test/unit/utils_test.js index 16ea31d78..6b9f774d4 100644 --- a/test/unit/utils_test.js +++ b/test/unit/utils_test.js @@ -38,6 +38,7 @@ describe('Utils', function() { expect(operation.source).to.eql("GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF"); expect(operation.type).to.eql("manageData"); expect(operation.value.length).to.eql(64); + expect(Buffer.from(operation.value.toString(), 'base64').length).to.eql(48); }); it('uses the passed-in timeout', function() { @@ -154,7 +155,7 @@ describe('Utils', function() { .addOperation( StellarSdk.Operation.manageData({ name: 'SDF auth', - value: randomBytes(64) + value: randomBytes(48).toString('base64') }) ) .setTimeout(30) @@ -201,6 +202,34 @@ describe('Utils', function() { ); }); + it('throws an error if operation value is not a 64 bytes base64 string', function() { + let keypair = StellarSdk.Keypair.random(); + const account = new StellarSdk.Account(keypair.publicKey(), "-1"); + const transaction = new StellarSdk.TransactionBuilder(account, { fee: 100 }) + .addOperation( + StellarSdk.Operation.manageData({ + name: 'SDF auth', + value: randomBytes(64), + source: 'GBDIT5GUJ7R5BXO3GJHFXJ6AZ5UQK6MNOIDMPQUSMXLIHTUNR2Q5CFNF' + }) + ) + .setTimeout(30) + .build(); + + transaction.sign(keypair); + const challenge = transaction + .toEnvelope() + .toXDR("base64") + .toString(); + + expect( + () => StellarSdk.Utils.verifyChallengeTx(challenge, keypair.publicKey()) + ).to.throw( + StellarSdk.InvalidSep10ChallengeError, + /The transaction\'s operation value should be a 64 bytes base64 random string/ + ); + }); + it('throws an error if transaction is not signed by the server', function() { let keypair = StellarSdk.Keypair.random(); From ca01ae44597e8ada54d4ba103db2d972c8577e3b Mon Sep 17 00:00:00 2001 From: Adolfo Builes Date: Tue, 6 Aug 2019 17:32:18 -0500 Subject: [PATCH 2/2] Bump stellar-base. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b49d7d6d7..cb6c99273 100644 --- a/package.json +++ b/package.json @@ -141,7 +141,7 @@ "eventsource": "^1.0.7", "lodash": "^4.17.11", "randombytes": "^2.1.0", - "stellar-base": "^1.0.3", + "stellar-base": "^1.1.1", "toml": "^2.3.0", "tslib": "^1.10.0", "urijs": "^1.19.1", diff --git a/yarn.lock b/yarn.lock index aa871a823..e60a35a48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7855,10 +7855,10 @@ statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" -stellar-base@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/stellar-base/-/stellar-base-1.0.3.tgz#8d3121ca1ce85321b0647c44e69e5877be8e16e1" - integrity sha512-1JP/OnjUfbXryrICQJOrxsGgw9VlsgdpGje67692uI9mN8xP+2EyTF1fDs2KllO1Xx/6AaIB+DaU9VGv2nBMgw== +stellar-base@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stellar-base/-/stellar-base-1.1.1.tgz#2a97b25584e3e92241a601903a96a776938848cf" + integrity sha512-E7L6bjM2OlY4wtf+G9ruG52/LXP/Bs7i5L4jbJJK+RFK/2jp6CNqK97i8/isKF/XpO46WW14EwqOUnXvVfBioQ== dependencies: base32.js "^0.1.0" bignumber.js "^4.0.0"