Securing client side json - c#

I am new in Windows store apps development. I am creating a Windows Store App which requires to store some data on client side. This data is present in JSON format having Build Action as Content. Whenever user runs the application, I am initializing some objects by reading this JSON file. However this is just a plain text and contains data that should not be revealed to the user. Can I encrypt this JSON by any means. I need basically a workaround where I encrypt the json data while building the application and decrypt this json while reading and initializing the objects. Please suggest.

I'm assuming your code looks like this:
string json = File.ReadAllText("/<path to json>/config.json");
// Parse the json ...
You can encrypt the content of the JSON file using AES encryption.
You will need to define a key that will be used for encryption and decryption.
Take a look in here : using AES encrypt / decrypt in c#
After using encryption your code will look like this:
when you need to read your configuration:
string encryptedJson = File.ReadAllText("/<path to json>/config.json");
string aesKey = "<your aes key>";
string plainJson = AesDecrypt(encryptedJson, aesKey);
// Parse the json ...
When you need save the configuration:
// Generate json ...
string plainJson;
string aesKey = "<your aes key>";
string encryptedJson = AesEncrypt(plainJson, aesKey);
File.WriteAllText("/<path to json>/config.json", encryptedJson);
Note that your key can be extracted from your compiled assemblies using reflection methods

Related

Trouble authenticating with SshUserKeyCredentials in libgit2sharp-SSH

Having some trouble authenticating with SshUserKeyCredentials using libgit2sharp-SSH:
var co = new CloneOptions();
co.CredentialsProvider = (_url, _user, _cred) => new SshUserKeyCredentials { PrivateKey="C:\\path\\to\\private_key" };
Repository.Clone("git#... .repository.git", path, co);
I found the SshUserKeyCredentials object browsing through the source code so my first question would be if it is possible to use this object to do deploy key based checkout from gitlab?
The object seems to want any combination of PrivateKey, Username, PublicKey and Passphrase. I'm currently using a PrivateKey.
The error I end up with:
{"Failed to start SSH session: Unable to exchange encryption keys"}
If this way isn't supposed to work is there an alternative way of using deploy keys to programmatically manage git from an C# environment?
I was able to figure out the following through trial-and-error and scouring the web.
You cannot have null for any field; use string.Empty.
Public and private key must be provided and in the proper format.
Private key had to be in PEM format (either use PuttyGen Conversion menu => Export OpenSSH or use openssl rsa -in id_rsa -out id_rsa.pem).
Public key had to be single line, starting with type, followed by base64 key, no comment at the end (this is the format shown in the public key text box on PuttyGen, except you have to remove the comment), e.g.
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAoblahblahblahblahblah
I added username git because that's what Bitbucket requires. Not sure you need that, but it can't be null, do string.Empty.
Example:
CredentialsHandler handler = (_url, _user, _cred) => new SshUserKeyCredentials
{
PrivateKey = #"C:\Users\blah\.ssh\keys\bitbucket.pem",
Username = "git",
Passphrase = string.Empty,
PublicKey = #"C:\Users\blah\.ssh\keys\bitbucket.pub"
}
See also:
PHP ssh2_auth_pubkey_file(): Authentication failed using public key: Invalid key data, not base64 encoded

Encrypt with RSACryptoServiceProvider and public key string on Windows Mobile 6

my Windows Mobile 6 application needs to send data to a php REST web service of a company.
that WS has a method that returns the public key to use to encrypt the username and password of the user of the mobile application.
They give me a sample code written in php which simply calls the WS to obtain the public key and then calls openssl_public_encrypt with, as public key parameter, the value returned by the web service's call. This is an excerpt
function CallAPI($url, $data = false)
{
$curl = curl_init();
$url = sprintf("%s?%s", $url, http_build_query($data));
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
return curl_exec($curl);
}
$public_key=CallAPI(, "https://***.***.***/index.php/rest/getPKey");
$json = json_encode(array("username"=>"********","psw"=>"*******"));
openssl_public_encrypt($json, $encrypted, $public_key);
From Windows Mobile point of view seems to be more complicated than this, also I am not really into RSA encryption.
the first thing I do is to call the WS to obtain the public key and I save it into a string. The following is the code I use to encrypt data.
ASCIIEncoding ByteConverter = new ASCIIEncoding();
byte[] dataToEncrypt = ByteConverter.GetBytes(data_string);
byte[] public_key = ByteConverter.GetBytes(public_key_string);
byte[] encryptedData;
RSACryptoServiceProvider RSA_provider = new RSACryptoServiceProvider();
RSAParameters key_info = RSA_provider.ExportParameters(false);
key_info.Modulus = public_key;
RSA_provider.ImportParameters(key_info);
encryptedData = RSA_provider.Encrypt(dataToEncrypt, false);
string encrypted_string = ByteConverter.GetString(encryptedData, 0, encryptedData.Length);
return encrypted_string;
If I try to send data to the web service it fails due to an authentication failure, also I noted that from php code that the encrypted string is always of 256 chars, while the .NET encrypted string has completely different length.
What I'm doing wrong?
I have seen a lot of questions on StackOverflow about working with .NET and RSA Encryption, but the features that are used are not contained in the Compact Framework.
Thank you in advance.
I've solved using BouncyCastle API for ecnryption/decryption on .NET side and sending data between Windows Mobile client and PHP server using UrlEncode and replacing all '+'s in the UrlEncoded string with a custom string known from both the client and the server, I decided for "####".

Best practice for encrypting on the client

I am currently using a web API that allows an "Encryption" option.
I can setup my account to have a "shared key", and using this key i should encrypt all data on the client before submitting to the server.
Details from their website:
Encryption Algorithm: DES
Block Mode: ECB
Padding: PKCS7 or PKCS5
(they are interchangeable)
"Shared key" in this meaning i believe is a symmetric algorithm - same key used to decrypt/encrypt, although i may be wrong on this one.
I would like to know what is the best practice of handling this scenario on the client side?
If my application's logic should be using this key to encrypt data, how is it safe from a hacker ?
Note that my app is written in C#, meaning it can be decompiled practically for free.
Unless your key is compromised, then the transmission of your data is safe – anyone eavesdropping on your client–server connection would not be able to decrypt your data unless they have your key.
Your main challenge lies in the secure storage of the key locally on both the client and the server. For this end, I would suggest looking into the Windows Data Protection API (DPAPI) exposed through the ProtectedData class in .NET.
If shared key means public key then you are, most probaly, using one of the algorithms known as asymmetric encryption. This way you are safe to hacker since public key can't be used to decrypt data.
If it's symmetric then all depends on how secure key is. You can store it separately from a program (so user can store it securely on a flash drive). So each user must have it's own key, it's not possible to use one symmetric key for all.
In this manner, client will encrypt the data with different key and server will decrypt with different key. This is called asymmetric encryption/decryption.
The .NET Framework provides the RSACryptoServiceProvider and DSACryptoServiceProvider classes for asymmetric encryption. These classes create a public/private key pair when you use the default constructor to create a new instance. Asymmetric keys can be either stored for use in multiple sessions or generated for one session only. While the public key can be made generally available, the private key should be closely guarded.
For example [VB.NET]:
Dim cspParam as CspParameters = new CspParameters()
cspParam.Flags = CspProviderFlags.UseMachineKeyStore
Dim RSA As System.Security.Cryptography.RSACryptoServiceProvider
= New System.Security.Cryptography.RSACryptoServiceProvider(cspParam)
The key information from the cspParam object above can be saved via:
Dim publicKey as String = RSA.ToXmlString(False) ' gets the public key
Dim privateKey as String = RSA.ToXmlString(True) ' gets the private key
The above methods enable you to convert the public and / or private keys to Xml Strings.
And of course, as you would guess, there is a corresponding FromXmlString method to get them back.
So to encrypt some data with the Public key. The no-parameter constructor is used as we are loading our keys from XML and
do not need to create a new cspParams object:
Dim str as String = "HelloThere"
Dim RSA2 As RSACryptoServiceProvider = New RSACryptoServiceProvider()
' ---Load the private key---
RSA2.FromXmlString(privateKey)
Dim EncryptedStrAsByt() As Byte =RSA2.Encrypt(System.Text.Encoding.Unicode.GetBytes(str),False)
Dim EncryptedStrAsString = System.Text.Encoding.Unicode.GetString(EncryptedStrAsByt)
and as a "proof of concept", to DECRYPT the same data, but now using the Public key:
Dim RSA3 As RSACryptoServiceProvider = New RSACryptoServiceProvider(cspParam)
'---Load the Public key---
RSA3.FromXmlString(publicKey)
Dim DecryptedStrAsByt() As Byte =RSA3.Decrypt(System.Text.Encoding.Unicode.GetBytes(EncryptedStrAsString), False)
Dim DecryptedStrAsString = System.Text.Encoding.Unicode.GetString(DecryptedStrAsByt)

Loading the Jira Public Certificate in .Net from a string (how to convert ASN.1 encoded SubjectPublicKeyInfo to X509 Cert in .Net)

I am building an oauth 1.0a service that will be consumed by a gadget within Jira, it's a .Net 3.5 Application written in C#.
Jira makes requests to this service using the RSA-SHA1 signature method, which means to verify the signature of the request I need create an X509Certificate instance form their public cert.
Within the Jira application you can get the public cert by going to the consumer info screen (which also has the consumer key for Jira etc.) and it presents the public key in this format:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCObJRTGSZbAo
jRkvKmm0cwFXnKcPMfR4t/sghvLe/+QVs6TJOz5cUh5UokSqyz
VeMsL0jomP18ZcR3SPcIFT7xtOGQjLwLk7ghfYSsxjTGs9VxsC
/PQk5OQRP3v43IxFNF3M2SYhFWJZTOnqrab5AsMh2Kxdv+D69D
CINXCu5ltQIDAQAB
Looking at the Jira code which generates this key I can see it's (supposedly) PEM encoded without the BEGIN/END certificate header/footer.
RSAKeys.toPemEncoding(consumer.getPublicKey())
RSAKeys is an open source class found here:
https://studio.atlassian.com/source/browse/OAUTH/trunk/api/src/main/java/com/atlassian/oauth/util/RSAKeys.java?r=HEAD
I wish to load this public cert (key) into an X509Certificate instance within .Net, but my attempts so far have failed. Here's the code I have:
static readonly Regex stripRegex = new Regex("-----[A-Z ]*-----");
public string ConvertFromOpenSsl(string key)
{
return stripRegex.Replace(key, "").Replace("\r", "").Replace("\n", "");
}
public X509Certificate2 GetConsumerCertificate(IConsumer consumer)
{
string cert =
#"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCObJRTGSZbAo
jRkvKmm0cwFXnKcPMfR4t/sghvLe/+QVs6TJOz5cUh5UokSqyz
VeMsL0jomP18ZcR3SPcIFT7xtOGQjLwLk7ghfYSsxjTGs9VxsC
/PQk5OQRP3v43IxFNF3M2SYhFWJZTOnqrab5AsMh2Kxdv+D69D
CINXCu5ltQIDAQAB";
string converted = ConvertFromOpenSsl(cert);
var bytes = Convert.FromBase64String(converted);
var cert = new X509Certificate2(bytes); // throws here
But on the last line of code I have an exception thrown:
System.Security.Cryptography.CryptographicException: Cannot find the requested object.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._QueryCertBlobType(Byte[] rawData)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate..ctor(Byte[] data)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData)
I'm pretty sure I am missing something elementary, but I can think what it is.
UPDATE
OK, on further investigation it appears that this is a SubjectPublicKeyInfo serialization of the public key, so it's ASN.1, base 64 encoded (162 bytes unencoded), which is the default output from Java using java.security.PublicKey.getEncoded().
So given all that - is there any easy way to create an X509Certificate2 instance wrapping this public key - or is additional metadata required beyond the public key to create an x509Certificate2 instance?
Jira should provide you with a Certificate (not just a public key).
Typically the Java world will give a base64 encoded or PEM certificate. X509Certificate2 from .Net can automatically .Load a base64, PEM or binary certificate.
you can generate your XML RSA certificate via .NET using RSACryptoServiceProvider. This will give you XML (FromXmlString method), the public key then needs to be encoded, for example by using this service:
https://superdry.apphb.com/tools/online-rsa-key-converter
and then used to create application link to JIRA.
The private key in XML form you got previously, can be used for signing .NET app requests directly.
I personally used DonNetAuth library for signing, exchannging tokens, etc and it works for me. The only bug I encountered was regarding jql queries, where the signing needed a bit of tweaking to work correctly. Here is the link:
http://samondotnet.blogspot.sk/2012/12/introduction-to-dotnetauth.html
Additionally see this link:
https://answers.atlassian.com/questions/172760/is-there-any-jira-oauth-implementation-example-in-net
Hope this helps.

How do I decrypt RSA data in C#.NET appropriately?

My server creates a RSACryptoServiceProvider and exports its parameters to a variable (RSAKeyInfo).
Then, the public key is sent to the client, and the client encrypts something with that public key.
Now, I need to be able to decrypt this very data when sent back to the server - hence why RSA is useful in my case.
However, I get a "Bad Data" exception when trying to recreate a RSACryptoServiceProvider with imported parameters from the first RSACryptoServiceProvider created previously.
... Code might be clearer.
Creating the crypto:
class Cryptograph
{
public Cryptograph()
{
this.RSAKeyInfo = new RSACryptoServiceProvider(2048, new CspParameters(1)).ExportParameters(true);
}
}
Accessing it later for decryption:
byte[] encrypted = ...;
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(this.Cryptograph.RSAKeyInfo);
byte[] decrypted = rsa.Decrypt(encrypted, false);
Console.WriteLine(Utilities.ByteArrayToHexString(decrypted));
I get the "Bad Data" exception at this line:
byte[] decrypted = rsa.Decrypt(encrypted, false);
What am I doing wrong? How can I do it properly?
Thank you :)
P.S.: Please don't send MSDN or obvious Google results links, I've read all these pages and still can't get it to work.
When something is encrypted with a public key, you need to use the private key for the decryption. I don't see where you are using the private key for decryption.
I realize you have already read this, but you may want to read the Encrypt page and this Decrypt page, and make certain that you are following the steps:
http://msdn.microsoft.com/en-us/library/te15te69.aspx
Unless you are encrypting very short messages, such as a password, RSA encryption should generally be used for encrypting a symmetric key, which is faster to encrypt/decrypt longer messages.
The size of what you can encrypt with a public key is tied to the length of the key.
I needed an encryption/decryption that used no padding, and C#.NET doesn't provide it by default. OpenSSL.NET will do the job, however, I'm stuck while trying to use it. (See this question if you want to help me make it work). :(

Categories