11

I need to encrypt a string and then be able to decrypt it again.

I implemented the solution here and it works well, but the resulting string is not suitable as it needs to be simple and short enough for a user to use.

I am encrypting incrementing database ID's (from 1) and there won't be more than 500. Ideally I'd like the encrypted string to be not more than 6 characters in length.

Any ideas appreciated..

edit: It's a lengthy form which the user can resume at a later date with this generated string

Community
  • 1
  • 1
notAnonymousAnymore
  • 2,637
  • 9
  • 49
  • 74
  • 5
    Are you sure you want to encrypt and not compress? What you describe actually sounds like hashing. Can you explain the use case more? – Oded Nov 08 '12 at 19:47
  • So whats your question again? Why are you trying to limit the encrypted string to 6 characters? You shouldn't even need to encrypt the string, you could actually hash it, and just keep a 1-1 relationship stored in memory. – Security Hound Nov 08 '12 at 19:49
  • Why are you encrypting incrementing database IDs? Could you just hash them? – Bradley Thomas Nov 08 '12 at 19:50
  • 2
    It sounds like you really want a hash rather than an encryption. You can't decrypt hashes, though. – Steve Danner Nov 08 '12 at 19:50
  • 3
    XY problem. If we had more understanding of the underlying WHY we could provide better answers. – Bradley Thomas Nov 08 '12 at 19:51

4 Answers4

8

You can use AES in CTR mode without any padding. In this mode there is a counter that is encrypted and then the result is xor'd with your plaintext which is the number. The result should be small and you will get the encryption of AES which will be better than any substitution cipher you use (which you could probably break by hand). You will have to get the BouncyCastle crypto library however as the Microsoft implementation of Rijndael does not have CTR as an available mode. Below is an example of the AES class you would need to implement. As well as an example of encryption and decryption.

using System;
using System.Text;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

public class AES
{
    private readonly Encoding encoding;

    private SicBlockCipher mode;


    public AES(Encoding encoding)
    {
        this.encoding = encoding;
        this.mode = new SicBlockCipher(new AesFastEngine());
    }

    public static string ByteArrayToString(byte[] bytes)
    {
        return BitConverter.ToString(bytes).Replace("-", string.Empty);
    }

    public static byte[] StringToByteArray(string hex)
    {
        int numberChars = hex.Length;
        byte[] bytes = new byte[numberChars / 2];

        for (int i = 0; i < numberChars; i += 2)
        {
            bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
        }

        return bytes;
    }


    public string Encrypt(string plain, byte[] key, byte[] iv)
    {
        byte[] input = this.encoding.GetBytes(plain);

        byte[] bytes = this.BouncyCastleCrypto(true, input, key, iv);

        string result = ByteArrayToString(bytes);

        return result;
    }


    public string Decrypt(string cipher, byte[] key, byte[] iv)
    {
        byte[] bytes = this.BouncyCastleCrypto(false, StringToByteArray(cipher), key, iv);

        string result = this.encoding.GetString(bytes);

        return result;
    }


    private byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, byte[] key, byte[] iv)
    {
        try
        {
            this.mode.Init(forEncrypt, new ParametersWithIV(new KeyParameter(key), iv));

            BufferedBlockCipher cipher = new BufferedBlockCipher(this.mode);

            return cipher.DoFinal(input);
        }
        catch (CryptoException)
        {
            throw;
        }
    }
}

Example Usage

string test = "1";

AES aes = new AES(System.Text.Encoding.UTF8);

RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
byte[] key = new byte[32];
byte[] iv = new byte[32];

// Generate random key and IV
rngCsp.GetBytes(key);
rngCsp.GetBytes(iv);

string cipher = aes.Encrypt(test, key, iv);

string plaintext = aes.Decrypt(cipher, key, iv);

Response.Write(cipher + "<BR/>");

Response.Write(plaintext);

Output Example

CB
1 
nerdybeardo
  • 4,655
  • 23
  • 32
3
//encryption   
string output="";   
char[] readChar = yourInput.ToCharArray();   
for (int i = 0; i < readChar.Length; i++)  
{   
    int no = Convert.ToInt32(readChar[i]) + 10;   
    string r = Convert.ToChar(no).ToString();   
    output+=r;   
}  
//decryption  
string output="";   
char[] readChar = yourInput.ToCharArray();   
for (int i = 0; i < readChar.Length; i++)   
{   
    int no = Convert.ToInt32(readChar[i]) - 10;   
    string r = Convert.ToChar(no).ToString();   
    output+=r;   
}
Tapas Pal
  • 7,073
  • 8
  • 39
  • 86
1

if you want it to be simple maybe use a main key of 6 letter add it to the 6 letters input do a modulo based on the allowed input chars

its like a =1

b =2

c = 3

and then simply add a number a + 13 mod 24 > ...

wont say its secure but its simple as you requested You might also do some combinations like for the next char is deoded prev char as +xx

user613326
  • 2,140
  • 9
  • 34
  • 63
0

Since you said that these are database IDs that are incrementing I'm assuming we're talking about positive integers. Limiting encryption is really not a good idea because the more limited your encryption is the easier it becomes to break. I'm not sure of your goal but it sounds like you may want to simply hide the ID from the end user by "encrypting it". So, if my assumption about these being positive whole integers between 1 and 999 then my suggestions are as follows. One, a simple character substitution. It will be pretty easy to figure out since you'll be limited to 10 characters. Two, convert them to hexidecimal. Won't fool a lot of people but the average end user might not recognize it. Third, convert the number to Base64. This won't be recognized as easily as hexidecimal. Last, come up with some sort of formula you can apply to the number that will always yield a unique result. I really don't advise that however because it's pretty difficult.

Leon Newswanger
  • 617
  • 1
  • 5
  • 17