Skip to content

Commit

Permalink
Fixed missing padding in SrpInteger arithmetic operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
yallie committed Dec 19, 2018
1 parent 142b4b8 commit cbd604a
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 19 deletions.
11 changes: 11 additions & 0 deletions src/srp.tests/SrpAuthenticationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,17 @@ public async Task ParallelAuthenticationTest()

// make sure both the client and the server have the same session key
Assert.AreEqual(clientSession.Key, serverSession.Key);

// verify padded length of all parameters
Assert.AreEqual(verifier.Length, parameters.PaddedLength);
Assert.AreEqual(clientEphemeral.Public.Length, parameters.PaddedLength);
Assert.AreEqual(clientEphemeral.Secret.Length, parameters.HashSizeBytes * 2);
Assert.AreEqual(serverEphemeral.Public.Length, parameters.PaddedLength);
Assert.AreEqual(serverEphemeral.Secret.Length, parameters.HashSizeBytes * 2);
Assert.AreEqual(serverSession.Key.Length, parameters.HashSizeBytes * 2);
Assert.AreEqual(clientSession.Key.Length, parameters.HashSizeBytes * 2);
Assert.AreEqual(serverSession.Proof.Length, parameters.HashSizeBytes * 2);
Assert.AreEqual(clientSession.Proof.Length, parameters.HashSizeBytes * 2);
}));

await Task.WhenAll(tasks);
Expand Down
44 changes: 41 additions & 3 deletions src/srp.tests/SrpIntegerTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Security.Cryptography;
using NUnit.Framework;

Expand Down Expand Up @@ -82,7 +83,7 @@ public void SrpIntegerSubtract()
public void SrpIntegerMultiply()
{
var result = SrpInteger.FromHex("CAFE") * SrpInteger.FromHex("babe");
Assert.AreEqual("94133484", result.ToHex());
Assert.AreEqual("94133484", result.ToHex(8));
}

[Test]
Expand All @@ -95,7 +96,7 @@ public void SrpIntegerDivide()
[Test]
public void SrpIntegerModulo()
{
var result = SrpInteger.FromHex("10") % SrpInteger.FromHex("9");
var result = SrpInteger.FromHex("10") % SrpInteger.FromHex("09");
Assert.AreEqual("07", result.ToHex());
}

Expand Down Expand Up @@ -253,5 +254,42 @@ public void RandomIntegerReturnsAnIntegerOfTheGivenSize()
Assert.AreEqual(16, rnd.ToHex().Length);
Assert.AreNotEqual("0000000000000000", rnd.ToHex());
}

[Test]
public void ArithmeticOperationsKeepTheLargestHexSizeOfOperands()
{
var left = SrpInteger.FromHex("12345");
var right = SrpInteger.FromHex("1234567890");
var operations = new Func<SrpInteger, SrpInteger, SrpInteger>[]
{
(a, b) => a + b,
(a, b) => a - b,
(a, b) => a / b,
(a, b) => a ^ b,
};

Assert.Multiple(() =>
{
foreach (var op in operations)
{
Assert.AreEqual(10, op(left, right).HexLength);
Assert.AreEqual(10, op(right, left).HexLength);
}
});

// multiplication loses hex widths
Assert.IsNull((left * right).HexLength);
Assert.IsNull((right * left).HexLength);

// mod gets the width of the modulus
Assert.AreEqual(10, (left % right).HexLength);
Assert.AreEqual(5, (right % left).HexLength);

// modPow gets the width of the modulus
Assert.AreEqual(5, left.ModPow(right, left).HexLength);
Assert.AreEqual(5, right.ModPow(left, left).HexLength);
Assert.AreEqual(10, left.ModPow(right, right).HexLength);
Assert.AreEqual(10, right.ModPow(left, right).HexLength);
}
}
}
10 changes: 10 additions & 0 deletions src/srp.tests/SrpServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ public void SrpServerGeneratesEphemeralValue()
Assert.IsTrue(ephemeral.Secret.Length < ephemeral.Public.Length);
}

[Test]
public void SrpServerEphemeralValueWidthEqualsToPaddedLength()
{
var server = new SrpServer();
var verifier = "a113f1b3ed0aed0bf3ec043b80eb8a5a983b201237b2d14bf59b6eaa09b3bc8c9b8371368974395bef93b2beba1ca95fd0eec768915fcb7725fba212850e285d92e3d89995dad4fbc430bed66f1049a7a95aea09a3a3e7a797152135d6e881ac8f703b886e6ba9f68fc8a304b1670b2b8adb109932fa9c642810598ef45d60a73b5e0fcc11c1fcc3989d2254a2407d7ffea3c4dc7c3511baa2137f4b2e9226bfd082e1acfe03d3a944810c41cbf633220cadb107fef709075b46796a1e632dd9aa075e40e4619998ef26e1c09238839883cdf3eee3804a82ca4bc3cd31bdf9c8cd2535511dcbc00491e5fe93e155321c7b686bda115b92a2d7bb5fb01a51355e";
var secret = "ddfddf4060e11ef3f5389b8be0ff4f5133f8958aa0dafb0e4ad65949cb5c723d";
var ephemeral = server.ComputeB(verifier, SrpInteger.FromHex(secret)).ToHex();
Assert.IsTrue(ephemeral.Length == server.Parameters.PaddedLength);
}

[Test]
public void SrpServerDeriveSession()
{
Expand Down
28 changes: 16 additions & 12 deletions src/srp/SrpInteger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ private static string NormalizeWhitespace(string hexNumber) =>
HexLength = newLength,
};

internal static int Max(params int?[] values) => values.Max(v => v ?? 0);

/// <summary>
/// Generates the random integer number.
/// </summary>
Expand Down Expand Up @@ -119,9 +121,11 @@ public SrpInteger ModPow(SrpInteger exponent, SrpInteger modulus)
/// <summary>
/// Returns the fixed-length hexadecimal representation of the <see cref="SrpInteger"/> instance.
/// </summary>
public string ToHex()
/// <param name="hexLength">Custom hexadecimal length (optional)</param>
public string ToHex(int? hexLength = null)
{
if (!HexLength.HasValue)
hexLength = HexLength ?? hexLength;
if (!hexLength.HasValue)
{
throw new InvalidOperationException("Hexadecimal length is not specified");
}
Expand All @@ -135,7 +139,7 @@ public string ToHex()
}

// ToString may add extra leading zeros to the positive BigIntegers, so we trim them first
return sign + value.ToString("x").TrimStart('0').PadLeft(HexLength.Value, '0');
return sign + value.ToString("x").TrimStart('0').PadLeft(hexLength.Value, '0');
}

/// <summary>
Expand Down Expand Up @@ -215,7 +219,7 @@ public byte[] ToByteArray()
return new SrpInteger
{
Value = left.Value - right.Value,
HexLength = left.HexLength,
HexLength = Max(left.HexLength, right.HexLength),
};
}

Expand All @@ -229,7 +233,7 @@ public byte[] ToByteArray()
return new SrpInteger
{
Value = left.Value + right.Value,
HexLength = left.HexLength,
HexLength = Max(left.HexLength, right.HexLength),
};
}

Expand All @@ -243,21 +247,21 @@ public byte[] ToByteArray()
return new SrpInteger
{
Value = dividend.Value / divisor.Value,
HexLength = dividend.HexLength,
HexLength = Max(dividend.HexLength, divisor.HexLength),
};
}

/// <summary>
/// Implements the operator %.
/// </summary>
/// <param name="dividend">The dividend.</param>
/// <param name="divisor">The divisor.</param>
public static SrpInteger operator %(SrpInteger dividend, SrpInteger divisor)
/// <param name="modulus">The modulus.</param>
public static SrpInteger operator %(SrpInteger dividend, SrpInteger modulus)
{
return new SrpInteger
{
Value = dividend.Value % divisor.Value,
HexLength = dividend.HexLength,
Value = dividend.Value % modulus.Value,
HexLength = modulus.HexLength,
};
}

Expand All @@ -271,7 +275,7 @@ public byte[] ToByteArray()
return new SrpInteger
{
Value = left.Value * right.Value,
HexLength = left.HexLength,
HexLength = null, // the padding is lost
};
}

Expand All @@ -285,7 +289,7 @@ public byte[] ToByteArray()
return new SrpInteger
{
Value = left.Value ^ right.Value,
HexLength = left.HexLength,
HexLength = Max(left.HexLength, right.HexLength),
};
}

Expand Down
8 changes: 4 additions & 4 deletions src/srp/srp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@
<PackageReleaseNotes>What's new:

v1.0.3:
- Fixed SrpParameters thread safety issue.
Fixed SrpParameters thread safety issue.

v1.0.2:
- Fixed sha384/sha512 support in .NET Standard 1.6 version.
Fixed sha384/sha512 support in .NET Standard 1.6 version.

v1.0.1:
- Enabled .NET Standard 1.6 support.
Enabled .NET Standard 1.6 support.

v1.0.0:
- Initial release.
Initial release.
</PackageReleaseNotes>
<CodeAnalysisRuleSet>..\srp.ruleset</CodeAnalysisRuleSet>
<BaseOutputPath>..\..\bin\</BaseOutputPath>
Expand Down

0 comments on commit cbd604a

Please sign in to comment.