-1

I am trying to create a simple system that encrypts strings, converts the encrypted byte array to a string and stores it in the database. Later on, the values can be retrieved from the database (as strings), comverted to byte arrays, decrypted and then converted to strings again. I am also using a 256 bit key. However, I seem to be doing something wrong and I am not familiar enough with the concept to come up with a fix.

Encryption code:

private static string EncryptString(SymmetricAlgorithm symAlg, string inString)
{
    byte[] inBlock = Encoding.Unicode.GetBytes(inString);
    ICryptoTransform xfrm = symAlg.CreateEncryptor();
    return Convert.ToBase64String(xfrm.TransformFinalBlock(inBlock, 0, inBlock.Length));
}

Decryption code:

private static byte[] DecryptString(SymmetricAlgorithm symAlg, string inBytes)
{
    ICryptoTransform xfrm = symAlg.CreateDecryptor();
    return xfrm.TransformFinalBlock(Convert.FromBase64String(inBytes), 0, inBytes.Length);
}

The error I am getting when decrypting:

System.ArgumentOutOfRangeException: Attempt to transform beyond end of buffer.
Parameter name: inputCount
at
System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at
CDMEncryptionLibrary.SyncEncryption.SecureCDM.DecryptString(SymmetricAlgorithm symAlg, String inBytes)

I understand that the problem is the conversion from and to bytes but how can I solve it?

--Edit

Decryption code is now:

    private static string DecryptString(SymmetricAlgorithm symAlg, string inBytesString)
    {

        var inBytes = Convert.FromBase64String(inBytesString);
        ICryptoTransform xfrm = symAlg.CreateDecryptor();
        byte[] outBlock= xfrm.TransformFinalBlock(inBytes, 0, inBytes.Length);
        return Encoding.Unicode.GetString(outBlock);
    }

with error The input data is not a complete block.

MonicaS
  • 155
  • 1
  • 3
  • 18
  • @mjwills decryption. Will update the post. thanks – MonicaS Feb 13 '18 at 12:23
  • 1
    From where did you get the idea to call `TransformFinalBlock` before writing anything at all? – Camilo Terevinto Feb 13 '18 at 12:25
  • 4
    I guess the size of `inBytes` is not the same as the result of `Convert.FromBase64String(inBytes)`. – jAC Feb 13 '18 at 12:25
  • 1
    Possible duplicate of [Symmetric encrypt/decrypt in .NET](https://stackoverflow.com/questions/2150703/symmetric-encrypt-decrypt-in-net) – mjwills Feb 13 '18 at 12:27
  • 6
    Hint: naming a *string* parameter `inBytes` is causing you confusion. I'd suggest naming it something more textual, and if you *want* an `inBytes` variable, that would be `byte[] inBytes = Convert.FromBase64String(encryptedBase64);` or similar. – Jon Skeet Feb 13 '18 at 12:27
  • @CamiloTerevinto . https://msdn.microsoft.com/en-us/library/09d0kyb3(v=vs.110).aspx – MonicaS Feb 13 '18 at 12:27
  • 1
    Don't do `inBytes.Length` when decrypting. That's length of base64 encoded string in characters. You need `var bytes = Convert.FromBase64String(inBytes); xfrm.TransformFinalBlock(bytes, 0, bytes.Length);` – Evk Feb 13 '18 at 12:30

1 Answers1

3

You are passing the length of the String, not the length of the byte array you convert the String to.

I.e. You pass Convert.FromBase64String(inBytes) as the first parameter but inBytes.Length as the last. Simply convert before taking the length;

private static byte[] DecryptString(SymmetricAlgorithm symAlg, string inBytes)
{
    ICryptoTransform xfrm = symAlg.CreateDecryptor();
    return xfrm.TransformFinalBlock(Convert.FromBase64String(inBytes), 0, Convert.FromBase64String(inBytes).Length);
}

or to be more readable;

private static byte[] DecryptString(SymmetricAlgorithm symAlg, string inBytesString)
{
    var inBytes = Convert.FromBase64String(inBytesString);
    ICryptoTransform xfrm = symAlg.CreateDecryptor();
    return xfrm.TransformFinalBlock(inBytes, 0, inBytes.Length);
}
Milney
  • 6,253
  • 2
  • 19
  • 33
  • The input data is not a complete block after changed the Padding to none – MonicaS Feb 13 '18 at 12:37
  • @MonicaS another error is another question. And for that new question it's better to post complete example (which string you encrypt exactly, what `SymmetricAlgorithm` you pass with which parameters, and so on). – Evk Feb 13 '18 at 12:38
  • You should set the padding, as having padding as None means you need to manually pad... Some Algorithms are 'block' cyphers so need a block of a certain size... padding adjusts your input to be that size. Note: Padding must match on encryption and decrption – Milney Feb 13 '18 at 12:38
  • I believe the recommended padding is System.Security.Cryptography.PaddingMode.PKCS7 – Milney Feb 13 '18 at 12:39
  • @Milney whenever I change the padding to anything else than none I get the "Padding is invalid and cannot be removed" error. – MonicaS Feb 13 '18 at 12:41
  • @MonicaS Are you sure you are setting the same padding in the encrypt function as you use in decrypt? That would imply that you have not correctly padded the encrypted input so when trying to decrypt it cannot remove it – Milney Feb 13 '18 at 12:43
  • Are you sure the keys are the same for encryption and decryption as this can also cause this error – Milney Feb 13 '18 at 12:44
  • Yes. I'm using the same Aes object with the same properties for both encryption and decryption. – MonicaS Feb 13 '18 at 12:45