-2

I have c++ code that encrypts a string as a plaintext using AES_CFB and generates a same size ciphertext, but the problem is the data type of input and output, So could anyone help me to let it encrypts an unsigned int number and generates unsigned int number ciphertext withe keeping the same length for the plaintext and chipertext (length of bits ).

string ENCRYPTOR(const std::string& PlainText)
{
    byte key[16]= "1234ff";//  byte key[ CryptoPP::AES::DEFAULT_KEYLENGTH ];
    byte iv[16]= "123456";//byte iv[ CryptoPP::AES::BLOCKSIZE ];

    std::string CipherText;

    // Encryptor
    CryptoPP::CFB_Mode< CryptoPP::AES >::Encryption encryptor( key, sizeof(key), iv);

    // Encryption
    CryptoPP::StringSource( PlainText, true,
        new CryptoPP::StreamTransformationFilter( encryptor,
            new CryptoPP::StringSink( CipherText ) ) ); 

    return (CipherText);
}

string DECRYPTOR(const string& CipherText)
{
    byte key[16]= "1234ff";
    byte iv[16]= "123456"; 

    std::string RecoveredText;

    // Decryptor
    CryptoPP::CFB_Mode< CryptoPP::AES >::Decryption decryptor( key, sizeof(key), iv );

    // Decryption
    CryptoPP::StringSource( CipherText, true,
        new CryptoPP::StreamTransformationFilter( decryptor,
            new CryptoPP::StringSink( RecoveredText ) ) ); 

    return (RecoveredText);
}

int main()
{
    string ciphertext;
    string plaintext = "3555";
    ciphertext= ENCRYPTOR(plaintext);
    string retrivdat = DECRYPTOR(ciphertext);

    cout<<"The plaintext data is:  "<<plaintext<<endl;
    cout<<"The ciphertextdata is:  "<<ciphertext<<endl;
    Coot<<"The retrieved data is:  "<<retrivdat<<end;

    return 0;
}

The output is

The plaintext data is:  3555
The chepertext data is:  ï¥R_
The retrieved data is:  3555
jww
  • 97,681
  • 90
  • 411
  • 885
MOH
  • 9
  • 1
    `CryptoPP::StringSource` has a constructor taking `const byte*` pointer to a buffer, and the length of that buffer. If you have `int x` to encrypt, just pass `(const byte*)&x` and `sizeof(x)`, correspondingly. – Igor Tandetnik Jan 04 '15 at 20:27
  • @IgorTandetnik With the remarks that 1) you can only encrypt bytes with most API's 2) according to the question, use `unsigned int` and 3) please make sure you use the same size `int` and same endianess on each machine 4) may not be the smallest encoding (but we don't know the minimum/maximum sizes) – Maarten Bodewes Jan 04 '15 at 20:38
  • Seems you have already succeeded in doing this (although first converting to a string seems non-optimal to me), what is your question? Do you require minimum bit size? Minimum size in bytes, some kind of maximum? – Maarten Bodewes Jan 04 '15 at 20:39
  • Thank you @Maarten and Igor. Actually I need to encrypt an integer PLAINTEXT value to an integer CHIPERTEXT value with same SIZE. For example the plaintext value is 453 (3 bytes) the CHIPERTEXT have to by any integer value with same SIZE (3 bytes). In other word the CHIPERTEXT SIZE have to be INTEGER and with same SIZE of PLAINTEXT value. – MOH Jan 05 '15 at 18:24

2 Answers2

0

Encrypt unsigned int value in form of bits stream by AES_CFB mode

Igor and Owlstead raised some valid points about size of integers and endianess. The easiest solution to avoid them is probably encode the integer as a string:

unsigned int n = ...;
ostringstream oss;

oss << n;

string plainText = oss.str();

Later, you can convert it back with:

string recovered = ...;
istringstream iss(recovered);

unsigned int n;
iss >> n;

byte key[16]= "1234ff";//  byte key[ CryptoPP::AES::DEFAULT_KEYLENGTH ];
byte iv[16]= "123456";//byte iv[ CryptoPP::AES::BLOCKSIZE ];

Your key and IV are too small. You should be getting compiler warnings because of it. AES::DEFAULT_KEYLENGTH is 16, so you need at least 16 characters for the key. AES::BLOCKSIZE is 16, so you need at least 16 characters for the initialization vector.

If the code above happens to work, then its purely because of luck. You should probably visit CFB Mode on the Crypto++ wiki. It has a working example.

Alternately, use PBKDF to stretch the short key and short IV. You can find an example at Crypto++ pbkdf2 output is different than Rfc2898DeriveBytes (C#) and crypto.pbkdf2 (JavaScript) on Stack Overflow.


The chepertext data is: ï¥R_

You can make this printable with:

string encoded;
HexEncoder hexer(new StringSink(encoded));

hexer.Put((byte*)cipherText.data(), cipherText.size());
hexer.MessageEnd();

cout << encoded << endl;

Alternately, you can use the following (with pipelines):

string encoded;

StringSource ss(cipherText, true,
    new HexEncoder(
        new StringSink(encoded)));

cout << encoded << endl;

HexEncoder and HexDecoder are discussed on the Crypto++ wiki, too.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • Thanks @jww, the cipherText [ï¥R_] length =3 bytes, so I am unable to get an integer number ciphertext with same size. – MOH Jan 05 '15 at 12:43
  • *"ï¥R_"* looks like 4 bytes to me. *"ï"*, *"¥"*, *"R"* and *"_"*. From where are you arriving at 3 bytes? – jww Jan 07 '15 at 00:27
  • Oh, sorry, you are right, it is 4 bytes. as you see the integer value 3555 =110111100011 (2 bytes) but its chipertext ï¥R_ (4 byte). Because it was treated as individual characters.if i change it to be integer plaintext i got wrong result – MOH Jan 07 '15 at 07:57
0

So you can:

  1. encode the number into the minimum number of x bytes, for instance using an unsigned big endian number
  2. encrypt with CFB, resulting in the same number of x bytes
  3. decrypt the number
  4. decode the number from the resulting x bytes (using the same encoding scheme of course)

If you want to see the ciphertext as number you'll have to decode the ciphertext as if it was a (signed or unsigned) number.

Note that you will still have to deal with the uniqueness of the IV. If you need to store the IV then there will be significant overhead.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • And if you are troubled by the IV, take a look at format preserving encryption. – Maarten Bodewes Jan 05 '15 at 23:23
  • Thanks @Maarten, I tried this, but the encoding and decoding process are generate a chipertext with longer size than the plaintext. also I concern about the computational overhead. – MOH Jan 06 '15 at 08:35
  • encode by this unsigned int n = ...; ostringstream oss; oss << n; string plainText = oss.str(); and decode it by string recovered = ...; istringstream iss(recovered); unsigned int n; iss >> n; – MOH Jan 06 '15 at 11:52
  • OK, so according to spec, the `<<` operator generates strings instead of encoding to bytes. Use e.g. [this answer](http://stackoverflow.com/q/5585532/589259) instead. – Maarten Bodewes Jan 06 '15 at 20:19