Padding is invalid and cannot be removed with Rijndael decryption - encryption

I am seeing the "Padding is invalid and cannot be removed" error when I call the method below to decrypt the string from a windows application. String was encrypted from an asp.net application. Both application references the same assembly. I am able encrypt and decrypt with out any problem from the asp.net application. Here is the main code where I do the encryption and decryption.
private static byte[] EncryptHelper(byte[] arrData, string Password, bool Encrypt)
{
//Create the SymetricAlgorithem object
SymmetricAlgorithm myAlg = new RijndaelManaged();
//define a salt value to derive the key.
byte[] salt = System.Text.Encoding.ASCII.GetBytes("hjkhj877ffasah");
//Instantiate Rfc2898DeriveBytes with the password and salt.
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(Password, salt);
myAlg.Key = key.GetBytes(myAlg.KeySize / 8);
myAlg.IV = key.GetBytes(myAlg.BlockSize / 8);
myAlg.Padding = PaddingMode.PKCS7;
//Create the ICryptoTransform Object
ICryptoTransform encrytptor = Encrypt ? myAlg.CreateEncryptor() : myAlg.CreateDecryptor();
//Create Memorystream to write the encrypted data
using (MemoryStream aStream = new MemoryStream())
{
//Create the CryptoStream Ojbect using the aStream object
using (CryptoStream encryptStream = new CryptoStream(aStream, encrytptor, CryptoStreamMode.Write))
{
//Write the contents to crypto stream
encryptStream.Write(arrData, 0, arrData.Length);
//Flush the cryptostream
encryptStream.FlushFinalBlock();
//Reposition the memorystream to write the contents to an array.
aStream.Position = 0;
}
aStream.Flush();
//Convert to an array and return
return aStream.ToArray();
}
}
This is the method I use to convert the plain text from/to byte array
private static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
private static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
For persist the cipher text to database I use Convert.ToBase64String() and Convert.FromBase64String. Is the problem is with the way I use Rfc2898DeriveBytes class?

Well I think it's important to mention that from a security perspective, you are going to have the same IV for every message with the same password, and a predictable IV is a really big no no.
After that point I kinda don't want to look at it more to see what's going wrong, there are a lot of really bad cut and paste C# encryption on stackoverflow, and they just sit there with no mechanism for update, no one looking at them again except for people finding them to cut and paste again.
Look at Modern Examples of Symmetric Authenticated Encryption of a string. c#.
I try to keep it up to date and reviewed.

Related

How do i store sensitive data (such as Database passwords) in an Oracle Database

Basically i'm building a WebApp (ASP.NET MVC5) working with Oracle Database. The application connects to multiple oracle databases and an admin should be able to dynamically add new database connections to the webapp.
The way we are doing it now, when an admin adds a new database via the admin panel, the database connection info is stored in our own Oracle Database (this includes the username and password to the database). These passwords are currently stored plaintext.
All the webapp would have to do is retrieve the database credentials from our own database, format them into a connection string and connect to the database.
The problem is, if we hash the passwords, they will not work in a connection string, nor would this add any security at all. All the encryption of these passwords should happen on the databas-side.
I found out about TDE (transparant data encryption) but i believe this is only available in the enterprise edition of Oracle Database and i do not have access to this. Is there any other way to securely store the database passwords? Am i missing something ?
You can simply encrypt the passwords and store it in the database. When a user changes the password or signs up for the first time, simply encrypt them. While checking for validation, encrypt the text box and check if two strings match.
And when you require to know the passwords, decrypt them.
A sample code for encryption looks like
// Encrypt the text
public static string EncryptText(string strText)
{
return Encrypt(strText, "a#94tOc*"); // use any string to encrypt other than a#94tOc*
}
//The function used to encrypt the text
private static string Encrypt(string strText, string strEncrKey)
{
byte[] byKey = { };
byte[] IV = { 0X12, 0X34, 0X56, 0X78, 0X90, 0XAB, 0XCD, 0XEF };
byKey = System.Text.Encoding.UTF8.GetBytes(strEncrKey.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
byte[] inputByteArray = System.Text.Encoding.UTF8.GetBytes(strText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byKey, IV), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
}
Similarly for decrypting, use:
//Decrypt the text
public static string DecryptText(string strText)
{
return Decrypt(strText, "a#94tOc*"); // use same as encryption string
}
//The function used to decrypt the text
private static string Decrypt(string strText, string sDecrKey)
{
byte[] byKey = { };
byte[] IV = { 0X12, 0X34, 0X56, 0X78, 0X90, 0XAB, 0XCD, 0XEF };
byte[] inputByteArray = new byte[strText.Length + 1];
byKey = System.Text.Encoding.UTF8.GetBytes(sDecrKey.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
inputByteArray = Convert.FromBase64String(strText.Replace(' ', '+'));
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(byKey, IV), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
return encoding.GetString(ms.ToArray());
}
So basically just call EncryptText(password) to encrypt and DecryptText(encrypted_password) to decrypt.

How can I read an encrypted text from a file and decrypt it?

I have some account info that is being encrypted and written to a file like this:
//imports here
public class Main
public static void main(String[] args) {
try {
String text = "this text will be encrypted";
String key = "Bar12345Bar12345";
//Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
//encrypt text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(text.getBytes());
write(new String(encrypted));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
}
public static void write(String message) {
BufferedWriter bw = null;
FileWriter fw = null;
try {
String data = message;
File file = new File(FILENAME);
if (!file.exists()) {
file.createNewFile();
}
fw = new FileWriter(file.getAbsoluteFile(), true);
bw = new BufferedWriter(fw);
bw.write(data);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bw != null)
bw.close();
if (fw != null)
fw.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
So the contents of the file is one string without any breaks in between. If I wanted to decrypt the string, I would do this:
String key = "Bar12345Bar12345";
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
byte[] encrypted = text.getBytes();
cipher.init(Cipher.DECRYPT_MODE, aesKey);
String decrypted = new String(cipher.doFinal(encrypted));
System.err.println(decrypted);
This works fine as long as byte[] encrypted is the same as used as in the encrypting process, but when I try to read the encrypted text from the file using a FileReader and a BufferedReader and change it into a byte using lines.getByte() it throws the exception
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
Compare the cipher text from the encrypting process with the cipher text from lines.getByte() before you try to do any decryption. They are most likely different. Try reading the entire file into a byte[] first before decrypting it. Symmetric ciphers need to do their work on blocks of the same size, in this case 16 bytes.
I would also be remiss if I didn't comment on some of the poor protocol choices.
Hard coded key - Your encryption key should never be hard-coded in your application. If you ever need to change your encryption key, you are not able to do so. If your application is distributed to end users, it's easy for them to recover the key using an application like strings.
You are using ECB as your mode of operation. ECB has several ways it can be attacked, such as block shuffling, which can allow an attacker to decrypt data without having the encryption key.
Encryption is hard to get right on your own. Consider solving your problem a different way.
You are trying to treat your encrypted array contents as (platform encoded) text, while it is not - it consists of random bytes.
You either need to create a binary file by writing the contents of encrypted to it directly. That or you can create a text file by first encoding encrypted to base64.
Currently you are trying to read lines, but there aren't any. And if there are some line endings in there they will be stripped from the ciphertext before those bytes can be decrypted.
If you perform new String(encrypted) then it is also possible that you lose part of your data, as unsupported encodings are removed from the string without warning.
Note that the word "ciphertext" is a bit misleading; modern ciphers such as AES handle binary data, not text.

AES Encryption between C# and F5 load balancer / TCL

I would like to use encryption to send traffic to my F5 BIG IP load balancer and have it use its own native CRYPTO:: methods to decrypt a base64 encoded string.
I am able to encrypt and decrypt a string within the appliance and within a Visual Studio 2012 console application but I cannot decrypt an encrypted string in the opposing environment.
Any suggestion here as to how to get the following keys in a compatible format that CRYPTO or C# understands would go a long way!
// C# key and vector declaration:
private const string AesIV = #"!QAZ2WSX#EDC4RFV";
private const string AesKey = #"5TGB&YHN7UJM(IK<";
It appears that in CRYPTO:: it needs it in hex format, I tried to convert it as seen below but that didnt help me.
C# console app code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
namespace ssoconsole_encrypt
{
class Program
{
private const string AesIV = #"!QAZ2WSX#EDC4RFV";
private const string AesKey = #"5TGB&YHN7UJM(IK<";
// set key "abed1ddc04fbb05856bca4a0ca60f21e"
//set iv "d78d86d9084eb9239694c9a733904037"
// set key "56bca4a0ca60f21e"
// set iv "39694c9a73390403"
/// <summary>
/// AES Encryption
/// </summary>
///
static public string Encrypt(string text)
{
// AesCryptoServiceProvider
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = Encoding.UTF8.GetBytes(AesIV);
aes.Key = Encoding.UTF8.GetBytes(AesKey);
string keyme = BitConverter.ToString(aes.Key);
string ivme = BitConverter.ToString(aes.IV);
Console.WriteLine(string.Format("The converted key is: {0}",keyme));
Console.WriteLine(string.Format("The converted iv is: {0}", ivme));
Console.WriteLine(System.Text.Encoding.UTF8.GetString(aes.Key));
// Thread.Sleep(10000);
//Console.WriteLine(aes.Key.ToString());
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// aes.Padding = PaddingMode.Zeros;
// Convert string to byte array
//byte[] src = Encoding.Unicode.GetBytes(text);
byte[] src = Encoding.UTF8.GetBytes(text);
// encryption
using (ICryptoTransform encrypt = aes.CreateEncryptor())
{
byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);
// Convert byte array to Base64 strings
return Convert.ToBase64String(dest);
}
}
/// <summary>
/// AES decryption
/// </summary>
static public string Decrypt(string text)
{
// AesCryptoServiceProvider
AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.IV = Encoding.UTF8.GetBytes(AesIV);
aes.Key = Encoding.UTF8.GetBytes(AesKey);
//aes.IV = Encoding.UTF8.GetBytes(#"01020304050607080900010203040506");
//aes.Key = Encoding.UTF8.GetBytes(#"01020304050607080900010203040506");
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// Convert Base64 strings to byte array
byte[] src = System.Convert.FromBase64String(text);
try
{
// decryption
using (ICryptoTransform decrypt = aes.CreateDecryptor())
{
byte[] dest = decrypt.TransformFinalBlock(src, 0, src.Length);
// return Encoding.Unicode.GetString(dest);
return Encoding.UTF8.GetString(dest);
}
}
catch (CryptographicException e)
{
return e.ToString();
}
}
static void Main()
{
string username = "jschoombee";
string encrypted = Encrypt(username);
string decrypted = Decrypt(encrypted);
// string decrypted = Decrypt("epvhTN55JnnVV9DBn1Cbsg==");
// string decrypted = Decrypt(encrypted);
Console.WriteLine(string.Format("jschoombee encrypted is : {0}",encrypted));
Console.WriteLine(string.Format("the Decrypted username for jp is : {0}", decrypted));
Thread.Sleep(1000000);
}
}
}
This is the Console Output:
The converted key is: 35-54-47-42-26-59-48-4E-37-55-4A-4D-28-49-4B-3C
The converted iv is: 21-51-41-5A-32-57-53-58-23-45-44-43-34-52-46-56
5TGB&YHN7UJM(IK<
jschoombee encrypted is : tGG9Un6VqcAOTQawlxwRXg==
the Decrypted username for jp is : jschoombee
This it the F5 / TCL code:
when RULE_INIT {
set static::hexkey "355447422659484E37554A4D28494B3C"
log local0.info"====Rule_Init===="
log local0.info "Key is $static::hexkey"
log local0.info"================="
}
when HTTP_REQUEST_DATA {
set iv "2151415A325753582345444334524656"
set text_to_encrypt "jschoombee"
set enc_out_no_binary [CRYPTO::encrypt -alg aes-256-cbc -keyhex $static::hexkey -ivhex $iv $text_to_encrypt]
set dec_in [CRYPTO::decrypt -alg aes-256-cbc -keyhex $static::hexkey -ivhex $iv $enc_out_no_binary]
log local0.info "The decrypted NO binary $dec_in"
log local0.info "The Encrypted NO binary Base64 is: [b64encode "$enc_out_no_binary"]"
binary scan $enc_out_no_binary H* enc_hex
log local0.info "The Encrypted NO binary Hex is: $enc_hex"
log local0.info "This is the IV $iv"
HTTP::release
}
The F5/TCL Output Log File:
Feb 11 13:05:45 AMS4-LB-01 info tmm1[9650]: <HTTP_REQUEST_DATA>: The decrypted NO binary jschoombee
Feb 11 13:05:45 AMS4-LB-01 info tmm1[9650]: <HTTP_REQUEST_DATA>: The Encrypted NO binary Base64 is: Rlz4cC9SlpRyON4cZI+dtQ==
Feb 11 13:05:45 AMS4-LB-01 info tmm1[9650]: <HTTP_REQUEST_DATA>: The Encrypted NO binary Hex is: 465cf8702f5296947238de1c648f9db5
Feb 11 13:05:45 AMS4-LB-01 info tmm1[9650]: <HTTP_REQUEST_DATA>: This is the IV 2151415A325753582345444334524656
There are some very strange things happening in your code regarding the key and IV.
First of all the key you've specified is 16 characters. In UTF-8 those result in 16 bytes. You are however specifying a key of 32 bytes (256 bits) in your C# code. Also be warned that many libraries (incorrectly) use AES-256 to mean Rijndael with a 256 bit block size. It's probably better to just use AES-128 and focus on making your protocol and code secure.
Second, a key can never be a character string. A character string normally is restricted with regards to which values can be used. E.g. control codes cannot be entered. This means that your key will never reach its intended strength. If you want to use a static key, you should specify it in hexadecimals as you do in your F5 code.
A static IV does not make much sense. The whole idea of the IV is to make sure that you will generate a different ciphertext if you encrypt a block with a value already processed. So please use a random IV, and place it in front of your ciphertext.
You seem to have the hang on using encoding/decoding on your plaintext (UTF-8) and ciphertext (Base 64). So please try and follow the advice given above and try again.

Encrypt in .Net and decrypt in AS3

I need to encrypt some files in ASP.net and decrypt them in a flash application built with Action Script 3.
AS3 developer found a lib call AS3crypto which seems like a good one for AS3. The idea is encrypt and decrypt using same key. Symmetrical Encryption?
But I am struggling to find .Net equivalent that would use same algorithm for encryption.
I have tried RC4 example from 4guysfromrolla blog which works too slow for me.
I have tried AES on this example (http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.100).aspx) which works great on .Net but I can't seem to decrypt using AS3crypto to get the same file back. AS3crypto doesn't seem to like to have IV for decryption. I can only supply one key.
So far I am lost. How can I encrypt a file in .Net and decrypt it back in AS3 to get the same file back?
Notice: use 16 char length for both Key and IV, ex: Key: 1234567890123456 and IV: 9876543210654321
Here is C# code
public byte[] Encrypt(byte[] someData, string KEY, string IV)
{
//preparing
byte[] keyBytes = Encoding.UTF8.GetBytes(KEY);
byte[] ivBytes = Encoding.UTF8.GetBytes(IV);
//here goes encryption
RijndaelManaged rijndaelManaged = new RijndaelManaged();
rijndaelManaged.Key = keyBytes;
rijndaelManaged.IV = ivBytes;
rijndaelManaged.BlockSize = 128;
rijndaelManaged.Mode = CipherMode.CBC;
ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(rijndaelManaged.Key, rijndaelManaged.IV);
byte[] result = null;
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(someData, 0, someData.Length);
cryptoStream.FlushFinalBlock();
result = memoryStream.ToArray();
}
}
return result;
}
And here is AS3 code using AS3Crypto library
private function decrypt(input:ByteArray, decrKey:String, decrIV:String):ByteArray
{
var key:ByteArray = Hex.toArray(Hex.fromString(decrKey));
var pad:IPad = new NullPad();
var aes:ICipher = Crypto.getCipher("aes-cbc", key, pad);
var ivmode:IVMode = aes as IVMode;
ivmode.IV = Hex.toArray(Hex.fromString(decrIV));
aes.decrypt(input);
return input;
}

is there AES source code (VB.NET) that decrypts AS3CRYPTO crypted msgs

Is there a simple ASP.NET (.VB) available for AES-encrypting?
here is a link to c# one but its complicate one having pretty much parameters, for example salt.
[http://www.gutgames.com/post/AES-Encryption-in-C.aspx]
I need a simple one that works together with GOOGLEAS3 Class that is called easily like this:
var key:ByteArray = Hex.toArray("1234567890abcdef");
var pt:ByteArray = Hex.toArray( Hex.fromString("aaaaaaaaaaaaaaaaaaaa"));
var aes:AESKey = new AESKey(key);
aes.encrypt(pt);
var out:String = Hex.fromArray(pt).toUpperCase();
AES is built into the framework, as the Aes class in System.Security.Cryptography. There are two concrete implementations, one managed, one using the Windows Crypto Service Provider (faster, but not portable to other platforms). There's also an implementation of Rijndael, from which AES derives.
Remember you need an initialization vector, as well as the key to encrypt/decrypt, as it's a block cipher. If you encrypt without setting one a random one will be used, but you will need to store and retrieve it for decryption.
Example Code: (lifted from chapter 6 of my forthcoming book grin)
static byte[] Encrypt(byte[] clearText, byte[] key, byte[] iv)
{
// Create an instance of our encyrption algorithm.
RijndaelManaged rijndael = new RijndaelManaged();
// Create an encryptor using our key and IV
ICryptoTransform transform = rijndael.CreateEncryptor(key, iv);
// Create the streams for input and output
MemoryStream outputStream = new MemoryStream();
CryptoStream inputStream = new CryptoStream(
outputStream,
transform,
CryptoStreamMode.Write);
// Feed our data into the crypto stream.
inputStream.Write(clearText, 0, clearText.Length);
// Flush the crypto stream.
inputStream.FlushFinalBlock();
// And finally return our encrypted data.
return outputStream.ToArray();
}
and to decrypt
static byte[] Decyrpt(byte[] clearText, byte[] key, byte[] iv)
{
// Create an instance of our encryption algorithm.
RijndaelManaged rijndael = new RijndaelManaged();
// Create an decryptor using our key and IV
ICryptoTransform transform = rijndael.CreateDecryptor(key, iv);
// Create the streams for input and output
MemoryStream outputStream = new MemoryStream();
CryptoStream inputStream = new CryptoStream(
outputStream,
transform,
CryptoStreamMode.Write);
// Feed our data into the crypto stream.
inputStream.Write(clearText, 0, clearText.Length);
// Flush the crypto stream.
inputStream.FlushFinalBlock();
// And finally return our decrypted data.
return outputStream.ToArray();
}
replace the RijndaelManaged class with one of the AES classes and a suitable key.

Resources