i implement AES 256 bit algorithm in C# but i am encrypting 128bit block of plain text which require padding so i dont want to pad and want use to stream cipher
use stream cipher instead of using 128 bit block
encrypt stream byte by byte
CryptLib _crypt = new CryptLib();
//string plainText = "This is the text to be encrypted";
String iv = CryptLib.GenerateRandomIV(16); //16 bytes = 128 bits
string key = CryptLib.getHashSha256("my secret key", 31); //32 bytes = 256 bits
MessageBox.Show(arm);//////////////////////
String cypherText = _crypt.encrypt(string1, key, iv);
Console.WriteLine("iv=" + iv);
Console.WriteLine("key=" + key);
Console.WriteLine("Cypher text=" + cypherText);
MessageBox.Show(cypherText);
textBox1.Text = cypherText;
Console.WriteLine("Plain text =" + _crypt.decrypt(cypherText, key, iv));
MessageBox.Show(_crypt.decrypt(cypherText, key, iv));
String dypher = _crypt.decrypt(cypherText, key, iv);
string outp = string.Empty;
char[] value = dypher.ToCharArray();
If the input data is always an exact multiple of the block size you can just specify no padding.
if you have data of unknown non-uniform block lengths padding is the general way to handle that.
Why do you not want to use padding.
Additionally:
It is common to prefix the encrypted data with the IV for use during decryption. The IV does not need to be secret and with this method the IV does not need to be shared in some other way and can easily be a different random value for each encryption.
Deriving a key from a password (string) with a hash function is not considered secure, instead use a key derivarion function such as PBKDF2.
Related
I have a client who needs us to use Blowfish ECB encryption with cipherMode 0, output 1. I have tried to solve for this, but I'm getting stuck. How do I fix my code?
Here are the full client instructions:
Algorithm: Blowfish
・ Mode: ECB
・ Padding: PKCS5Padding
*Initial vector is unnecessary because we use ECB mode.
Example
・Encrypt Key: 2fs5uhnjcnpxcpg9
→ Plain Text : 3280:99:20120201123050
→ Cipher Text : daa745f1901364c0bd42b9658db3db96336758cd34b2a576
* Please keep Cipher Text with 16 hexadecimal characters .
* Please generate Cipher Text without “salt”.
I need to write this in C#. Here's what I did, but it doesn't seem to be working:
string member_id = "3280";
string panelType = "99";
string RandomString = "20120201123050";
string encryptionKey = "2fs5uhnjcnpxcpg9";
string cryptstr = member_id + ":" + panelType + ":" + RandomString;
string plainText = cryptstr;
BlowFish b = new BlowFish(encryptionKey);
string cipherText = b.Encrypt_ECB("3280:99:20120201123050");
The result is not daa745f1901364c0bd42b9658db3db96336758cd34b2a576. Where did I go wrong?
Encrypt_ECB() so I assume its Schneier's class.
The ctor expects a hexadecimal string if one is passed, you need the overload for a byte array:
BlowFish b = new BlowFish(Encoding.UTF8.GetBytes(encryptionKey));
The output is still not correct, lets see what it really should be by decrypting their example:
string clear = b.Decrypt_ECB("daa745f1901364c0bd42b9658db3db96336758cd34b2a576");
gives us:
"3280:99:20120201123050\u0002\u0002"
Which is good but there are 2 0x2 bytes on the end, the N x 0xN is due to the PKCS padding. To get the match you need to pad the input:
// input to bytes
List<byte> clearBytes = new List<byte>(Encoding.UTF8.GetBytes("3280:99:20120201123050"));
// how many padding bytes?
int needPaddingBytes = 8 - (clearBytes.Count % 8);
// add them
clearBytes.AddRange(Enumerable.Repeat((byte)needPaddingBytes, needPaddingBytes));
// encrypt
byte[] cipherText = b.Encrypt_ECB(clearBytes.ToArray());
// to hex
string cipherTextHex = BitConverter.ToString(cipherText).Replace("-", "").ToLowerInvariant();
So im trying to encrypt data using C# DES
have the following code
static public string Encrypt(string _dataToEncrypt) {
SymmetricAlgorithm algorithm = DES.Create();
ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
byte[] inputbuffer = Encoding.Unicode.GetBytes(_dataToEncrypt);
byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
return Convert.ToBase64String(outputBuffer);
}
static public string Decrypt(string _dataToDecrypt) {
SymmetricAlgorithm algorithm = DES.Create();
ICryptoTransform transform = algorithm.CreateDecryptor(key, iv);
byte[] inputbuffer = Convert.FromBase64String(_dataToDecrypt); // Here is the problem.
byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
return Encoding.Unicode.GetString(outputBuffer);
}
And im getting an error System.FormatException: 'Invalid length for a Base-64 char array or string.'
It works when string has an even number of characters.
Is it even real to encrypt/decrypt data with an odd number of characters ?
DES, as well as AES does not have limit on what can be encrypted, the problem is elsewhere.
It looks like it is a Bas64 encoding problem given the line the error occurs on.
Perhaps trailing "=" characters were stripped from the Base64.
Information:
DES is a block based encryption algorithm, as such the input must be an exact multiple of the block size, 8-bytes for DES. When the input is not always an exact multiple padding must be added, the easiest way to to let the implementation do that for you by specifying padding, generally PKCS#5 for DES.
For SymmetricAlgorithm use Padding Property PKCS7, it is always best to fully specify everything and not rely on defaults.
algorithm.Padding = PaddingMode.PKCS7;
How can I decrypt HMAC SHA256 encrypted string?
private string CreateToken(string message, string secret)
{
secret = secret ?? "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
using (var hmacsha256 = new HMACSHA256(keyByte))
{
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
return Convert.ToBase64String(hashmessage);
}
}
How can I do reverse engineering if I have resultant string?
Thanks in advance.
A hash is a one-way function, by definition it is not reversible. What is it that you are trying to achieve?
If it's for something like password comparison then just hash the password you have and then compare the resulting hashes. Without any further context it's hard what to suggest.
HMACSHA256: It is a hash based Message authentication code.It is used to verify the message integrity on the insecure channel.It is a forward only hash algorithm, it can not be decrypted. It hashes the message based on the shared secret key which is known by both parties(sender and receiver).Sender uses the shared secret and compute the hash value from original data and send both the original data and hash value and then receiver re-computes the hash value from the original data. If both hash value matches it means no tempered in original data, if not matched it means tempered in original data for this scenario validation is failed.
I have this PHP script which we need to convert to C# to decode a result from an API post request, but I am experiencing issues with my C# implementation.
We get the result fine while running the PHP script which is XXXX-XXXX-XXXX but get different errors.
Values are:
encodedText = "U8Q+m2zpFMLa/3gYILHx5w=="
key = "examplesecret"
keyHash = "6315046b2c085bbeeab87c65"
Php Script:
<?php
$secret = 'examplesecret';
$encrypted_code = 'U8Q+m2zpFMLa/3gYILHx5w==';
// Base64
// Decode
$encrypted_code = base64_decode( $encrypted_code );
// Create decryption module
$cipher = mcrypt_module_open( 'tripledes', '', 'ecb', '' );
$keysize = mcrypt_enc_get_key_size( $cipher ); // = 24
// Generate key
$hash = md5( $secret );
$key = substr( $hash, 0, $keysize );
// Initialise decrypter
$iv = mcrypt_create_iv( mcrypt_enc_get_iv_size( $cipher ),
MCRYPT_DEV_RANDOM );
mcrypt_generic_init( $cipher, $key, $iv );
// Decrypt code
$decrypted = mdecrypt_generic( $cipher, $encrypted_code );
// Output decrypted code
echo $decrypted;
?>
C# Script
public static string Decrypt(string encodedText, string key)
{
TripleDESCryptoServiceProvider desCryptoProvider = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider hashMD5Provider = new MD5CryptoServiceProvider();
byte[] byteHash;
byte[] byteBuff;
byteHash = hashMD5Provider.ComputeHash(Encoding.UTF8.GetBytes(key));
desCryptoProvider.Key = byteHash;
desCryptoProvider.Padding = PaddingMode.None;
desCryptoProvider.Mode = CipherMode.ECB; //CBC, CFB
byteBuff = Convert.FromBase64String(encodedText);
var byteHex = BitConverter.ToString(byteBuff).Replace("-", " ");
string plaintext = Encoding.UTF8.GetString(desCryptoProvider.CreateDecryptor().TransformFinalBlock(byteHex, 0, byteHex.Length));
return plaintext;
}
A couple of things I see:
You derive $key via a substr in PHP; but just take the output of MD5 in C#, are they the same? (e.g. if PHP's value was a hex string, then the 16 bytes of MD5 are 32 characters, which gets trunctated to 24 characters, being a 12-byte (96-bit) value; in C# it's 16 bytes)
Speaking of the keys, if you're using PHP before 5.6, a deficient key was 0-padded (per the documentation of mcrypt_encrypt; C# won't do that for you. So that's another thing to check.
You have an IV in the PHP code, but ECB doesn't use an IV. That won't be causing your problem here, but it's less than ideal.
Of course, I should at this point warn that ECB is "too stable" and doesn't hide patterns in encrypted data, and doesn't hide that you're sending the same message again.
TransformFinalBlock takes bytes, but you seem to be giving it a string here. Since C# is a strongly typed language, this can't really be the code you're running.
You should avoid talking about the specific implementations of algorithms. TripleDES.Create() is preferred to new TripleDESCryptoServiceProvider(), MD5.Create() over new MD5CryptoServiceProvider(); and type the variables as just TripleDES and MD5.
The TripleDES object, the MD5 object, and the output of CreateDecryptor() are all IDisposable, so you should really wrap them in a using statement to be more efficient with your native resources.
The most likely culprit for your problem, though, is that you're not generating the same key in both languages.
I am new in C# wpf programming but I am trying to connect to MySQL database and to hash my password. Unfortunately while I was implementing the algorith I get error in this code:
byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length];
salt.CopyTo(plainTextWithSaltBytes, 0);
plainText.CopyTo(plainTextWithSaltBytes, salt.Length);
The error is:
Error: no overload for method 'Copy To' takes 2 arguments Exceptions: System.ArgumentNullException System.ArgumentOutOfRangeException
enter code here
By any chance do you know what is causing this errors and how to fix it?
You need to copy plainTextBytes, not plainText:
byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length];
salt.CopyTo(plainTextWithSaltBytes, 0);
plainTextBytes.CopyTo(plainTextWithSaltBytes, salt.Length);
If you need to do simple hash, this bit of code may encrypt your password:
String GetEncryptedPassword (String prmUser, String prmPassword)
{
// Concatenating the password and user name.
String encryptedPassword = prmUserName + prmPassword;
// Converting into the stream of bytes.
Byte[] passInBytes = Encoding.UTF8.GetBytes(encryptedPassword);
// Encrypting using SHA1 encryption algorithm.
passInBytes = SHA1.Create().ComputeHash(passInBytes);
// Formatting every byte into %03d to make a fixed length 60 string.
return passInBytes.Aggregate(String.Empty, (pass, iter) => pass += String.Format("{0:000}", iter));
}
This code will give you a nice encrypted hash of 60 characters. But remember that you can't regenerate your original username and password from the hash, because this is a one way algorithm. There are few more encryption algorithms in System.Security.Cryptography that you can use.