8

I need a simple algorithm to encrypt / decrypt a string. Something like Base64 but a little more secure. It is not mission critical. All I need is some string manipulation. Not as easy as copy the string and make it human readable using a simple base 64 decoder.

Why not using AES?

Since my app is created using .NET Core, it runs on windows and mac. The problem i am facing is that in order to use System.Security on mac, i need openssl to be installed. Since i dont have sudo access, i cant install it.

So here are the requirements:

  • Simple String Encryption
  • No Dependencies on System.Security.*

Ive read Simple insecure two-way "obfuscation" for C# but there is no solution without dependencies.

Community
  • 1
  • 1
dknaack
  • 60,192
  • 27
  • 155
  • 202
  • Why not implement some simple bitshifting and wrap the result in Base64? – lokusking Aug 07 '16 at 16:10
  • If you have such a solution feel free to post it as a answer. Thank you! – dknaack Aug 07 '16 at 16:12
  • Have you tested the managed version of the crypto implementations? Like, https://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged(v=vs.110).aspx. I would assume that they don't rely on external dependencies, however I'm not sure. – jishi Aug 07 '16 at 16:17
  • On a Mac you do not need openssl to be installed to e installed ignorer to use AES, use Common Crypto by including Security.framework. Common Crypto is just "C" code and uses whatever hardware encryption is available. – zaph Aug 07 '16 at 16:28

4 Answers4

27

If you are looking for obfuscation rather than security, you could XOR the string with a constant or the output of a PRNG initialized with a constant seed.

Example with constant:

byte xorConstant = 0x53;

string input = "foo";
byte[] data = Encoding.UTF8.GetBytes(input);
for (int i = 0; i < data.Length; i++)
{
    data[i] = (byte)(data[i] ^ xorConstant)
}
string output = Convert.ToBase64String(data);

To decode:

byte xorConstant = 0x53;
byte[] data = Convert.FromBase64String(input);
for (int i = 0; i < data.Length; i++)
{
    data[i] = (byte)(data[i] ^ xorConstant)
}
string plainText = Encoding.UTF8.GetString(data);
Ken Pespisa
  • 21,989
  • 3
  • 55
  • 63
Mitch
  • 21,223
  • 6
  • 63
  • 86
  • 1
    exactly what i wanted to post. dam you. +1. – Stavm Aug 07 '16 at 16:22
  • 1
    Here is the problem, if there is a string of 0's (or even one) the string constant will be immediately known. – zaph Aug 07 '16 at 16:27
  • @zaph, With any known plaintext the constant is known. That is why it is unquestionably unsecure. Further, there are only 256 possible keys, so you can brute force it trivially. It is not meant to be secure. – Mitch Aug 07 '16 at 16:28
  • Perhaps I an more tuned to this because a co-worker "encrypted" some data that had leading zeros, when I saw the output I immediately knew the key without even trying. – zaph Aug 07 '16 at 16:35
  • nice answer but the code has simem problems the solution is`for (int i = 0; i < data.Length; i++)` and `data[i] = (byte)(data[i] ^ xorConstant);` – Shady Mohamed Sherif Nov 24 '17 at 01:27
1

All the asymmetric and symmetric encryption methods reside in System.Security namespaces. From this SO answer:

The symmetric encryption options available in .NET Core are:

  • AES (System.Security.Cryptography.Aes.Create())
  • 3DES (System.Security.Cryptography.TripleDES.Create())

And for asymmetric encryption

  • RSA (System.Security.Cryptography.RSA.Create())

So it appears you will need System.Security at least.

EDIT: Here's a nice SO question with a ton of functions relating to encryption. Note extensive usage of System.Security namespace classes and methods.

Community
  • 1
  • 1
Nick Bull
  • 9,518
  • 6
  • 36
  • 58
  • I agree with this answer. In fact if you do not want to include `System.Security`, the only other option is implementing it yourself or copy-pasting the encryption method you want from said namespace. – Angelos Chalaris Aug 07 '16 at 16:12
  • @AngelosChalaris Exactly - in fact, OP, why can you not copy and paste in the code from a security library? Here's a bunch of functions from an SO answer: http://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp – Nick Bull Aug 07 '16 at 16:13
  • The problem is that these methods don't work on mac without openssl being installed. – dknaack Aug 07 '16 at 16:13
  • @dknaack *Why would you write an app for Mac in C# to begin with? Why not Java for example, which is better supported and much similar to C#?* You can always copy and alter the libraries from said namespaces, though, to work for Mac and it shouldn't be too much trouble. – Angelos Chalaris Aug 07 '16 at 16:20
1

Use XTEA, it is actually reasonably secure.

Below is the entire source code from Wikipedia:

#include <stdint.h>

/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */

void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
    for (i=0; i < num_rounds; i++) {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
    }
    v[0]=v0; v[1]=v1;
}

void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    for (i=0; i < num_rounds; i++) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0]=v0; v[1]=v1;
}
zaph
  • 111,848
  • 21
  • 189
  • 228
0

Something with BitShifting:

 var topSecret = "This is%&/(/ TopSecret 111!!";
 int shft = 5;
 string encrypted = topSecret.Select(ch => ((int) ch) << shft).Aggregate("", (current, val) => current + (char) (val*2));
 encrypted = Convert.ToBase64String(Encoding.UTF8.GetBytes(encrypted));
 string decrypted = Encoding.UTF8.GetString(Convert.FromBase64String(encrypted)).Select(ch => ((int) ch) >> shft).Aggregate("", (current, val) => current + (char) (val/2));

Encrypted:

4ZSA4aiA4amA4bOA4KCA4amA4bOA4KWA4KaA4K+A4KiA4K+A4KCA4ZSA4a+A4bCA4ZOA4aWA4aOA4bKA4aWA4bSA4KCA4LGA4LGA4LGA4KGA4KGA

Decrypted again:

This is%&/(/ TopSecret 111!!

Note

Not very pretty and very minimal. You can tweak the salts and Encodings to fit your needs.

Cheers

lokusking
  • 7,396
  • 13
  • 38
  • 57