Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 237: Added decompression buffer limit of 250Kb to Deflate compression alg #238

Merged
merged 3 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ JWE JSON Serialization cross-tested with [JWCrypto](https://github.com/latchset/
Library is fully FIPS compliant since v2.1

## Which version?
- v5.0 brings Linux, OSX and FreeBSD compatibility for [ECDH encryption](#ecdh-es-and-ecdh-es-with-aes-key-wrap-key-management-family-of-algorithms) as long as managed `ECDsa` keys support. And fixes cross compatibility issues with encryption over NIST P-384, P-521 curves.
- v5.0 brings Linux, OSX and FreeBSD compatibility for [ECDH encryption](#ecdh-es-and-ecdh-es-with-aes-key-wrap-key-management-family-of-algorithms) as long as managed `ECDsa` keys support. Fixes cross compatibility issues with encryption over NIST P-384, P-521 curves. And introduces new [security fixes and controls](#customizing-compression).

- v4.1 added additional capabilities to manage runtime avaliable alg suite, see [Customizing library for security](#customizing-library-for-security). And also introduced default max limits for `PBKDF2` (`PBES2-*`) max iterations according to [OWASP PBKDF2 Recomendations](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2).

Expand All @@ -32,7 +32,10 @@ Library is fully FIPS compliant since v2.1
- PCLCrypto based experimental project living up here: [jose-pcl](https://github.com/dvsekhvalnov/jose-pcl).

## Important upgrade notes
> :warning: **v4 -> v5 JWK EC keys now bridges to `ECDsa` by default instead of `CngKey` on .net 4.7.2+ and netstandard2.1+**
> :warning: **v4 -> v5**:
> - JWK EC keys now bridges to `ECDsa` by default instead of `CngKey` on .net 4.7.2+ and netstandard2.1+
> - Deflate decompression is limited to 250Kb by default. Check out [customization section](#customizing-compression) if need more.


> :warning: **v3.0 -> v3.1 stricter argument validation extraHeaders argument**
>
Expand Down Expand Up @@ -1452,8 +1455,20 @@ One can use following methods to deregister any signing, encryption, key managem
```c#
JWT.DefaultSettings.DeregisterJws(JwsAlgorithm.none)
.DeregisterJwe(JweAlgorithm.RSA1_5)
.DeregisterJwe(JweAlgorithm.DIR);
.DeregisterJwe(JweAlgorithm.DIR)
.DeregisterCompression(JweCompression.DEF);
```

### Customizing compression
There were denial-of-service attacks reported on JWT libraries that supports deflate compression by constructing malicious payload that explodes in terms of RAM on decompression. See for details: https://github.com/dvsekhvalnov/jose-jwt/issues/237

As of v5 `jose-jwt` limits decompression buffer to 250Kb to limit memory consumption and additionaly provides a way to adjust the limit according to specific scenarios:

``` cs
// Override compression alg with new limits (10Kb example)
Jose.JWT.DefaultSettings.RegisterCompression(JweCompression.DEF, new DeflateCompression(10 * 1024));
```

### Customizing PBKDF2
As it quite easy to abuse `PBES2` family of algorithms via forging header with extra large `p2c` values, `jose-jwt` library introduced iteration count limits in v4.1 to reduce runtime exposure.

Expand All @@ -1468,7 +1483,7 @@ By default, `maxIterations` is set according to [OWASP PBKDF2 Recomendations](ht
If it is desired to implement different limits, it can be achieved via registering `Pbse2HmacShaKeyManagementWithAesKeyWrap` implementation with different parameters:

```c#
Jost.JWT.DefaultSettings
Jose.JWT.DefaultSettings
// Pick your own min/max limits
.RegisterJwe(JweAlgorithm.PBES2_HS256_A128KW, new Pbse2HmacShaKeyManagementWithAesKeyWrap(128, new AesKeyWrapManagement(128), 310000, 310000));
.RegisterJwe(JweAlgorithm.PBES2_HS384_A192KW, new Pbse2HmacShaKeyManagementWithAesKeyWrap(192, new AesKeyWrapManagement(192), 250000, 250000));
Expand Down
14 changes: 14 additions & 0 deletions UnitTests/ArraysTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,19 @@ public void RightmostBits()
Assert.Equal(new byte[] { 8, 9 }, Arrays.RightmostBits(data, 16));
Assert.Equal(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, Arrays.RightmostBits(data, 72));
}

[Fact]
public void Truncate()
{
// given
byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// then
Assert.Equal(new byte[] {}, Arrays.Truncate(data, 0));
Assert.Equal(new byte[] { 0 }, Arrays.Truncate(data, 1));
Assert.Equal(new byte[] { 0, 1, 2, 3, 4 }, Arrays.Truncate(data, 5));
Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, Arrays.Truncate(data, 10));
}

}
}
37 changes: 37 additions & 0 deletions UnitTests/SecurityVulnerabilitiesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,42 @@ public void BitLengthIntegerOverflow()
Console.Out.WriteLine(e.ToString());
}
}

[Fact]
public void DeflateBomb()
{
// given
Jwk privateKey = new Jwk(
e: "AQAB",
n: "qFZv0pea_jn5Mo4qEUmStuhlulso8n1inXbEotd_zTrQp9K0RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1MmnO_0N97dMBz_7fmvyv0hgHaBdQ5mR5u3LTlHo8tjRE7-GzZmGs6jMcyj7HbXobDPQJZpqNy6JjliDVXxW8nWJDetxGBlqmTj1E1fr2RCsZLreDOPSDIedG1upz9RraShsIDzeefOcKibcAaKeeVI3rkAU8_mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXIkhvNu_ve0v7LiLT4G_OxYGzpOQcCnimKdojzNP6GtVDaMPh-QkSJE32UCos9R3wI2Q",
p: "0qaOkT174vRG3E_67gU3lgOgoT6L3pVHuu7wfrIEoxycPa5_mZVG54SgvQUofGUYEGjR0lavUAjClw9tOzcODHX8RAxkuDntAFntBxgRM-IzAy8QzeRl_cbhgVjBTAhBcxg-3VySv5GdxFyrQaIo8Oy_PPI1L4EFKZHmicBd3ts",
q: "zJPqCDKqaJH9TAGfzt6b4aNt9fpirEcdpAF1bCedFfQmUZM0LG3rMtOAIhjEXgADt5GB8ZNK3BQl8BJyMmKs57oKmbVcODERCtPqjECXXsxH-az9nzxatPvcb7imFW8OlWslwr4IIRKdEjzEYs4syQJz7k2ktqOpYI5_UfYnw1s",
d: "lJhwb0pKlB2ivyDFO6thajotClrMA3nxIiSkIUbvVr-TToFtha36gyF6w6e6YNXQXs4HhMRy1_b-nRQDk8G4_f5urd_q-pOn5u4KfmqN3Xw-lYD3ddi9qF0NLeTVUNVFASeP0FFqbPYfdNwD-LyvwjhtT_ggMOAw3mYvU5cBfz6-3uPdhl3CwQFCTgwOud_BA9p2MPMUHG82wMK_sNO1I0TYpjm7TnwNBwiKbMf-i5CKnuohgoYrEDYLeMg3f32eBljlCFNYaoCtT-mr1Ze0OTJND04vbfLotV-BBKulIpbOOSeVpKG7gJxZHmv7in7PE5_WzaxKFVoHW3wR6v_GzQ",
dp: "KTWmTGmf092AA1euOmRQ5IsfIIxQ5qGDn-FgsRh4acSOGE8L7WrTrTU4EOJyciuA0qz-50xIDbs4_j5pWx1BJVTrnhBin9vNLrVo9mtR6jmFS0ko226kOUpwEVLgtdQjobWLjtiuaMW-_Iw4gKWNptxZ6T1lBD8UWHaPiEFW2-M",
dq: "Jn0lqMkvemENEMG1eUw0c601wPOMoPD4SKTlnKWPTlQS6YISbNF5UKSuFLwoJa9HA8BifDrD-Mfpo1M1HPmnoilEWUrfwMqqdCkOlbiJQhKY8AZ16QGH50kDXhmVVa8BRWdVQWBTUzWXS5kXMaeskVzextTgymPcOAhXN-ph7MU",
qi: "sRAPigJpl8S_vsf1zhJTrHM97xRwuB26R6Tm-J8sKRPb7p5xxNlmOBBFvWmWxdto8dBElNlydSZan373yBLxzW-bZgVp-B2RKT1B3WhTYW_Vo5DLhWi84XMncJxH7avtxtF9yksaeKe0e2n3J6TTan53mDg4KF8U0OEO2ciqO9g"
);

Jwk publicKey = new Jwk(
e: "AQAB",
n: "qFZv0pea_jn5Mo4qEUmStuhlulso8n1inXbEotd_zTrQp9K0RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1MmnO_0N97dMBz_7fmvyv0hgHaBdQ5mR5u3LTlHo8tjRE7-GzZmGs6jMcyj7HbXobDPQJZpqNy6JjliDVXxW8nWJDetxGBlqmTj1E1fr2RCsZLreDOPSDIedG1upz9RraShsIDzeefOcKibcAaKeeVI3rkAU8_mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXIkhvNu_ve0v7LiLT4G_OxYGzpOQcCnimKdojzNP6GtVDaMPh-QkSJE32UCos9R3wI2Q"
);

string strU = new string('U', 400000000);
string strUU = new string('U', 100000000);
string payload = $@"{{""U"":""{strU}"", ""UU"":""{strUU}""}}";
string bomb = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM, JweCompression.DEF);

// when
try
{
string decoded = Jose.JWT.Decode(bomb, privateKey, JwsAlgorithm.RS256);
Assert.True(false, "Should fail with NotSupportedException");
}
catch (JoseException e)
{
Console.Out.WriteLine(e.ToString());
}
}
}
}
1 change: 1 addition & 0 deletions UnitTests/SettingsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ private class MockKeyManagement : DirectKeyManagement, IKeyManagement

private class MockCompression : DeflateCompression, ICompression
{
public MockCompression(): base(250*1024) {}
public bool CompressCalled { get; set; }
public bool DecompressCalled { get; set; }

Expand Down
13 changes: 13 additions & 0 deletions UnitTestsNet40/ArraysTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,18 @@ public void RightmostBits()
Assert.That(Arrays.RightmostBits(data,16), Is.EqualTo(new byte[] { 8, 9 }));
Assert.That(Arrays.RightmostBits(data, 72), Is.EqualTo(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }));
}

[Test]
public void Truncate()
{
// given
byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// then
Assert.That(Arrays.Truncate(data, 0), Is.EqualTo(new byte[] {}));
Assert.That(Arrays.Truncate(data, 1), Is.EqualTo(new byte[] { 0 }));
Assert.That(Arrays.Truncate(data, 5), Is.EqualTo(new byte[] { 0, 1, 2, 3, 4 }));
Assert.That(Arrays.Truncate(data, 10), Is.EqualTo(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }));
}
}
}
28 changes: 28 additions & 0 deletions UnitTestsNet40/SecurityVulnerabilitiesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,33 @@ public void BitLengthIntegerOverflow()
//if we reach that point HMAC check was bypassed although the decrypted data is different
Assert.Fail("JoseException should be raised.");
}

[Test]
public void DeflateBomb()
{
// given
byte[] x = Base64Url.Decode("weNJy2HscCSM6AEDTDg04biOvhFhyyWvOHQfeF_PxMQ");
byte[] y = Base64Url.Decode("e8lnCO-AlStT-NJVX-crhB7QRYhiix03illJOVAOyck");
byte[] d = Base64Url.Decode("VEmDZpDXXK8p8N0Cndsxs924q6nS1RXFASRl6BfUqdw");

var privateKey = EccKey.New(x, y, d, usage: CngKeyUsages.KeyAgreement);
var publicKey = EccKey.New(x, y, usage: CngKeyUsages.KeyAgreement);

string strU = new string('U', 400000000);
string strUU = new string('U', 100000000);
string payload = $@"{{""U"":""{strU}"", ""UU"":""{strUU}""}}";
string bomb = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.ECDH_ES, JweEncryption.A128GCM, JweCompression.DEF);

// when
try
{
string decoded = Jose.JWT.Decode(bomb, privateKey);
Assert.Fail("Should fail with NotSupportedException");
}
catch (JoseException e)
{
Console.Out.WriteLine(e.ToString());
}
}
}
}
4 changes: 3 additions & 1 deletion UnitTestsNet40/SettingsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,9 @@ class MockKeyManagement : DirectKeyManagement, IKeyManagement
}

class MockCompression : DeflateCompression, ICompression
{
{
public MockCompression(): base(250*1024) {}

public bool CompressCalled { get; set; }
public bool DecompressCalled { get; set; }

Expand Down
13 changes: 13 additions & 0 deletions UnitTestsNet46/ArraysTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,5 +126,18 @@ public void RightmostBits()
Assert.Equal(new byte[] { 8, 9 }, Arrays.RightmostBits(data, 16));
Assert.Equal(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, Arrays.RightmostBits(data, 72));
}

[Fact]
public void Truncate()
{
// given
byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

// then
Assert.Equal(new byte[] {}, Arrays.Truncate(data, 0));
Assert.Equal(new byte[] { 0 }, Arrays.Truncate(data, 1));
Assert.Equal(new byte[] { 0, 1, 2, 3, 4 }, Arrays.Truncate(data, 5));
Assert.Equal(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, Arrays.Truncate(data, 10));
}
}
}
37 changes: 37 additions & 0 deletions UnitTestsNet46/SecurityVulnerabilitiesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,5 +201,42 @@ public void BitLengthIntegerOverflow()
Console.Out.WriteLine(e.ToString());
}
}

[Fact]
public void DeflateBomb()
{
// given
Jwk privateKey = new Jwk(
e: "AQAB",
n: "qFZv0pea_jn5Mo4qEUmStuhlulso8n1inXbEotd_zTrQp9K0RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1MmnO_0N97dMBz_7fmvyv0hgHaBdQ5mR5u3LTlHo8tjRE7-GzZmGs6jMcyj7HbXobDPQJZpqNy6JjliDVXxW8nWJDetxGBlqmTj1E1fr2RCsZLreDOPSDIedG1upz9RraShsIDzeefOcKibcAaKeeVI3rkAU8_mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXIkhvNu_ve0v7LiLT4G_OxYGzpOQcCnimKdojzNP6GtVDaMPh-QkSJE32UCos9R3wI2Q",
p: "0qaOkT174vRG3E_67gU3lgOgoT6L3pVHuu7wfrIEoxycPa5_mZVG54SgvQUofGUYEGjR0lavUAjClw9tOzcODHX8RAxkuDntAFntBxgRM-IzAy8QzeRl_cbhgVjBTAhBcxg-3VySv5GdxFyrQaIo8Oy_PPI1L4EFKZHmicBd3ts",
q: "zJPqCDKqaJH9TAGfzt6b4aNt9fpirEcdpAF1bCedFfQmUZM0LG3rMtOAIhjEXgADt5GB8ZNK3BQl8BJyMmKs57oKmbVcODERCtPqjECXXsxH-az9nzxatPvcb7imFW8OlWslwr4IIRKdEjzEYs4syQJz7k2ktqOpYI5_UfYnw1s",
d: "lJhwb0pKlB2ivyDFO6thajotClrMA3nxIiSkIUbvVr-TToFtha36gyF6w6e6YNXQXs4HhMRy1_b-nRQDk8G4_f5urd_q-pOn5u4KfmqN3Xw-lYD3ddi9qF0NLeTVUNVFASeP0FFqbPYfdNwD-LyvwjhtT_ggMOAw3mYvU5cBfz6-3uPdhl3CwQFCTgwOud_BA9p2MPMUHG82wMK_sNO1I0TYpjm7TnwNBwiKbMf-i5CKnuohgoYrEDYLeMg3f32eBljlCFNYaoCtT-mr1Ze0OTJND04vbfLotV-BBKulIpbOOSeVpKG7gJxZHmv7in7PE5_WzaxKFVoHW3wR6v_GzQ",
dp: "KTWmTGmf092AA1euOmRQ5IsfIIxQ5qGDn-FgsRh4acSOGE8L7WrTrTU4EOJyciuA0qz-50xIDbs4_j5pWx1BJVTrnhBin9vNLrVo9mtR6jmFS0ko226kOUpwEVLgtdQjobWLjtiuaMW-_Iw4gKWNptxZ6T1lBD8UWHaPiEFW2-M",
dq: "Jn0lqMkvemENEMG1eUw0c601wPOMoPD4SKTlnKWPTlQS6YISbNF5UKSuFLwoJa9HA8BifDrD-Mfpo1M1HPmnoilEWUrfwMqqdCkOlbiJQhKY8AZ16QGH50kDXhmVVa8BRWdVQWBTUzWXS5kXMaeskVzextTgymPcOAhXN-ph7MU",
qi: "sRAPigJpl8S_vsf1zhJTrHM97xRwuB26R6Tm-J8sKRPb7p5xxNlmOBBFvWmWxdto8dBElNlydSZan373yBLxzW-bZgVp-B2RKT1B3WhTYW_Vo5DLhWi84XMncJxH7avtxtF9yksaeKe0e2n3J6TTan53mDg4KF8U0OEO2ciqO9g"
);

Jwk publicKey = new Jwk(
e: "AQAB",
n: "qFZv0pea_jn5Mo4qEUmStuhlulso8n1inXbEotd_zTrQp9K0RK0hf7t0K4BjKVhaiqIam4tVVQvkmYeBeYr1MmnO_0N97dMBz_7fmvyv0hgHaBdQ5mR5u3LTlHo8tjRE7-GzZmGs6jMcyj7HbXobDPQJZpqNy6JjliDVXxW8nWJDetxGBlqmTj1E1fr2RCsZLreDOPSDIedG1upz9RraShsIDzeefOcKibcAaKeeVI3rkAU8_mOauLSXv37hlk0h6sStJb3qZQXyOUkVkjXIkhvNu_ve0v7LiLT4G_OxYGzpOQcCnimKdojzNP6GtVDaMPh-QkSJE32UCos9R3wI2Q"
);

string strU = new string('U', 400000000);
string strUU = new string('U', 100000000);
string payload = $@"{{""U"":""{strU}"", ""UU"":""{strUU}""}}";
string bomb = Jose.JWT.Encode(payload, publicKey, JweAlgorithm.RSA_OAEP, JweEncryption.A256GCM, JweCompression.DEF);

// when
try
{
string decoded = Jose.JWT.Decode(bomb, privateKey);
Assert.True(false, "Should fail with NotSupportedException");
}
catch (JoseException e)
{
Console.Out.WriteLine(e.ToString());
}
}
}
}
2 changes: 2 additions & 0 deletions UnitTestsNet46/SettingsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ class MockKeyManagement : DirectKeyManagement, IKeyManagement

class MockCompression : DeflateCompression, ICompression
{
public MockCompression(): base(250*1024) {}

public bool CompressCalled { get; set; }
public bool DecompressCalled { get; set; }

Expand Down
5 changes: 4 additions & 1 deletion jose-jwt/JWTSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@ public JwtSettings()

private readonly Dictionary<JweCompression, ICompression> compressionAlgorithms = new Dictionary<JweCompression, ICompression>
{
{ JweCompression.DEF, new DeflateCompression() }
{
// 250Kb limited decompression buffer
JweCompression.DEF, new DeflateCompression(250 * 1024)
}
};

private readonly Dictionary<JweCompression, string> jweCompressionHeaderValue = new Dictionary<JweCompression, string>
Expand Down
37 changes: 27 additions & 10 deletions jose-jwt/compression/DeflateCompression.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
using System;
using System.IO;
using System.IO.Compression;

namespace Jose
{
public class DeflateCompression : ICompression
{
private readonly long maxBufferSizeBytes;

public DeflateCompression(long maxBufferSizeBytes)
{
this.maxBufferSizeBytes = maxBufferSizeBytes;
}

public byte[] Compress(byte[] plainText)
{
using (MemoryStream output = new MemoryStream())
Expand All @@ -20,17 +28,26 @@ public byte[] Compress(byte[] plainText)

public byte[] Decompress(byte[] compressedText)
{
using (MemoryStream ms = new MemoryStream())
{
using (MemoryStream compressedStream = new MemoryStream(compressedText))
{
using (DeflateStream deflater = new DeflateStream(compressedStream, CompressionMode.Decompress))
{
deflater.CopyTo(ms);
}
}
byte[] buffer = new byte[maxBufferSizeBytes];

return ms.ToArray();
try
{
using (MemoryStream ms = new MemoryStream(buffer))
{
using (MemoryStream compressedStream = new MemoryStream(compressedText))
{
using (DeflateStream deflater = new DeflateStream(compressedStream, CompressionMode.Decompress))
{
deflater.CopyTo(ms);
}
}

return Arrays.Truncate(ms.ToArray(), ms.Position);
}
}
catch(NotSupportedException e)
{
throw new JoseException("Unable to deflate compressed payload, most likely exceeded decompression buffer size.", e);
}
}
}
Expand Down
1 change: 0 additions & 1 deletion jose-jwt/jose-jwt.net40.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
<Compile Include="JwtOptions.cs" />
<Compile Include="JwtSettings.cs" />
<Compile Include="keys\EccKey.cs" />
<Compile Include="keys\EccKeyUnix.cs" />
<Compile Include="keys\RsaKey.cs" />
<Compile Include="native\BCrypt.cs" />
<Compile Include="native\NCrypt.cs" />
Expand Down
15 changes: 15 additions & 0 deletions jose-jwt/util/Arrays.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,5 +199,20 @@ public static byte[] RightmostBits(byte[] data, int lengthBits)

return result;
}

public static byte[] Truncate(byte[] data, long size)
{
Ensure.MinValue(size, 0, "Truncate() can't go negative size, but was given {0}", size);
Ensure.MaxValue(size, data.Length, "Truncate() can't go beyond array size {0}, but was given {1}", data.Length, size);
Ensure.MaxValue(size, Int32.MaxValue, "Truncate() can't go beyond int32, but was given {0}", size);

int byteCount = Convert.ToInt32(size);

var result = new byte[byteCount];

Buffer.BlockCopy(data, 0, result, 0, byteCount);

return result;
}
}
}
2 changes: 1 addition & 1 deletion jose-jwt/util/Ensure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static void MinValue(long arg, long min, string msg, params object[] args
throw new ArgumentException(string.Format(msg,args));
}

public static void MaxValue(int arg, long max, string msg, params object[] args)
public static void MaxValue(long arg, long max, string msg, params object[] args)
{
if(arg > max)
throw new ArgumentException(string.Format(msg,args));
Expand Down
Loading