I need to encrypt and decrypt a string in C#.
I have managed to write the right decoder for a string which I receive from a Java service - 3DES, DESede/ECB/NoPadding.
Now, I am having some a time encoding a string accordingly.
Below is the decryptor (which is perfect and not need any changes).
attached also the encryptor which should encrypt a string that will be decrypted with the attached decryptor.
decryptor:
public static string Decryptor240815B(string Message) /* Working */
{
string cipher = Message.Replace(" ", "+");
byte[] keyBytes;
string cipherString = FromHexString(cipher);
byte[] cipherBytes = Convert.FromBase64String(cipherString);
keyBytes = UTF8Encoding.UTF8.GetBytes(seed);
var tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyBytes;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.None;
ICryptoTransform transformation = tdes.CreateDecryptor();
byte[] decryptedBytes = transformation.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length);
tdes.Clear();
string response = UTF8Encoding.UTF8.GetString(decryptedBytes);
return response;
}
public static string 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 Encoding.UTF8.GetString(bytes);
}
encryptor (need change):
public static string Encrypt030915(string message)
{
byte[] keyBytes = UTF8Encoding.UTF8.GetBytes(seed);
//string hexedMSG = StringToHexString(message);
byte[] textBytes = UTF8Encoding.UTF8.GetBytes(message);
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
ICryptoTransform cTransform = tdes.CreateEncryptor();
tdes.Key = keyBytes;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.None;
byte[] resultArray = cTransform.TransformFinalBlock(textBytes, 0, textBytes.Length);
tdes.Clear();
string base64 = Convert.ToBase64String(resultArray);
string retVal = FromBase64ToHEX(base64);
return retVal;
//byte[] ba = Encoding.UTF8.GetBytes(base64);
// return ToHexString(resultArray);
//return ByteArrayToString030915(ba);
}
private static string FromBase64ToHEX(string base64)
{
char[] c = new char[base64.Length * 2];
byte b;
for (int i = 0; i < base64.Length; ++i)
{
b = ((byte)(base64[i] >> 4));
c[i * 2] = (char)(b > 9 ? b + 0x37 : b + 0x30);
b = ((byte)(base64[i] & 0xF));
c[i * 2 + 1] = (char)(b > 9 ? b + 0x37 : b + 0x30);
}
return new string(c);
}
You need to move the
ICryptoTransform transformation = tdes.CreateDecryptor();
line below setting the parameters, as CreateDecryptor uses the parameters (like Key!) as they are set on the TripleDESCryptoServiceProvider at the moment. But in your original code, you create the decryptor and only after that set the decryption parameters, which do not get used at all (and the decryptor gets to use a random key instead). Replace the relevant lines with:
var tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyBytes;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.None;
ICryptoTransform transformation = tdes.CreateDecryptor();
and it will work.
However, note that your code is 1) unnecessarily complicated, 2) completely insecure.
Related
In swift I wrote this code to encrypt a string
func Encrypt2(_ input:String)->String?{
let key = "123456abcdefcdhs"
do{
let encrypted: Array<UInt8> = try AES(key: key, iv: key, padding: .pkcs5).encrypt(Array(input.utf8))
return encrypted.toBase64()?.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
}catch{
}
return nil
}
And in c# the code for decryption is this
string key = "123456abcdefcdhs";
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
byte[] encryptedData = Convert.FromBase64String(textToDecrypt);
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return Encoding.UTF8.GetString(plainText);
Encrytion works fine but when it comes to c# decryption...give me an error saying
base64 length.
I tried changing the .pkcs5 to .pkcs7 but still doesn't work.
whats wrong with the code?
The base64 string is --> aMtLgvWQOguK+GPbGT/Jxw==
sometimes the string is --> aMtLgvWQOguK GPbGT/Jxw==
I want to encrypt a text in PHP and to decrypt in in C#, but i can't.
This is my PHP code:
define('AES_256_ECB', 'aes-256-ecb');
$encryption_key = "SomeSimpleTest";
$data = "Test123";
$encryptedData = openssl_encrypt($data, AES_256_ECB, $encryption_key, 0);
..and this is my C# code:
(AESEncryption.cs class)
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace AESCrypto
{
class AESEncryption
{
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
// Set your salt here to meet your flavor:
byte[] saltBytes = passwordBytes;
// Example:
//saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 256;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.ECB;
//AES.Padding = PaddingMode.PKCS7;
using (CryptoStream cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
public static string Decrypt(string decryptedText, byte[] passwordBytes)
{
byte[] bytesToBeDecrypted = Convert.FromBase64String(decryptedText);
// Hash the password with SHA256
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] decryptedBytes = AES_Decrypt(bytesToBeDecrypted, passwordBytes);
// Getting the size of salt
int saltSize = GetSaltSize(passwordBytes);
// Removing salt bytes, retrieving original bytes
byte[] originalBytes = new byte[decryptedBytes.Length - saltSize];
for (int i = saltSize; i < decryptedBytes.Length; i++)
{
originalBytes[i - saltSize] = decryptedBytes[i];
}
return Encoding.UTF8.GetString(originalBytes);
}
public static int GetSaltSize(byte[] passwordBytes)
{
var key = new Rfc2898DeriveBytes(passwordBytes, passwordBytes, 1000);
byte[] ba = key.GetBytes(2);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ba.Length; i++)
{
sb.Append(Convert.ToInt32(ba[i]).ToString());
}
int saltSize = 0;
string s = sb.ToString();
foreach (char c in s)
{
int intc = Convert.ToInt32(c.ToString());
saltSize = saltSize + intc;
}
return saltSize;
}
public static byte[] GetRandomBytes(int length)
{
byte[] ba = new byte[length];
RNGCryptoServiceProvider.Create().GetBytes(ba);
return ba;
}
}
}
Usage of it:
using AESCrypto;
...
public string DecryptText(string input, string password)
{
// Get the bytes of the string
byte[] bytesToBeDecrypted = Convert.FromBase64String(input);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesDecrypted = AESEncryption.AES_Decrypt(bytesToBeDecrypted, passwordBytes);
string result = Encoding.UTF8.GetString(bytesDecrypted);
return result;
}
private void btn1_Click(object sender, EventArgs e)
{
textBox1.Text = DecryptText("KEY_ENCRYPTED_WITH_PHP", "SomeSimpleTest");
}
I even tried with CBC but does not work...The mode of encryption is not important. I only want to make it work as it should.
Thanks.
php code:
define('AES_128_ECB', 'aes-128-ecb');
$encryption_key = "MY_16_CHAR_KEY:)";
$data = "MyOwnEncryptedSecretText";
$encryptedData = openssl_encrypt($data, AES_128_ECB, $encryption_key, 0);
C# code:
public String Decrypt(String text, String key)
{
//decode cipher text from base64
byte[] cipher = Convert.FromBase64String(text);
//get key bytes
byte[] btkey = Encoding.ASCII.GetBytes(key);
//init AES 128
RijndaelManaged aes128 = new RijndaelManaged();
aes128.Mode = CipherMode.ECB;
aes128.Padding = PaddingMode.PKCS7;
//decrypt
ICryptoTransform decryptor = aes128.CreateDecryptor(btkey, null);
MemoryStream ms = new MemoryStream(cipher);
CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
byte[] plain = new byte[cipher.Length];
int decryptcount = cs.Read(plain, 0, plain.Length);
ms.Close();
cs.Close();
//return plaintext in String
return Encoding.UTF8.GetString(plain, 0, decryptcount);
}
and usage of it:
string DecryptedText = Decrypt("GENERATED_KEY", "MY_16_CHAR_KEY:)");
Now it works great :)
Thanks.
I did some encryption using PHP in my Database and would normally decrypt using:
$encrypt_method = "AES-256-CBC";
$secret_key = "testing";
$secret_iv = "testingyes!!!";
$key = hash('sha256', $secret_key); // hash the key
$iv = substr(hash('sha256', $secret_iv), 0, 16); // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
echo(openssl_decrypt(base64_decode($data), $encrypt_method, $key, 0, $iv)); // the decrypted data
I'm trying to do the same task but with C# 2013 to decrypt the same data, any ideas?
I would encrypt in php using:
$encrypt_method = "AES-256-CBC";
$secret_key = "testing";
$secret_iv = "testingyes!!!";
$key = hash('sha256', $secret_key); // hash the key
$iv = substr(hash('sha256', $secret_iv), 0, 16); // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
echo(base64_encode(openssl_encrypt($data, $encrypt_method, $key, 0, $iv))); // the encrypted data
encrypting: this is a test
gives: d0EzQ2MvMHkxRks2cXg5NkFkK2twZz09=
I tried this in C#:
public static String sha256_hash(String value)
{
StringBuilder Sb = new StringBuilder();
using (SHA256 hash = SHA256Managed.Create())
{
Encoding enc = Encoding.UTF8;
Byte[] result = hash.ComputeHash(enc.GetBytes(value));
foreach (Byte b in result)
Sb.Append(b.ToString("x2"));
}
return Sb.ToString();
}
private static String AES_decrypt(String Input)
{
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 256;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.None;
aes.Key = Convert.FromBase64String(sha256_hash("testing"));
aes.IV = Convert.FromBase64String(sha256_hash("testingyes!!!").Substring(0, 16));
var decrypt = aes.CreateDecryptor();
byte[] xBuff = null;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
byte[] xXml = Convert.FromBase64String(Input);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = ms.ToArray();
}
String Output = Encoding.UTF8.GetString(xBuff);
return Output;
}
string cipherData = "d0EzQ2MvMHkxRks2cXg5NkFkK2twZz09=";
string f = AES_decrypt(cipherData);
Console.Write(f);
But I'm getting error: specified key is not a valid size for this algorithm
However the key I'm using is working when I use PHP
RijndaelManaged aes = new RijndaelManaged();
aes.KeySize = 256;
aes.BlockSize = 256;
Block size should be 128 to be compatible with AES-256-CBC.
Rijndael supports variable block sizes - AES does not.
I have a key which is in hex as 1C19D5ED8D88DC40 and the data in hex as 041164DFFFFE7FF7.
I am supposed to do DES encryption to obtain the encrypted value in hex as B652FF1BA23C279B. i struggled a lot with all possible encrypting methods of DES but couldn't get the exact value. I found it in this link I passed the binary values of the above hex as input and got the desired.
Help with C# code to get the above value.
public static string Encrypt(string Data,string Key)
{
byte[] key = Encoding.ASCII.GetBytes(Key);
// byte[] iv = Encoding.ASCII.GetBytes("password");
byte[] data = Encoding.ASCII.GetBytes(Data);
byte[] enc = new byte[0];
TripleDES tdes = TripleDES.Create();
//tdes.IV = iv;
tdes.Key = key;
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.Zeros;
ICryptoTransform ict = tdes.CreateEncryptor();
enc = ict.TransformFinalBlock(data, 0, data.Length);
return Bin2Hex(enc);
}
// my bin2hex implementation
static string Bin2Hex(byte[] bin)
{
StringBuilder sb = new StringBuilder(bin.Length * 2);
foreach (byte b in bin)
{
sb.Append(b.ToString("x").PadLeft(2, '0'));
}
return sb.ToString();
}
I'm encrypting a big string with TDES and trying to decrypt it. Can't understand what's is wrong.
When it does the READ function in decryption I get "Bad Data" from the Cryptographic Exception. (I marked the line with comments)
To generate and encrypt the string:
public void MssGenerateKeyPair(string ssSymmetricKey, out string ssCipheredKeyPair, out string ssPublicKey) {
ssCipheredKeyPair = string.Empty;
ssPublicKey = string.Empty;
//Symmetric key is the hash of user's signing password
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
byte[] tempKey = sha1.ComputeHash(Encoding.UTF8.GetBytes(ssSymmetricKey));
byte[] key = new byte[24];
tempKey.CopyTo(key, 0);
//if symmetric keys is < 24
for (int index = 0, i = tempKey.Length; i < key.Length; index++, i++)
{
key[i] = tempKey[index];
}
//define symmetric encryption data
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = key;
tdes.IV = new byte[8];
tdes.Mode = CipherMode.CBC;
tdes.Padding = PaddingMode.PKCS7;
//define assymetric stuff
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, tdes.CreateEncryptor(), CryptoStreamMode.Write);
byte[] toChipher = Encoding.UTF8.GetBytes(rsa.ToXmlString(true));
cryptoStream.Write(toChipher, 0, toChipher.Length);
byte[] cipheredKeyPair = memoryStream.ToArray();
ssCipheredKeyPair = Convert.ToBase64String(cipheredKeyPair);
ssPublicKey = rsa.ToXmlString(false);
cryptoStream.Close();
memoryStream.Close();
} // MssGenerateKeyPair
To decrypt the string
public void MssSignData(string ssSymmetricKey, byte[] ssDataToSign, byte[] ssCipheredKeyPair, out byte[] ssSignature, out byte[] ssSignedData) {
ssSignature = new byte[] {};
ssSignedData = new byte[] {};
//Symmetric key is the hash of user's signing password
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
byte[] tempKey = sha1.ComputeHash(Encoding.UTF8.GetBytes(ssSymmetricKey));
byte[] key = new byte[24];
tempKey.CopyTo(key, 0);
//if symmetric keys is < 24
for (int index = 0, i = tempKey.Length; i < key.Length; index++, i++)
{
key[i] = tempKey[index];
}
//define symmetric encryption data
TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
tdes.Key = key;
tdes.IV = new byte[8];
tdes.Mode = CipherMode.CBC;
tdes.Padding = PaddingMode.PKCS7;
MemoryStream memoryStream = new MemoryStream(ssCipheredKeyPair);
CryptoStream cryptoStream = new CryptoStream(memoryStream, tdes.CreateDecryptor(), CryptoStreamMode.Read);
MemoryStream plainMemoryStream = new MemoryStream();
byte[] tempPlainBytes = new byte[1024];
int read = 0;
int totalRead = 0;
do
{
//################################################################
//ERROR IN THE FOLLOWING LINE
//################################################################
read = cryptoStream.Read(tempPlainBytes, 0, tempPlainBytes.Length);
totalRead += read;
plainMemoryStream.Write(tempPlainBytes, 0, read);
} while (read > 0);
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(Encoding.UTF8.GetString(plainMemoryStream.ToArray()));
ssSignature = rsa.SignData(ssDataToSign, new SHA1CryptoServiceProvider());
ssSignedData = ssDataToSign;
cryptoStream.Close();
memoryStream.Close();
plainMemoryStream.Close();
} // MssSignData
Code to test
private void button1_Click(object sender, EventArgs e)
{
string key;
string pkey;
byte[] sig;
byte[] avs;
OutSystems.NssPseudoCertificates.CssPseudoCertificates c = new OutSystems.NssPseudoCertificates.CssPseudoCertificates();
c.MssGenerateKeyPair("xpto",out key, out pkey);
c.MssSignString("xpto", "hello", key, out sig, out avs);
}
Like Marvin Smit said in his comments: to add the flush, I did it and worked!
Credits go to him!