Skip to content

Commit

Permalink
Reorder tests by popular use-case first and add LargeMessages test
Browse files Browse the repository at this point in the history
  • Loading branch information
mythz committed Jul 19, 2015
1 parent 910d009 commit 703ce53
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 147 deletions.
Expand Up @@ -68,153 +68,6 @@ public void TestFixtureTearDown()
}

protected abstract IJsonServiceClient CreateClient();

[Test]
public void Can_Send_Encrypted_Message()
{
var client = CreateClient();

var request = new HelloSecure { Name = "World" };

byte[] cryptKey, authKey, iv;
AesUtils.CreateCryptAuthKeysAndIv(out cryptKey, out authKey, out iv);

var cryptAuthKeys = cryptKey.Combine(authKey);

var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml);
var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv);

var timestamp = DateTime.UtcNow.ToUnixTime();
var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson();

var encryptedBytes = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv);
var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv);

var encryptedMessage = new EncryptedMessage
{
EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys),
EncryptedBody = Convert.ToBase64String(authEncryptedBytes),
};

var encResponse = client.Post(encryptedMessage);

authEncryptedBytes = Convert.FromBase64String(encResponse.EncryptedBody);

if (!HmacUtils.Verify(authEncryptedBytes, authKey))
throw new Exception("Invalid EncryptedBody");

var decryptedBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);

var responseJson = decryptedBytes.FromUtf8Bytes();
var response = responseJson.FromJson<HelloSecureResponse>();

Assert.That(response.Result, Is.EqualTo("Hello, World!"));
}

[Test]
public void Does_throw_on_old_messages()
{
var client = CreateClient();

var request = new HelloSecure { Name = "World" };

byte[] cryptKey, authKey, iv;
AesUtils.CreateCryptAuthKeysAndIv(out cryptKey, out authKey, out iv);

var cryptAuthKeys = cryptKey.Combine(authKey);

var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml);
var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv);

var timestamp = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(21)).ToUnixTime();

var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson();

var encryptedBytes = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv);
var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv);

try
{
var encryptedMessage = new EncryptedMessage
{
EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys),
EncryptedBody = Convert.ToBase64String(authEncryptedBytes),
};
var encResponse = client.Post(encryptedMessage);

Assert.Fail("Should throw");
}
catch (WebServiceException ex)
{
ex.StatusDescription.Print();

var errorResponse = (EncryptedMessageResponse)ex.ResponseDto;

authEncryptedBytes = Convert.FromBase64String(errorResponse.EncryptedBody);
if (!HmacUtils.Verify(authEncryptedBytes, authKey))
throw new Exception("EncryptedBody is Invalid");

var responseBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);
var responseJson = responseBytes.FromUtf8Bytes();
var response = responseJson.FromJson<ErrorResponse>();
Assert.That(response.ResponseStatus.Message, Is.EqualTo("Request too old"));
}
}

[Test]
public void Does_throw_on_replayed_messages()
{
var client = CreateClient();

var request = new HelloSecure { Name = "World" };

byte[] cryptKey, iv;
AesUtils.CreateKeyAndIv(out cryptKey, out iv);

byte[] authKey = AesUtils.CreateKey();

var cryptAuthKeys = cryptKey.Combine(authKey);

var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml);
var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv);

var timestamp = DateTime.UtcNow.ToUnixTime();
var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson();

var encryptedBytes = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv);
var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv);

var encryptedMessage = new EncryptedMessage
{
EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys),
EncryptedBody = Convert.ToBase64String(authEncryptedBytes),
};

var encResponse = client.Post(encryptedMessage);

try
{
client.Post(encryptedMessage);

Assert.Fail("Should throw");
}
catch (WebServiceException ex)
{
ex.StatusDescription.Print();

var errorResponse = (EncryptedMessageResponse)ex.ResponseDto;

authEncryptedBytes = Convert.FromBase64String(errorResponse.EncryptedBody);
if (!HmacUtils.Verify(authEncryptedBytes, authKey))
throw new Exception("EncryptedBody is Invalid");

var responseBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);
var responseJson = responseBytes.FromUtf8Bytes();
var response = responseJson.FromJson<ErrorResponse>();
Assert.That(response.ResponseStatus.Message, Is.EqualTo("Nonce already seen"));
}
}

[Test]
public void Can_Send_Encrypted_Message_with_ServiceClients()
{
Expand Down Expand Up @@ -372,6 +225,21 @@ public void Can_call_GET_only_Services()
Assert.That(response.Result, Is.EqualTo("Hello, World!"));
}

[Test]
public void Can_send_large_messages()
{
var client = CreateClient();
IEncryptedClient encryptedClient = client.GetEncryptedClient(client.Get<string>("/publickey"));

var request = new LargeMessage {
Messages = 100.Times(i => new HelloSecure {Name = "Name" + i})
};

var response = encryptedClient.Send(request);

Assert.That(response.Messages.Count, Is.EqualTo(request.Messages.Count));
}

[Test]
public void Can_send_auto_batched_requests()
{
Expand All @@ -386,6 +254,152 @@ public void Can_send_auto_batched_requests()

Assert.That(responseNames, Is.EqualTo(names.Map(x => "Hello, {0}!".Fmt(x))));
}

[Test]
public void Can_Send_Encrypted_Message()
{
var client = CreateClient();

var request = new HelloSecure { Name = "World" };

byte[] cryptKey, authKey, iv;
AesUtils.CreateCryptAuthKeysAndIv(out cryptKey, out authKey, out iv);

var cryptAuthKeys = cryptKey.Combine(authKey);

var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml);
var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv);

var timestamp = DateTime.UtcNow.ToUnixTime();
var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson();

var encryptedBytes = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv);
var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv);

var encryptedMessage = new EncryptedMessage
{
EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys),
EncryptedBody = Convert.ToBase64String(authEncryptedBytes),
};

var encResponse = client.Post(encryptedMessage);

authEncryptedBytes = Convert.FromBase64String(encResponse.EncryptedBody);

if (!HmacUtils.Verify(authEncryptedBytes, authKey))
throw new Exception("Invalid EncryptedBody");

var decryptedBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);

var responseJson = decryptedBytes.FromUtf8Bytes();
var response = responseJson.FromJson<HelloSecureResponse>();

Assert.That(response.Result, Is.EqualTo("Hello, World!"));
}

[Test]
public void Does_throw_on_old_messages()
{
var client = CreateClient();

var request = new HelloSecure { Name = "World" };

byte[] cryptKey, authKey, iv;
AesUtils.CreateCryptAuthKeysAndIv(out cryptKey, out authKey, out iv);

var cryptAuthKeys = cryptKey.Combine(authKey);

var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml);
var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv);

var timestamp = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(21)).ToUnixTime();

var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson();

var encryptedBytes = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv);
var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv);

try
{
var encryptedMessage = new EncryptedMessage
{
EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys),
EncryptedBody = Convert.ToBase64String(authEncryptedBytes),
};
var encResponse = client.Post(encryptedMessage);

Assert.Fail("Should throw");
}
catch (WebServiceException ex)
{
ex.StatusDescription.Print();

var errorResponse = (EncryptedMessageResponse)ex.ResponseDto;

authEncryptedBytes = Convert.FromBase64String(errorResponse.EncryptedBody);
if (!HmacUtils.Verify(authEncryptedBytes, authKey))
throw new Exception("EncryptedBody is Invalid");

var responseBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);
var responseJson = responseBytes.FromUtf8Bytes();
var response = responseJson.FromJson<ErrorResponse>();
Assert.That(response.ResponseStatus.Message, Is.EqualTo("Request too old"));
}
}

[Test]
public void Does_throw_on_replayed_messages()
{
var client = CreateClient();

var request = new HelloSecure { Name = "World" };

byte[] cryptKey, iv;
AesUtils.CreateKeyAndIv(out cryptKey, out iv);

byte[] authKey = AesUtils.CreateKey();

var cryptAuthKeys = cryptKey.Combine(authKey);

var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml);
var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv);

var timestamp = DateTime.UtcNow.ToUnixTime();
var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson();

var encryptedBytes = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv);
var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv);

var encryptedMessage = new EncryptedMessage
{
EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys),
EncryptedBody = Convert.ToBase64String(authEncryptedBytes),
};

var encResponse = client.Post(encryptedMessage);

try
{
client.Post(encryptedMessage);

Assert.Fail("Should throw");
}
catch (WebServiceException ex)
{
ex.StatusDescription.Print();

var errorResponse = (EncryptedMessageResponse)ex.ResponseDto;

authEncryptedBytes = Convert.FromBase64String(errorResponse.EncryptedBody);
if (!HmacUtils.Verify(authEncryptedBytes, authKey))
throw new Exception("EncryptedBody is Invalid");

var responseBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey);
var responseJson = responseBytes.FromUtf8Bytes();
var response = responseJson.FromJson<ErrorResponse>();
Assert.That(response.ResponseStatus.Message, Is.EqualTo("Nonce already seen"));
}
}
}

public class CryptUtilsTests
Expand Down
Expand Up @@ -2,6 +2,7 @@
// License: https://raw.github.com/ServiceStack/ServiceStack/master/license.txt

using System;
using System.Collections.Generic;
using ServiceStack.Auth;

namespace ServiceStack.WebHost.Endpoints.Tests.UseCases
Expand Down Expand Up @@ -39,6 +40,11 @@ public class HelloAuthenticated : IReturn<HelloAuthenticatedResponse>, IHasSessi
public int Version { get; set; }
}

public class LargeMessage : IReturn<LargeMessage>
{
public List<HelloSecure> Messages { get; set; }
}

[Authenticate]
public class HelloAuthSecure : IReturn<HelloAuthSecureResponse>
{
Expand Down Expand Up @@ -100,5 +106,10 @@ public object Any(HelloAuthenticated request)
IsAuthenticated = session.IsAuthenticated,
};
}

public object Any(LargeMessage request)
{
return request;
}
}
}

0 comments on commit 703ce53

Please sign in to comment.