Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
When I try to encrypt using AES, I get the error Invalid length for a Base-64 char array or string when i try to execute this line of code:
byte[] clearBytes = Convert.FromBase64String(clearText);
Here is my code:
public string AESEncrypt( string clearText )
{
clearText = HttpUtility.UrlEncode( clearText ) ;
byte[] clearBytes = Convert.FromBase64String( clearText ) ;
byte[] ivBytes = Encoding.UTF8.GetBytes( InitV );
byte[] keyBytes = Encoding.UTF8.GetBytes( EncryptionKey ) ;
var symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.PKCS7;
var enctryptor = symmetricKey.CreateEncryptor(keyBytes, ivBytes);
using (MemoryStream ms = new MemoryStream())
{
using ( CryptoStream cs = new CryptoStream( ms, enctryptor, CryptoStreamMode.Write ) )
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
return clearText;
}
Alternately, when I try to decrypt, I get the error The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters. trying to execute this line of code:
byte[] cipherBytes = Convert.FromBase64String(cipherText);
Here is my code:
public string AESDecrypt(string cipherText)
{
string clearText;
cipherText = HttpUtility.UrlEncode(cipherText) ;
byte[] cipherBytes = Convert.FromBase64String(cipherText);
byte[] ivBytes = Encoding.UTF8.GetBytes(InitV);
byte[] keyBytes = Encoding.UTF8.GetBytes(EncryptionKey);
var symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
symmetricKey.Padding = PaddingMode.PKCS7;
var enctryptor = symmetricKey.CreateDecryptor(keyBytes, ivBytes);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, enctryptor, CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
return clearText;
}
I don't know what makes you think that URL encode generates base 64 encoded bytes, but decoding it will usually result in the errors that you are getting.
cipherText = HttpUtility.UrlEncode(cipherText);
byte[] cipherBytes = Convert.FromBase64String(cipherText);
is just absolute nonsense. Please look up what these functions do and try again.
Are you passing your base64 encoded string on the QueryString? If so it likely contains "+" signs which are not valid data on the QueryString. URL Encode your base 64 string.
http://msdn.microsoft.com/en-us/library/zttxte6w(v=vs.110).aspx
Related
I have this code in CryptoJS, inside browser:
var decrypt = function (cipherText) {
var key = "a_long_key_goes_here";
var iv = "initial_vector_goes_here";
key = CryptoJS.enc.Hex.parse(key);
iv = CryptoJS.enc.Hex.parse(iv);
var decrypted = CryptoJS.TripleDES.decrypt({
ciphertext: CryptoJS.enc.Hex.parse(cipherText)
}, key, {
iv: iv,
mode: CryptoJS.mode.CBC
});
var clearText = decrypted.toString(CryptoJS.enc.Utf8);
return clearText;
};
This code is not written by me. Also the cipherText come from another server that I have no access to. However, I have access to key and to iv.
I can decrypt that cipherText inside a browser's console. But I want to use these keys to decrypt that cipherText inside C# code. Here's the code I've written:
public void Desrypt()
{
ICryptoTransform decryptor;
UTF8Encoding encoder;
string key = "a_long_key_goes_here";
string iv = "initial_vector_goes_here";
var cipherText = "cipher_text_goes_here";
string clearText = "";
byte[] cipherBytes = FromHexString(cipherText);
using (Aes aes = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, new byte[] { });
aes.Key = pdb.GetBytes(32);
aes.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
clearText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return clearText;
}
public static byte[] FromHexString(string hexString)
{
var bytes = new byte[hexString.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
return bytes;
}
I have some problems though. I don't understand if I'm correctly decoding the given cipherText from hexadecimal or not. Also I can't instantiate Rfc2898DeriveBytes, because I don't know what the second parameter (salt) should be.
Also I don't know where should I use that iv I've gotten from the CryptoJS code.
Could you please help?
So that both codes are compatible, the following changes of the C# code are necessary:
The return type of the Decrypt method must be changed from void to string.
Key and IV have to be decoded hexadecimal like the ciphertext with FromHexString.
Instead of AES, TripleDES must be used.
Rfc2898DeriveBytes implements PBKDF2 and must not be applied (since the JavaScript code does not use PBKDF2 either).
The decrypted data must not be decoded with Encoding.Unicode (which corresponds to UTF16LE in .NET), but with Encoding.UTF8.
The C# code can handle 24 bytes keys (to support 3TDEA) and 16 bytes keys (to support the less secure 2TDEA). The posted CryptoJS code also handles these key sizes plus additionally 8 bytes keys (to support the least secure, DES compatible variant 1TDEA).
The following C# code decrypts a ciphertext generated with CryptoJS and 3TDEA:
public string Decrypt()
{
byte[] key = FromHexString("000102030405060708090a0b0c0d0e0f1011121314151617"); // 24 bytes (3TDEA)
byte[] iv = FromHexString("0001020304050607"); // 8 bytes
byte[] ciphertext = FromHexString("2116057c372e0e95dbe91fbfd148371b8e9974187b71e7c018de89c757280ad342d4191d29472040ee70d19015b025e1");
string plaintext = "";
using (TripleDES tdes = TripleDES.Create())
{
tdes.Key = key;
tdes.IV = iv;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, tdes.CreateDecryptor(tdes.Key, tdes.IV), CryptoStreamMode.Write))
{
cs.Write(ciphertext, 0, ciphertext.Length);
}
plaintext = Encoding.UTF8.GetString(ms.ToArray());
}
}
return plaintext;
}
The decryption is also possible with the posted JavaScript code, which shows the functional equivalence of both codes.
Note: Since AES is more performant than TripleDES, AES should be used if possible.
I am getting an error while decrypting and encrypted string:
5duOH+Tlg5deIrWZiHoNaQ==wVxXSl9pFu6A8h14/nLdyBkDzO4xmec7PQ0cB7MHjCDqhSRum3C7I1OfqL1rEWbNonU/ayCaJS18zV7ivQQU7A==MBJzKMrrrbmc2/vBZSPDkQ==I09Kj25UO+LcmRzgoqTT2g==+Fkm9VCGplEK6eEyHyEtuEodKSbckC07M2FShu2ukCg=
Error is as follows:
The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
My encryption code is:
public string EncryptQueryString(string inputText, string key, string salt)
{
byte[] plainText = Encoding.UTF8.GetBytes(inputText);
using (RijndaelManaged rijndaelCipher = new RijndaelManaged())
{
PasswordDeriveBytes secretKey = new PasswordDeriveBytes(Encoding.ASCII.GetBytes(key), Encoding.ASCII.GetBytes(salt));
using (ICryptoTransform encryptor = rijndaelCipher.CreateEncryptor(secretKey.GetBytes(32), secretKey.GetBytes(16)))
using (MemoryStream memoryStream = new MemoryStream())
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainText, 0, plainText.Length);
cryptoStream.FlushFinalBlock();
string base64 = Convert.ToBase64String(memoryStream.ToArray());
// Generate a string that won't get screwed up when passed as a query string.
string urlEncoded = HttpUtility.UrlEncode(base64);
return urlEncoded;
}
}
}
Decryption:
public string DecryptQueryString(string inputText, string key, string salt)
{
byte[] encryptedData = Convert.FromBase64String(inputText);
PasswordDeriveBytes secretKey = new PasswordDeriveBytes(Encoding.ASCII.GetBytes(key), Encoding.ASCII.GetBytes(salt));
using (RijndaelManaged rijndaelCipher = new RijndaelManaged())
using (ICryptoTransform decryptor = rijndaelCipher.CreateDecryptor(secretKey.GetBytes(32), secretKey.GetBytes(16)))
using (MemoryStream memoryStream = new MemoryStream(encryptedData))
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
byte[] plainText = new byte[encryptedData.Length];
cryptoStream.Read(plainText, 0, plainText.Length);
string utf8 = Encoding.UTF8.GetString(plainText);
return utf8;
}
}
Base64 padding consists of = or ==, and so it looks like multiple Base64 strings where appended together somehow. You'll have to find where they all originally ended, split them there, and try again.
Note that Base64 strings do not always have padding, only when it is needed, so there may even need to be breaks in places that you cannot see here.
I want to pass an id to QueryString of my webpage, as I don't want visitors to see the number, I encode it using RijndaelManaged algorithm, My issue is, this encryption sometimes add a character for example '+' which causes double escape sequence error.
I was wondering if there is way to exclude some characters from encryption output.
My encryption code is as below:
public static string Encrypt(string plainText)
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] keyBytes = new Rfc2898DeriveBytes(PasswordHash, Encoding.ASCII.GetBytes(SaltKey)).GetBytes(256 / 8);
var symmetricKey = new RijndaelManaged() { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros };
var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.ASCII.GetBytes(VIKey));
byte[] cipherTextBytes;
using (var memoryStream = new MemoryStream())
{
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
cipherTextBytes = memoryStream.ToArray();
cryptoStream.Close();
}
memoryStream.Close();
}
return Convert.ToBase64String(cipherTextBytes);
}
You could convert your bytearray to a Hex string instead of a base64 string. Hex will only contain [a-f0-9]
See this question for details.
But as for your original Problem: you should really use URL encoding for your query strings, which will solve the Problem of the + character.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have encryption / decryption method in python written as
import base64
from Crypto.Cipher import AES
def get_encrypted_message(message):
"""Return encrypted message."""
length = 16 - (len(message) % 16)
message += chr(length) * length
cipher = AES.new('abcdefghijklmnopqrstuvwxyz123456',
AES.MODE_CBC, 16 * '\x00')
message = cipher.encrypt(message)
return base64.b64encode(message)
def get_decrypted_message(message):
"""Return decrypted message."""
if not message:
return
message = base64.b64decode(message)
cipher = AES.new(
'abcdefghijklmnopqrstuvwxyz123456', AES.MODE_CBC, 16 * '\x00')
msg = cipher.decrypt(message)
return msg.strip()
ENCRYPTED_MSG = get_encrypted_message('123')
print ENCRYPTED_MSG # 5pRIk9MDE3z9caf/ayilIA==
print get_decrypted_message(ENCRYPTED_MSG) # 123
I am now looking for equivalent Windows phone 8.1 C# AES algorithm encryption method. I am new to windows phone development and in my application i have to query data by passing encrypted data.
Please guide or help in writing this simple code. As I am finding it very difficult to get winphone 8.1 c# algo, I dont see any AES algo is available or not as it was available in 8.
Thanks!
WP 8.1 and WinRT
public static string Encrypt2(string password, string plainText)
{
IBuffer passwordBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
IBuffer plainBuffer = CryptographicBuffer.ConvertStringToBinary(plainText, BinaryStringEncoding.Utf8);
IBuffer iv = WindowsRuntimeBuffer.Create(16);
SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
// create symmetric key from derived password key
CryptographicKey symmKey = symProvider.CreateSymmetricKey(passwordBuffer);
// encrypt data buffer using symmetric key and derived salt material
IBuffer encryptedBuffer = CryptographicEngine.Encrypt(symmKey, plainBuffer, iv);
string encryptedText = CryptographicBuffer.EncodeToBase64String(encryptedBuffer);
return encryptedText;
}
public static string Decrypt2(string password, string encryptedText)
{
IBuffer passwordBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
IBuffer encryptedBuffer = CryptographicBuffer.DecodeFromBase64String(encryptedText);
IBuffer iv = WindowsRuntimeBuffer.Create(16);
SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
// create symmetric key from derived password material
CryptographicKey symmKey = symProvider.CreateSymmetricKey(passwordBuffer);
// encrypt data buffer using symmetric key and derived salt material
IBuffer plainBuffer = CryptographicEngine.Decrypt(symmKey, encryptedBuffer, iv);
string plainText = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, plainBuffer);
return plainText;
}
EVERYTHING ELSE
public static string Encrypt(string password, string plainText)
{
using (var aes = new AesManaged())
{
aes.Key = Encoding.UTF8.GetBytes(password);
aes.IV = new byte[16];
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
byte[] plainBuffer = Encoding.UTF8.GetBytes(plainText);
using (MemoryStream input = new MemoryStream(plainBuffer))
using (MemoryStream output = new MemoryStream())
using (ICryptoTransform encryptor = aes.CreateEncryptor())
using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
{
input.CopyTo(cs);
cs.FlushFinalBlock();
string encryptedText = Convert.ToBase64String(output.GetBuffer(), 0, (int)output.Length);
return encryptedText;
}
}
}
public static string Decrypt(string password, string encryptedText)
{
using (var aes = new AesManaged())
{
aes.Key = Encoding.UTF8.GetBytes(password);
aes.IV = new byte[16];
aes.Padding = PaddingMode.PKCS7;
aes.Mode = CipherMode.CBC;
byte[] encryptedBuffer = Convert.FromBase64String(encryptedText);
using (MemoryStream input = new MemoryStream(encryptedBuffer))
using (MemoryStream output = new MemoryStream())
using (ICryptoTransform decryptor = aes.CreateDecryptor())
using (CryptoStream cs = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
{
cs.CopyTo(output);
string plainText = Encoding.UTF8.GetString(output.GetBuffer(), 0, (int)output.Length);
return plainText;
}
}
}
Note that there is a small problem here: I'm using UTF8 for the encoding of both the password and the strPlainText, but python uses bytestring for everything, and bytestring is encoding agnostic (see What is a Python bytestring?).
Example of use:
string result = Encrypt("abcdefghijklmnopqrstuvwxyz123456", "123"); // 5pRIk9MDE3z9caf/ayilIA==
string decrypted = Decrypt("abcdefghijklmnopqrstuvwxyz123456", result); // 123
The method returns the same encrypted result as your example.
A small problem of this piece of code is that the IV (the initialization vector) is initialized with an empty biffer (new byte[16] and 16 * '\x00' in Python). This is a "bad habit". Even using the CBC cyphermode is considered to be "bad".
I have the following code for encryption and decryption. The problem is that at decryption besides the decrypted text i have some "aaaaa" after the text. why? need some help. THX!
public static byte[] Encrypt(byte[] PlainTextBytes, string key , string InitialVector)
{
try
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
Byte[] KeyBytes = encoding.GetBytes(key);
byte[] InitialVectorBytes = encoding.GetBytes(InitialVector);
RijndaelManaged SymmetricKey = new RijndaelManaged();
ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
MemoryStream MemStream = new MemoryStream();
CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
CryptoStream.FlushFinalBlock();
byte[] CipherTextBytes = MemStream.ToArray();
return CipherTextBytes;
//decrytion
public static string Decrypt(byte[] PlainTextBytes1, string key, string InitialVector)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
Byte[] KeyBytes = encoding.GetBytes(key);
RijndaelManaged SymmetricKey = new RijndaelManaged();
byte[] InitialVectorBytes = Encoding.UTF8.GetBytes(InitialVector);
ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes);
MemoryStream MemStream1 = new MemoryStream(PlainTextBytes1);
CryptoStream CryptoStream = new CryptoStream(MemStream1, Decryptor, CryptoStreamMode.Read);
Byte[] pltxt = new byte[PlainTextBytes1.Length];
CryptoStream.Read(pltxt, 0, pltxt.Length);
ASCIIEncoding textConverter = new ASCIIEncoding();
round = textConverter.GetString(pltxt);
return round;
}
where am i wrong?
In your decrypt function you have:
Byte[] pltxt = new byte[PlainTextBytes1.Length];
This is wrong because the cypher text is longer than the plain text, because it's padded to get a multiple of the block size.
CryptoStream.Read(pltxt, 0, pltxt.Length);
Read returns how many bytes were actually returned. It doesn't guarantee that it will return as many bytes as you requested.
And then there are multiple other defects/bad style things:
The parameter passed into Decrypt is called PlainTextBytes1 it should be called cyphertext.
The way you create the key/initvec bytes from the string. ASCII encoding is a bad choice here. ASCII can't represent any byte string. Perhaps you want to hex en/decode a string of twice the size of the key instead?
ASCII en/decoding the plaintext will only work for ASCII characters and silently corrupt all other characters. Why don't you use UTF-8 instead?
.net naming conventions say you should use lowercase names for parameters