Problem :
Given an app that needs to exchange info such as ConsumerKey/ConsumerSecret for oAuth from
- server running "WebApi" over ServiceStack
- consumer is a desktop app
Looking to encrypt the messages using Public/Private keys which are already in place
Is there any support for encrypting/decrypting messages, hopefully transparently ? i.e. the encrypting/decryption is handled via say Filters on the server ?
OR
any workaround on how to do this ?
FYI – the server already requires SSL and requests are authenticated, however the registration is free/automated, hence the need for encryption
Solution :
Update
The Encrypted Messaging Feature released in v4.0.42 now enables a secure channel for all Services offering protection to clients who can now easily send and receive encrypted messages over unsecured HTTP.
There’s no published support for Message Level encryption built into the ServiceStack at the moment, although this is something we’re thinking of adding in the future. Below is an example of an approach you could try with ServiceStack today for exploratory purposes (it will require more R&D on your part to come up with a good solid design), and as this is an area that may change in future, it’s not a use-case we’re supporting right now, but here’s something that could work with ServiceStack as it is now:
class EncryptedRequest
{
//Name of the request type
public string Type { get; set; }
//Serialized Request DTO using something like JSON
public string EncryptedBody { get; set; }
//optional: let server the private key that was used (if multiple)
public string PrivateKeyMd5Hash { get; set; }
}
class EncryptedResponse
{
//Name of the response type
public string Type { get; set; }
//Serialized Response DTO
public string EncryptedBody { get; set; }
//optional
public string PublicKeyMd5Hash { get; set; }
}
Here is a convenient CryptUtils wrapper that makes it easy to create Public/Private keys as well as being able to Encrypt/Decrypt text using them.
Then you can have a single service, and do something like:
class EncryptedService : Service
{
const string PublicKey = ...;
const string PrivateKey = ...;
EncryptedResponse Any(EncryptedRequest request)
{
var requestType = Type.GetType("{0}.{1}"
.Fmt(typeof(EncryptedRequest).Namespace, request.Type));
var json = CryptUtils.Decrypt(PrivateKey, request.EncryptedBody);
var requestDto = JsonSerializer.DeserializeFromString(json,requestType);
var responseDto = GetAppHost().Config.ServiceController
.Execute(requestDto, base.RequestContext);
return new EncryptedResponse {
Type = responseDto.GetType().Name,
EncryptedBody = CryptUtils.Encrypt(PublicKey, responseDto.ToJson()),
};
}
}
The client would also need a copy of the Public/Private key pair which you would exchange out-of-band.